ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ThingsBoard仪表板状态设计实战:从遥测、RPC到告警联动

ThingsBoard仪表板状态设计实战:从遥测、RPC到告警联动 做物联网这几年ThingsBoard 算是我用得比较顺手的一套开源平台了。很多刚接触它的朋友第一件事往往不是搭数据采集也不是写规则引擎而是先在仪表板上把设备状态摆出来——因为领导要看客户也要看没有一块像样的状态面板项目连验收都过不了。今天就把 ThingsBoard 仪表板状态相关的整套做法捋一遍从数据怎么来、状态怎么算到组件怎么配、RPC 命令怎么下发再到我踩过的那些坑一次讲清楚。这篇文章主要面向两类人。一类是刚上手 ThingsBoard、正在搭第一个设备监控面板的开发者另一类是已经在用但被状态同步、RPC 下发、子设备联动折腾过的老用户。需要的基础知识不多会用 MQTT 工具、能看懂 JSON 就够了剩下的看完照着做就行。1. 先搞清楚仪表板上的状态到底指什么很多人在仪表板上折腾半天其实压根没想明白状态这个词包含几层意思。我见过最典型的需求是我要看到设备状态结果做出来只有一个绿灯红灯。实际上状态至少可以拆成三层设备在线状态、业务运行状态、告警状态。这三层数据来源不同、更新机制不同、展示方式也不同分开处理才不容易乱。1.1 设备在线状态谁告诉你设备还活着在线状态是 ThingsBoard 里最基础的一层。它不是一个你自己上报的字段而是平台根据设备活动情况自动推断出来的。设备通过 MQTT、HTTP 或者 CoAP 接入后只要上送了任意遥测、属性更新或者 RPC 响应平台都会刷新这个设备的最后活动时间。如果你在 ThingsBoard 的设备列表里打开一个设备详情能看到活跃、最近连接时间之类的信息底层就是靠最后活动时间算出来的。这里必须点破一个误区设备在线不等于设备一直连着 MQTT。平台不会因为你 TCP 没断开就永远认为你在线它是按超过多久没有活动就判定离线的逻辑来的这个时间在服务端配置里叫设备活动超时时间。默认情况下一个设备如果只是挂着连接、从来不发数据过一段时间就会被标记为离线。所以在实际项目里不要指望平台自动维护在线的准确性。设备侧必须做心跳最简单的做法是每隔 30 到 60 秒上送一个心跳遥测比如发送一个{hb: 1}平台一收到就会刷新活跃时间。这样仪表板上的在线状态才可信。1.2 业务状态遥测数据如何变成状态在线状态是基础但业务上要看的远不止这个。比如一台空压机客户要的不是在线/离线而是运行中、待机、故障、停机这些业务状态这就属于业务运行状态。业务状态一般有两种生成方式。第一种是设备自己算直接把结果上报比如{status: running}仪表板拿这个字段直接展示简单直接实时性最好。缺点是设备固件必须按你定义好的字段规范上报如果设备是老协议改不动这种方式就行不通。第二种是平台侧算通过规则链把原始遥测值转换成状态。比如温度传感器上报的是 5 分钟均值但监控面板要的是温度是否越限这个状态那就用规则链加一个脚本节点判断temperature 80就输出{overheated: true}再保存到最新的遥测或者属性里仪表板再绑定这个派生字段。大多数项目两种方式都会用。设备侧负责上送开关状态、档位这些实时状态平台侧负责兜底把越限、离线这些异常从原始数据里挖出来。这样状态展示既有实时性又有可靠性不会出现设备坏了自己上报一个正常的尴尬情况。1.3 状态数据在 ThingsBoard 里的存放位置这里必须先搞清楚三个概念遥测Telemetry、属性Attribute和最新遥测Latest Telemetry。遇到过很多项目状态数据一会儿放属性一会儿放遥测结果不同组件读不到对不上排查起来非常难受。数据类别特点适合存放的状态仪表板组件取值方式遥测 Telemetry时序数据带时间戳可做历史查询温度、转速、运行状态等随时间变化的值最新遥测Latest telemetry客户端属性设备上报的键值不按时间序列存储固件版本、安装位置、设备配置客户端属性共享属性平台端配置设备可读取阈值、运行参数、平台下发的配置项共享属性服务器属性主要由平台端维护设备活跃状态、最后连接时间服务器属性判断标准就一条这个状态值需不需要看历史变化需要就放遥测只是看当前值放属性反而更轻量。不过要注意遥测存的是时间序列数据量大了要规划保留策略别拿它当属性存一份又当遥测存一份后面存储会很难受。2. 仪表板状态设计的整体思路实操之前先讲设计思路。很多新手一上来就拖组件做完发现东一块西一块自己也看不懂。我现在的习惯是在创建仪表板之前先画一版草图把要展示的状态分层、分组、定数据源再动手配。2.1 状态面板的分层设计状态面板我一般分成三层每层对应不同的组件类型数据源也各不相关。设备层展示在线/离线、信号强度、最后通信时间。这一层负责回答设备还在不在通常用顶部的状态卡片队列或者实体表来展示。数据源优先绑定服务器属性里的 active、lastConnected 字段。业务层展示每个设备的核心指标和运行状态。比如空压机是运行中还是待机门锁是开启还是关闭。这一层用状态指示器、卡片来展示数据源绑定设备上送的业务状态字段一般是遥测。告警层展示当前告警、未处理事件、需要人工介入的动作。这一层用告警组件、告警列表来展示。数据源是平台侧创建的告警实体不是设备遥测。这样分完之后每一层的数据链路是独立的排查的时候切分界面就知道问题出在设备侧还是平台规则链还是仪表板配置上。2.2 别名状态组件的数据源基石仪表板上的组件必须绑定数据源而数据源最常用的方式就是实体别名Entity Alias。别名的作用是为仪表板上的组件建立一个设备/资产集合的引用这样组件读取的是别名背后动态变化的数据而不是写死的设备 ID。别名有几种常用类型单实体、实体列表、实体类型、由关系派生。单实体适合做单台设备的详情面板实体类型适合做同一类设备的批量监控关系派生适合从某个资产比如一个站房下面取设备做有层级的设备组。我强烈建议所有组件都走别名哪怕你只有一个设备。因为后面设备换新、加设备、改设备类型都只需要改别名对应的过滤条件组件的绑定关系不会断。项目上线后最怕的就是设备 ID 变了面板全部空白别名机制就是为了避免这个灾难。2.3 状态颜色与图标策略状态展示最直观的还是颜色和图标。一个状态卡片如果是绿的用户就知道正常变红了用户就知道要处理。但颜色的使用一定要统一规范不然一个面板里黄绿红混着用第二天客户就打电话来问你们哪里爆了。我这边通常定这么一套规范正常/在线/运行中绿色待机/暂停/低风险黄色故障/离线/越限红色未知/未上报灰色这套规范不只用在状态指示器上还用在整个平台的告警严重程度标记里做到全局一致。在 ThingsBoard 的状态组件里设置样式映射时按规范选颜色不要临时起意换个浅红深红的省得后面自己看都迷糊。3. 实操从数据上送到状态卡片落地设计想清楚了接下来就是动手。我从一个最简单的 MQTT 设备开始把完整链路走一遍设备上送数据 - 创建仪表板 - 配置别名 - 绑定状态组件 - 下发 RPC 命令 - 状态联动刷新。3.1 设备接入状态字段怎么上送设备接入 ThingsBoard 最常用的是 MQTT。设备在平台里创建之后会拿到一个接入凭据通常是一个 access token。设备用这个 token 连接 MQTT 服务的 1883 端口主题路径就是v1/devices/me/telemetry。用命令行工具模拟设备上送遥测命令长这样mosquitto_pub -h 127.0.0.1 -p 1883 -t v1/devices/me/telemetry -u ACCESS_TOKEN -m {temperature: 36.5, status: running, mode: 2}这里上送了一个遥测包含三个 keytemperature、status、mode。其中 status 这个字段就是仪表板状态卡片的直接数据来源。设备侧开发时要保证 status 字段的值规范统一比如running、stopped、fault三种取值不要一会儿叫 run 一会儿叫 running不然仪表板样式映射会失效。如果只是想上送配置类属性比如设备位置、固件版本可以走属性主题mosquitto_pub -h 127.0.0.1 -p 1883 -t v1/devices/me/attributes -u ACCESS_TOKEN -m {position: line-1, fw_version: 1.0.3}这里面有个容易踩的坑上送遥测和上送属性虽然命令差不多但数据归宿完全不同。遥测会进入时序数据库占存储属性存的是最新值不按时间堆积。所以心跳这类高频且不需要历史的数据尽量走属性主题别和业务遥测混在一起。3.2 仪表板与实体别名配置在 ThingsBoard 左侧菜单找到 Dashboards点加号创建新仪表板起个名字比如设备状态总览。创建完点 Open Dashboard进入仪表板后再点右下角铅笔图标进入编辑模式。编辑模式下先配实体别名。入口在 Dashboard 编辑界面的 Entity Aliases 菜单。点击 Add Alias填写别名名称比如全部设备然后在 Filter Type 里选择 Entity TypeEntity Type 选 Device再按设备 Profile 过滤出你要的那批设备。配置完保存之后别名在组件的数据源里就可以被选中了。注意别名是一个仪表板层面的引用多个组件可以共用同一个别名。比如实体表和状态卡片都可以用全部设备这个别名这样你只需要维护一个过滤条件。3.3 常用状态组件及关键参数ThingsBoard 自带组件库里有几个组件做状态展示非常好用。我把它们和适用场景整理成了表配置的时候直接参考。组件类型适合场景数据源类型关键配置项State Indicator单个设备状态指示Latest telemetry / AttributeValue 字段、样式映射颜色/图标Cards 卡片设备关键指标总览Latest telemetry / Attribute字段映射、刷新周期Entity Table 实体表设备列表状态总览Entity 类型别名列配置、单元格样式函数Timeseries Graph 图表状态/指标趋势分析Timeseries遥测 key、时间窗口、聚合方式State Indicator 是最常用的状态卡片。拖入组件后在编辑界面配置 Data source选中设备别名然后设置键值为status。接下来在样式设置里做映射比如running对应绿色圆形图标stopped对应灰色方块图标fault对应红色警告图标一个关键细节如果状态字段不是设备直接上送的遥测而是平台规则链算出来的、存放在共享属性里的值那数据源类型就要选 Shared attribute别选 Latest telemetry。这里选错了卡片就永远读不到值。还有一个特别容易忽略的点刷新间隔。仪表板组件默认不是每秒钟都在拉数据状态卡片可能停留在你上次打开页面的瞬间。在组件的高级设置里可以设置刷新周期我一般状态卡片设 5 秒图表设 30 秒。设得太频繁会给平台造成不必要的压力设得太长状态又失去实时性。3.4 RPC 命令下发与状态闭环状态面板不能只看还要能控。这就涉及到热词里的thingsboard 使用下发命令和thingsboard 下发 rpc 子设备下发。先讲单个设备怎么通过 RPC 下发命令。原理其实很清晰仪表板上的按钮触发 JavaScript 动作调用api.sendRpcRequest发送 RPC 请求平台服务端收到后把命令推给设备设备通过订阅主题v1/devices/me/rpc/request/收到设备处理完把结果发到v1/devices/me/rpc/response/requestId平台把响应返回给仪表板设备端订阅 RPC 请求主题命令行模拟是这样mosquitto_sub -h 127.0.0.1 -p 1883 -t v1/devices/me/rpc/request/ -u ACCESS_TOKEN -v收到请求后设备执行操作再发布响应mosquitto_pub -h 127.0.0.1 -p 1883 -t v1/devices/me/rpc/response/1 -u ACCESS_TOKEN -m {success: true, status: running}这里的关键是设备在响应 RPC 的同时最好立刻把最新的状态以遥测上送比如{status: running}。这样仪表板上的状态卡片会随 RPC 命令下发后自动刷新形成下发命令 - 设备执行 - 状态反馈的闭环。如果你只做了 RPC 响应但没有遥测上送面板上的状态是不会变的。仪表板上的按钮配置也不复杂。编辑仪表板新建一个图片按钮或者 Switch 组件在 Action 里选择 RPC 命令填写方法名和参数。{ method: setMode, params: { mode: start }, timeout: 10000 }这里的 method 是自定义的设备端解析 JSON 时按这个字段分发到对应处理逻辑。timeout 我建议一定设置默认不设超时设备离线时 RPC 会一直挂着用户点按钮半天没反应体验很差。设了 10 秒超时前端至少能提示你请求超时。实际项目中我还会做一个两段式反馈RPC 响应返回 success 后先提示命令已送达等最新遥测里的状态值真正变化后再提示状态已更新。因为 RPC 响应只能证明命令送达并得到处理不等于设备的物理状态已经变化这两者之间通常有个执行延时。如果直接把 RPC 响应当成状态变更很容易被客户投诉我点了启动界面显示成功了但设备没转。4. 进阶场景子设备状态与告警联动设备数量少的时候单个设备管理就够了。但工业项目里一个网关底下挂几十个 Modbus 子设备是常态。这种场景下子设备状态怎么上仪表板是一个很讲究的工程问题。4.1 网关场景下子设备状态怎么来网关接入时ThingsBoard 里的设备模型是网关 子设备两层。网关是一个真实的设备子设备是逻辑设备并不直接建立 MQTT 长连接。子设备的数据全部通过网关代理上送使用网关专属主题上送子设备遥测v1/gateway/telemetry上送子设备属性v1/gateway/attributes接收下发到子设备的 RPCv1/gateway/rpc子设备状态在仪表板上的展示和普通设备有个本质区别平台不会自动判断子设备在线与否它只能看到网关的活动。如果网关不把子设备状态上报上来仪表板对子设备就是一片空白。所以项目里我一般让网关侧做两件事。第一定期上报每个子设备的状态比如{ subDevice1: { status: online, last_seen: 1720000000000 }, subDevice2: { status: offline, last_seen: 1719990000000 } }第二网关自己维护一份子设备维护表知道哪些子设备注册过、最近一次通信是什么时候超过某个阈值就标记离线。这样仪表板上的子设备状态才有可信度。在仪表板组件里要对网关上报的数据做解析。比如用一个函数脚本把这串 JSON 映射成每个子设备的状态字段再绑定到实体表或者状态卡片上。如果直接用原始字段组件只会显示一长串 JSON客户看不懂。4.2 告警状态与仪表板联动状态面板不能只显示正常状态。我更愿意说状态面板的核心价值是把需要人处理的事情暴露出来这件事要交给告警。ThingsBoard 的规则链可以配置告警逻辑。一条比较典型的告警规则链是这样从设备遥测消息里解析temperature通过脚本节点判断temperature 80返回 true调用 Create Alarm 节点创建一条类型为温度越限的告警设置严重程度为 CRITICAL告警自动关联到当前设备仪表板上加一个告警组件绑定设备别名就可以展示当前告警数量、最新告警详情。状态卡片也可以根据是否有未处理告警来换颜色正常状态是绿色有未处理告警就显示红色。联动这块有个小技巧规则链里更新状态字段时把告警是否存在也考虑进去。比如脚本里判断有未确认告警时status 强制显示为 abnormal这比前端组件自己猜要可靠得多。前端只负责展示状态计算逻辑统一收口到规则链里别散落在各个组件的 JS 函数里。4.3 关于 JetLinks 的一点对比热词里有 jetlinks vs thingsboard 的对比这里简单聊几句我的看法。JetLinks 是国产物联网平台在协议接入、设备管理、本地化支持方面做得不错如果项目对国产化环境、本地二次开发、复杂协议适配有硬性要求JetLinks 值得考虑。但单说仪表板生态和状态展示这块ThingsBoard 的组件库、文档资源、社区案例都更丰富做状态面板的周期明显更短。选型不是非黑即白核心还是看团队熟悉哪套、项目约束是什么。我自己在标准 IoT 监控场景里偏好 ThingsBoard但遇到需要深度对接国内硬件私有协议的场景也会认真评估 JetLinks。这里不展开说太多一句话总结仪表板能力只是选型维度之一协议层和数据层的匹配度往往更重要。5. 常见问题与排查技巧这一节是重点我把项目中实际遇到过的、社区里高频出现的问题做一次集中排查。状态面板出问题大多数情况不是仪表板本身而是数据链路某一段断了。5.1 设备在线却显示离线的排查这是被问得最多的一个问题设备明明在跑数据也在发仪表板却显示离线。原因前面提过平台判断在线依赖的是最后活动时间而设备可能根本没有持续上报数据。排查步骤打开设备详情页确认最后活动时间是否还在更新如果停止更新检查设备侧是否做了心跳上报如果没有心跳补上定时上报频率建议 30 到 60 秒确认服务端 activity timeout 配置是否过短需要注意的是心跳数据如果走遥测主题会产生大量时序数据。推荐做法是走属性主题上报或使用专门的轻量字段别把心跳和业务遥测混在一起。5.2 状态卡片不刷新状态卡片有数据但一直不刷新是最容易排查的一类。顺序如下确认最新遥测里有没有这个字段在设备详情页的 Latest Telemetry 栏目里找没有值说明设备没上送对字段名检查固件或脚本里的 key 是否和组件绑定的一致有值但卡片不动检查组件刷新间隔是否太长刷新间隔没问题退出仪表板编辑模式重新进入排除编辑态缓存还有一个常见原因组件数据源类型选错了。比如字段存在遥测里组件绑定了客户端属性那当然读不到。排查的时候先看清字段类型再核对组件的数据源配置。5.3 别名与数据源配置错误别名配置问题是新手重灾区。常见情况单实体别名选错了实体类型绑定了资产但目标是设备实体列表过滤里设备 Profile 选错导致列表为空关系派生筛选方向反了本来要向资产下面取设备配置成了向设备上面找资产排查方式很简单在别名编辑界面右侧一般有实体预览功能能实时看到当前别名查出来的实体数量。先确认这里能不能查出设备再回仪表板判断组件是不是绑定错了别名。教训是不要在多个组件里用 JSON 硬编码设备 ID统一走别名管理省很多事。5.4 RPC 下发失败与状态不同步RPC 下发失败最常遇到的是设备端没有订阅正确的主题。普通设备订阅v1/devices/me/rpc/request/网关场景下平台把命令发到v1/gateway/rpc由网关负责转发给子设备而不是直接发给子设备。子设备 RPC 下发还有一个坑平台里的子设备注册信息和网关内部的设备映射不匹配。比如平台知道子设备 A但网关没维护 A 的注册信息命令到网关就断了。遇到这种情况优先检查网关的设备映射表。状态不同步的问题核心原因往往是设备执行完命令后没有上报新状态。记住前面说的那条铁律RPC 响应只证明命令已送达并处理不等于设备状态已变更。状态是否变更必须以最新遥测为准。所以设备固件里一定要在动作执行完成后主动上送一次状态遥测别等着平台去猜。5.5 设备离线状态下命令怎么处理还想多说一条RPC 下发时设备恰好离线怎么办。ThingsBoard 的 RPC 有持久化机制部分 RPC 可以让离线设备在重新上线后收到命令。但实际项目中我很少依赖这个特性因为离线期间的状态变化很可能已经让这条命令失去意义。更稳妥的做法是前端在下发前先查询设备 active 状态离线就直接提示设备离线无法执行命令设备端也做状态同步上线后拉取一次最新期望状态而不是依赖平台补发命令。这样既省心又避免命令堆积。6. 写在最后仪表板背后是链路设计做状态仪表板做久了我最大的体会是仪表板只是最上面那一层皮真正决定它好不好用的是数据从设备端到平台再到组件这条链路设计得是否清晰。设备侧字段规范、平台侧状态计算、仪表板组件映射这三段缺一不可。分段排查的能力比记住某一个组件的配置参数更重要。我自己的习惯是每个项目开工前先定义一份状态字段规范清单把所有的状态字段名、取值、含义、数据存放位置写清楚然后让设备端开发、规则链配置、仪表板设计共用这一份文档。这样做下来后期维护会轻松很多也不会出现设备端改了字段名、仪表板悄悄变灰的情况。最后再分享一个小技巧如果你第一次做 ThingsBoard 仪表板不要追求一次做完。先搭一个最小可用的单设备状态卡片把完整链路跑通再慢慢丰富成多设备总览、告警联动、RPC 控制。链路通了剩下的就是拼图链路不通组件拖得再多也是白搭。这套思路我在多个项目里验证过是真的能少走弯路。
返回列表