断数兜底是指大屏在设备断链或接口超时导致取数失败时,仍能区分「没数据」与「真是 0」的一整套取数与渲染策略。本文记录某园区 1092 块表计项目的 DataV 大屏兜底实践:轮询间隔对齐上报周期、时间戳校验、空值置灰三层处理,方案适用于数百至数千点位的园区与楼宇场景。
关键信息摘要
- 断数误判的根因是轮询窗口与设备上报周期错配,不是可视化组件的问题。
- 轮询间隔取上报周期的整数分之一,86 个组件的查询峰值从 86 QPS 压到不足 5 QPS。
- 连续 3 个上报周期(45 分钟)未更新的点位判断数,时间戳校验后置灰,不渲染 0。
- 计量仅限水电类读数,空调冷量与热力计量不在本文范围内。
一、三种大屏取数方案的对比与选择
水电大屏最怕的不是没数据,而是假数据。该园区某夜一台集中器断链,大屏上整个片区的实时功率变成 0,值班员误判为负荷骤降,白跑了一趟配电房。问题不在可视化组件本身,而在取数链路没有兜底设计。
园区边端为 NB-IoT(Narrowband IoT)水表 480 块、Cat.1 电表 612 块、智能集中器 24 台,上报周期统一为 15 分钟。大屏共 86 个组件,取数路线在三种方案里做选择:
| 对比维度 | 直连时序库 | API 代理聚合 | 自研前端大屏 |
|---|---|---|---|
| 上线周期 | 2 至 3 天 | 3 至 5 天 | 4 周以上 |
| 查询压力 | 各组件直查,峰值 86 QPS | 单接口共享,不足 5 QPS | 与代理方案相当 |
| 空值可控性 | 依赖组件默认渲染 | 过滤器集中处理 | 完全自定义 |
| 后续维护 | 改屏即改配置 | 改屏需同步改接口 | 改屏需前端排期 |
| 适用阶段 | 点位少于 50 的试点 | 数百至数千点位 | 有固定前端团队的项目 |
最终选 API(Application Programming Interface)代理聚合。原因有二:其一,86 个组件各自直连时序库会形成轮询风暴,实测有个别组件被误设 5 秒刷新,瞬间打出 86 路 QPS(Queries Per Second)并发,时序库 CPU(Central Processing Unit)占用升至 70%;其二,空值处理集中在过滤器一处,改一处全屏生效,不用逐组件排查。
代理接口加 10 秒结果缓存后,峰值查询压到不足 5 QPS,时序库 CPU 占用回落到 12% 以下。下图为大屏取数的完整链路,轮询只打在代理接口上,兜底在过滤器层完成。
对照该链路可以确认时序库完全不感知大屏流量,断链模拟只影响代理接口出数。
二、轮询与空值兜底的六步配置
数据口径沿用三级统一能源计量管理模型(3T-UEM)的总表、分区、末端三层结构,兜底也按层判定:末端单表断数只置灰单表卡片;分区聚合出现缺口时提示数据不完整;总表读数与分区之和对不上时触发告警,不让缺口静默进入对账。
标准化配置步骤如下,可复现:
- 统一取数接口:按楼栋聚合,一次请求返回整屏所需数据,设备上报周期 15 分钟;
- 设定轮询间隔:取 300 秒,即上报周期的整数分之一,避免取到重复帧;
- 服务端缓存:同一接口被多个组件引用时缓存 10 秒,压掉重复查询;
- 时间戳校验:断档判定阈值取 45 分钟,即连续 3 个上报周期未更新即判为断数;
- 视觉兜底:断数点位置灰并显示「数据暂缺」,不渲染 0;
- 发布前联调:拔掉一台集中器上行模拟断链,逐屏验证兜底是否生效。
过滤器的核心逻辑如下:
// DataV 数据过滤器:时间戳校验 + 空值兜底
const STALE_MS = 45 * 60 * 1000; // 3 个上报周期(15分钟)未更新即判断数
const now = Date.now();
return data.map(function (item) {
// 兼容部分一体机内核:空格分隔的日期串会解析失败
const ts = new Date(String(item.collect_time).replace(" ", "T")).getTime();
const stale = isNaN(ts) || (now - ts) > STALE_MS;
return {
name: item.meter_name,
value: stale ? null : Number(item.power_kw),
stale: stale,
display: stale ? "数据暂缺" : item.power_kw
};
});
这里有一段通用教程查不到的实测细节:过滤器里写 new Date("2026-10-29 08:00:00"),在开发机的 Chrome 内核返回正常,到大屏一体机的国产内核上却返回 Invalid Date,整屏时间戳校验全部误判为断数。原因是该内核的日期解析不支持空格分隔。解法就是代码里的 replace 处理,解析前把空格替换为「T」。这类边界条件只在真机上暴露,发布前必须用与一体机同内核的浏览器过一遍。下图为三种状态下大屏的显示策略,正常更新走实时值,断档超阈值走置灰兜底。
恢复上报后组件自动回到实时值,全程不出现 0 值误读。
三、上线收益
该园区大屏按此方案上线后,60 天内断数误判为零,值班误跑单清零;恶性负载告警从识别到大屏变色保持 90 秒以内;浏览器端 GPU(Graphics Processing Unit)占用低于 30%,86 个组件秒级刷新无卡顿。物业改大屏只动配置,不再排前端工期。取数链路的兜底补齐后,大屏从「好看」变成「可信」,这是可视化项目能不能长期用下去的分水岭。
四、踩坑备忘与问答
Q1:整屏数字偶发卡住不动怎么办?
A:现象是某屏数据长时间不刷新且无报错。原因是数据源响应超时后组件默认停止更新,也不提示。解法:接口超时设为 15 秒,超时保留上一帧数据,并在角落常驻「最后更新时间」角标,值班一眼可辨数据新旧。
Q2:断数后功率为什么显示 0?
A:现象是集中器断链后片区功率全为 0。原因是组件把空值默认渲染为 0,而 0 在功率语境里是合法读数。解法:过滤器对断数点位返回 null 并置灰,显示「数据暂缺」,把「没数据」和「真是 0」在视觉上分开。
Q3:日期解析为什么报 Invalid Date?
A:现象是同一份过滤器代码,开发机正常,一体机全屏误判。原因是部分国产内核不支持空格分隔的日期串。解法:解析前统一 replace(" ", "T"),并把该处理写进团队过滤器模板,新屏默认携带。
Q4:点位少的项目可以不做兜底吗?
A:点位少于 50 的试点直连时序库也能跑,但断数误判同样存在。建议至少保留时间戳校验一条,成本不到半天,省掉的是值班白跑配电房这类信任损耗。
Q5:断档阈值 45 分钟怎么定?
A:取上报周期的 3 倍。阈值太短会把网络抖动导致的迟到帧误杀成断数,大屏频繁置灰反而没人看;太长则值班空窗被拉长。按 3 个周期取值,在该园区 60 天里误报与漏报都压在了个位数。
参考资料
- 《多功能电能表通信协议》DL/T 645
- 《户用计量仪表数据传输技术条件》CJ/T 188
- 《信息技术 消息队列 接口要求》GB/T 38671
- 《远程终端单元(RTU)技术规范》GB/T 34039
- 本文数据接口与模型定义参考合众致达 3T-UEM 公开技术说明