ThingsBoard 的仪表板状态,玩明白了才是真入门。不少刚接触 ThingsBoard 的朋友,第一眼看到那套可拖拽的 Dashboard 界面会觉得挺惊艳,但真正落地到项目里,发现设备数据上来了、图表也配好了,反而开始犯迷糊:设备明明在线,状态显示却不对;RPC 指令发出去了,仪表板上按按钮没反馈;甚至同一个设备,在不同仪表板里状态还不一致。这些问题我早期做物联网项目时全都踩过,后来把实体、遥测、属性、RPC 回执这一条链路彻底理顺,才总算把“仪表板状态”这几个字吃透。
这篇文章不打算做功能介绍,而是想从一个实际落地者的角度,把 ThingsBoard 仪表板状态相关的底层逻辑、配置技巧、排查思路,以及和 JetLinks 这类同类平台的对比体验一次性讲清楚。不管你是刚搭好环境准备做设备接入,还是已经被仪表板状态折腾了好几天的开发者,这篇文章都值得你花十几分钟过一遍。
1. 内容整体设计与思路拆解
1.1 仪表板状态到底是什么
先说一个容易被忽略的事实:ThingsBoard 里的“仪表板状态”(Dashboard State)并不是一个简单的“在线/离线”开关,而是一整套由实体(Entity)、遥测(Telemetry)、属性(Attribute)和别名(Alias)组合而成的数据呈现逻辑。你在仪表板上看到的每一个图表、每一个卡片、每一个设备状态灯,本质上都是在查询某个实体的某个数据键值,然后通过可视化组件把它们渲染出来。
打个比方,如果 ThingsBoard 是一间监控室,那仪表板就是监控室里的屏幕墙,而“状态”则是屏幕墙上每一个画面背后的信号源。信号源不通,屏幕墙再漂亮也没用。很多人把精力花在美化仪表板组件上,却忽略了信号源——也就是实体别名、键名映射、时序数据是否对齐——这才是仪表板状态各种问题的根源。
从整体设计思路上看,官方把“仪表板状态”分成了几个层次:
- 根状态(Root State):仪表板加载后默认展示的状态,相当于首页。
- 子状态(Child State):通过组件交互(如点击表格行)可以切换到的状态,常用于主从联动。
- 临时状态(Temporary State):不保存到仪表板配置里的状态,只在当前会话中生效。
真正干活的时候,你还要叠加“状态类型”的概念。ThingsBoard 支持四种状态类型:实体(Entity)、默认(Default)、视图(View)、流程(Flow)。每一种状态都对应一套实体别名和数据绑定机制。早期版本的仪表板很容易让人一头雾水,就是因为这几种状态混在一起,很难分清到底哪个组件在驱动哪个数据源。
1.2 为什么状态会“看起来不对”
我见过太多人问:设备明明上报数据了,仪表板上的状态却不更新。这里头的坑通常不是 ThingsBoard 本身的问题,而是没有搞清楚数据在平台里的流转路径。数据流的完整链路是:设备端 → 网关/传输层 → TB 规则引擎 → 保存遥测或属性 → 仪表板别名查询 → 组件渲染。
任何一个环节断了,状态就“不对”。最常见的断点有三个:
第一,规则引擎没有把消息保存到正确的实体上。设备上报的数据进到 TB 后,默认会走 Root Chain,如果你的规则链里没有配置“Save Timeseries”节点,或者节点指定的实体键名跟仪表板里的键名不一致,那数据就相当于丢了。
第二,仪表板别名(Alias)绑定的实体范围有问题。比如你创建了多个设备,但别名只选了单个设备,或者选了设备分组但类型不对,仪表板自然会显示“No data”或者空白。
第三,前端时序查询的时间窗和实际数据的时间戳不一致。这个问题最容易让人抓狂,仪表板组件默认查询最近 15 分钟的数据,如果你的设备是按小时上报的,你在仪表板上看到的自然就是一条直线。
理解了这条链路,后面所有配置和排查才有了支点。别急着改仪表板,先把数据流理清楚,状态问题就解决了一大半。
1.3 方案选型:自研还是用现成平台
围绕“ThingsBoard 仪表板状态”这个主题,很多团队其实还面对一个选择题:是直接把 ThingsBoard 拿来用,还是在它基础上做二次开发,以及要不要考虑 JetLinks 这类国内平台。
我在项目中做过一次对比,结论是:如果你要把仪表板状态做成对外展示的运营大屏,还要频繁调整布局和交互,ThingsBoard 的灵活度明显更高。它默认提供的 Dashboard 组件虽然不算特别炫酷,但胜在数据绑定逻辑非常清晰,每个组件的数据源都是显式配置的,排错方便。JetLinks 在某些中国本地化场景里接入协议更省事,比如它自带的 MQTT、HTTP 协议网关配置更贴近国内开发者的习惯,但它的仪表板能力相对弱一些,更多是作为设备管理平台来用。
如果团队里没有专职前端,又需要炫酷大屏展示,JetLinks 的简易配置可能更快见效;但如果你要的是长期可控、数据展示维度深、主从联动复杂的状态仪表板,ThingsBoard 的实体绑定和状态管理机制会更合手。后面我会用一整节单独聊 JetLinks 和 ThingsBoard 的对比,这里先不展开。
2. 核心细节解析与实操要点
2.1 实体别名:仪表板状态的“数据管道”
所有仪表板组件的背后都是实体别名(Entity Alias)。你创建一个图表组件时,第一步不是选图表类型,而是选“数据源”,数据源里最关键的就是实体别名。
实体别名有几种类型,最常用的是:
- 单实体(Single Entity):直接绑定一个设备、资产或客户。
- 实体列表(Entity List):绑定满足条件的多个实体。
- 实体分组(Entity Group):绑定一个设备分组或资产分组。
- 实体类型(Entity Type):按类型,比如所有设备。
踩坑提醒:如果你在仪表板里看到“No entities found”,先回去检查别名范围。我记得有一次做项目,把设备分组换成了资产类型,结果仪表板全空白,折腾了半个小时才发现是别名类型选错了。
实体别名确定之后,再往下就是数据键(Key)。这个 Key 可不是随便写的,它必须和设备上报遥测里的键名完全一致。我见过不少人在设备端上报的是temperature,结果仪表板配置里写成了temp,那自然没数据。这个问题很基础,但实际排查时出现的频率相当高。
2.2 状态字段:在线离线是怎么算出来的
有人认为设备在仪表板上的“在线/离线”状态是设备心跳上报的,其实不是。ThingsBoard 的在线离线状态,本质上是平台侧基于设备会话(Session)维护的。设备接入过 TB(比如连上 MQTT 并成功鉴权),TB 就会在内存里维护这个设备的会话。设备主动断开、或者长时间没有收发消息导致会话超时,这个状态就会翻转。
这在仪表板上的体现是:active 字段为 true 代表设备在线。很多自定义组件或卡片,会通过订阅active这个属性值来做状态灯显示。
实操要点:
- 如果你用 MQTT 接入,设备正常连接成功后,你在设备详情页能看到设备状态变为“Active”。
- 物联网设备不可能一直保持连接,所以大概率你会用到“设备离线判定”。默认情况下,TB 的会话超时时间是 10 秒,但你需要区分设备的持久会话(persistent session)还是非持久会话。非持久会话断开后,服务端会相对更快地标记离线。
要注意的是,设备端程序里如果异常退出,没有发 DISCONNECT 包,服务端只能靠超时机制判定离线。这个超时受 MQTT broker 的 keepalive 参数影响,调整不合适,仪表板的状态刷新就会滞后。
2.3 订阅属性与遥测的差异
仪表板上要展示状态,要么读属性(Attribute),要么读遥测(Telemetry),两者在语义上有着明确分工:
- 属性(Attribute)通常是静态或低频信息,比如设备的序列号、固件版本、安装位置、工作模式。客户端属性、服务端属性、共享属性三种类型,用途各异。
- 遥测(Telemetry)是时序数据,比如温度、湿度、电压、功耗,带时间戳,会自动存入 Cassandra 或 PostgreSQL(按部署方式而定)。
做仪表板状态配置时,建议遵循一个原则:状态类信号(比如开关、运行模式、告警标识)用属性来存,因为它不参与时序分析,每次变化都记历史反而占空间;而采样类信号(比如温度曲线、电流波动)用遥测存,方便做聚合展示和告警规则。
这里有个我早期容易混淆的地方:在仪表板的“最新遥测”组件里,其实是可以同时查属性和遥测的。但如果你把高频率变化的属性(比如每秒钟变化的信号强度)存成属性,每次写入都要触发一次属性更新事件,规则链和订阅端都得跟着处理,性能容易出瓶颈。所以该用遥测的地方还是用遥测,别为了省事全塞到属性里。
2.4 状态刷新机制与前端时间窗口
ThingsBoard 仪表板的前端组件默认采用固定时间窗口查询,通常是“最近 15 分钟”。你可以在组件的高级设置里调整时间窗口,甚至可以设置成“实时模式”,让它持续订阅最近的数据。
但这背后容易忽略一个点:仪表板组件的自动刷新时间和查询窗口是两个概念。自动刷新是指前端每隔多少秒去拉一次数据;查询窗口则是指拉取哪个时间段的数据。两者配置得不匹配,就会出现一种典型症状:图表显示有数据,但信息永远延迟,或者数据只看得到一小段。
我自己的习惯是:
- 对需要实时监控的状态类组件,把自动刷新调到 5 秒,时间窗口选“最近 5 分钟”。
- 对趋势类图表,自动刷新调到 30 秒,时间窗口选“最近 1 小时”或者“最近 24 小时”。
- 对不常变化的属性值展示,自动刷新调到 60 秒就够了。
这个配置没有绝对标准,但思路要明确:状态数据的实时性来自刷新频率与窗口的配合,目标不是让所有组件都高频刷新,而是让用户看到的状态和实际设备状态保持合理偏差。
3. 实操过程与核心环节实现
3.1 如何搭一个带设备状态的仪表板
接下来我用一个简化但完整的具体场景来做演示,目标读者是第一次完整配置仪表板状态的人。
假设你的场景是:监控 20 台温控设备,每台设备会上报temperature、humidity、power三个遥测键,同时会上报一个workMode属性(自动/手动),你要在仪表板上展示每台设备的在线状态、最新温度、当前工作模式,并支持下发 RPC 指令控制设备的开关。
步骤拆解如下:
- 创建设备并接入。在“实体”菜单里创建设备,记录设备凭证(Access Token),然后在设备端用 MQTT 协议接入,上报
temperature、humidity、power三个遥测数据,并上报属性workMode。 - 确认数据进来。切到“最新遥测”页面,能看到三个键值实时变化,同时设备详情里能看到设备状态为“Active”。这一步是检验数据链路是否通的关键。
- 创建仪表板。在“仪表板”菜单里新建一个 Dashboard,命名为“温控设备监控”。
- 添加实体别名。在仪表板编辑界面,点“实体别名”按钮,新增两个别名:
all_temp_devices:类型选“实体列表”,筛选条件选“设备类型 = 温控设备”。single_temp_device:类型选“单实体”,绑定你刚才创建的那台设备。
- 添加状态卡片组件。拖入一个“卡片”组件,数据源选
all_temp_devices,数据键分别配置为temperature、humidity、power,高级设置里把自动刷新改成 5 秒,时间窗改成最近 5 分钟。 - 添加状态灯逻辑。如果你想做一个一眼看出设备在线与否的灯,可以用“状态开关”组件或者自定义卡片,并订阅
active属性。这个属性是平台自动维护的,设备成功连接后就是 true,断开后按 keepalive 超时变成 false。 - 配置 RPC 按钮。这一步后面单独讲,先留个位置。
配置完成后,保存仪表板,打开后应该能看到 20 台设备的数据。如果没有数据,按上面说过的排查链路:先看设备“最新遥测”是否有数据,再看别名筛选是否命中,最后看组件键名是否匹配。
3.2 下发 RPC 指令:让仪表板状态“活”起来
有朋友搜索了“thingsboard 使用下发命令”“thingsboard 下发rpc 子设备下发”这类关键词,说明仪表板状态展示并不是终点,远程控制才是常态。ThingsBoard 的 RPC 能力在仪表板上通常表现为两种形式:一种是组件自带的“RPC 按钮”,另一种是通过服务端规则链的“RPC 请求”节点下发指令。
组件层面,ThingsBoard 提供了“RPC 按钮”组件。操作方法如下:
- 在你的仪表板上拖入一个“按钮”组件,数据源绑定单台设备。
- 在配置里写 RPC 方法名,比如
setPower。 - 添加参数,比如
{"value": "ON"}。 - 在设备端实现一个 MQTT RPC 订阅处理逻辑,设备收到这个指令后,执行动作,并返回响应。
页面上的 RPC 按钮,会走 TB 的服务端 RPC 通道,把指令发给设备,设备匹配到方法名后执行并返回结果,前端组件可以按返回值刷新展示。
关于“子设备下发”,这个其实常出现在网关模式下。ThingsBoard 官方对网关场景的处理方式是:网关设备本身接入 TB,子设备数据通过网关上传,同时 TB 对子设备的 RPC 指令也由网关转发。仪表板上绑定的实体如果是子设备,下发 RPC 时消息并不会直接到子设备,而是到网关,由网关按子设备标识(如deviceName)进行二次转发。
这里常见的坑是:仪表板绑定的实体是子设备,但网关上报的是父设备心跳,你在操作面板上看着子设备“在线”,其实网关并没有把子设备状态同步上来。解决办法是:给子设备配置“属性上报”逻辑,由网关主动上报子设备的active属性。真正要排查子设备状态时,优先看网关日志,而不是盯仪表板。
3.3 规则链在状态链路中的关键作用
仪表板状态能不能实时更新,规则链是一个很关键的环节。TB 的规则引擎负责处理所有进入平台的消息,默认的“Root Chain”里只配置了“保存最新遥测”和“保存原始遥测”。如果你用的是默认规则链,那数据链路是通的;但如果你想在数据到达时做一些自定义处理,比如根据温度阈值改变设备状态属性,你就得改规则链或新建子规则链。
实操举例:你希望当一台温控设备的温度超过 60 度时,设备状态自动标记成“故障”。这时需要在规则链里增加一个筛选节点,条件设置为“temperature >= 60”,然后接一个“保存属性”节点,把faultFlag保存为 true。这样仪表板上绑定faultFlag属性,就可以直接显示设备的健康状态。
这个设计思路特别好用,因为它把“设备判断逻辑”从设备端搬到了平台端。设备端只需要老老实实上报数据,业务规则交给你在 TB 里灵活编排。仪表板上的状态,因此也不仅仅是设备自己上报的在线状态,而可以带上业务语义,比如“高温告警”“低电量”等状态。
4. 常见问题与排查技巧实录
这里把我实际运维和开发中踩过的坑、以及社区里高频问题做一个速查整理,每一条都是实打实的经验,可以放在手边对照排查。
4.1 设备状态显示离线,但设备明明在运行
这是最常见的一个问题。排查思路按顺序走:
- 先看设备详情页里“设备状态”是不是 Active。如果是,说明设备与会话还在,问题出在仪表板组件配置。如果不是,继续往下。
- 检查设备端 MQTT 连接是否正常、keepalive 是否设得太短。很多低功耗设备在使用 NB-IoT 或 LoRa 网关时,网络链路本身就不稳定,设备离线判定很容易出现误判。
- 确认设备是否走了持久会话。在 TB 的 MQTT 接入配置里,如果设备端设定了 clean session = false,服务端对会话的保持时间会更长,离线状态翻转会比预想慢一些。
实际经验:你可以主动调低会话超时时间,让离线更灵敏,但这会增加服务端的内存消耗。自己权衡,别盲目追求实时离线。
4.2 仪表板没数据,但设备“最新遥测”里有数据
这种情况下,问题多半出在仪表板的数据源配置上。按以下优先级排查:
- 实体别名是否选中了你想要的那个设备或分组。
- 数据键名是否和最新遥测里的键名完全一致,大小写也要盯。
- 组件时间窗是否覆盖了数据产生的时间段。
- 是否配置了数据聚合(如按小时平均),但实际数据点太少导致聚合结果为空。
很多时候,前三项没问题,卡在时间窗上。尤其要注意,如果你手动改了设备端的时间戳,或者设备端和数据服务器时间不同步,查出来的数据就会“凭空消失”。
4.3 为什么有的仪表板状态能自动刷新,有的不行
一度我以为自己配置有问题,后来发现是版本差异。在较旧版本的 ThingsBoard 中,部分组件(如表单、静态卡片)不支持高频自动刷新,或者刷新频率有最小限制。新版基本都支持自定义,但如果你是老旧版本,就得去代码层面调整。
解决办法:建议把仪表板组件升级到官方推荐的“最新遥测”“卡片”“状态开关”这几类,这些组件对状态刷新支持最好。另外,尽量避免在同一页面上拖入过多高频刷新组件,否则浏览器请求量会瞬间拉高,前端性能直接拉胯。
4.4 RPC 下发超时,设备端没收到指令
RPC 下发失败有几个高频原因:
- 设备端没有按规范订阅 RPC 指令的 Topic。ThingsBoard 的 MQTT RPC 分为服务端 RPC 和客户端 RPC。服务端 RPC 下发的 Topic 是
v1/devices/me/rpc/request/+,设备要先订阅这个主题。如果没有订阅,指令自然到不了设备端。 - 设备根本没有连接在线。很多人误以为 RPC 指令会先缓存再下发,其实服务端 RPC 在设备离线时默认不会缓存,直接提示超时。
- 请求超时时间设置太短。TB 默认 RPC 超时时间是 10 秒,如果你设备处理逻辑较慢,需要调大超时。
我自己的习惯是:设备端 RPC 响应逻辑一定要精简。收到指令,马上返回一个 ACK(表示收到),然后再异步去执行具体动作,最后再返回执行结果。不然 RPC 等待超时,前端按钮就会报错,仪表板状态也跟着变成“未知”。
5. 深度对比:ThingsBoard 和 JetLinks 怎么选
围绕“jetlinks vs thingsboard”这个搜索,我也说一下自己的实际感受。
JetLinks 是国产物联网平台,协议接入和自定义协议解析做得比较接地气,文档也是中文的,国内开发者上手容易。如果你主要做设备接入、数据采集、规则处理,JetLinks 这套东西确实省心不少。但它的仪表板能力,跟 ThingsBoard 相比,差距还是明显的。
ThingsBoard 的仪表板核心优势在三点:
- 组件类型丰富。图表、卡片、表格、地图、状态灯、RPC 按钮,基本覆盖了监控类页面的所有需求。
- 状态管理机制灵活。通过实体别名和状态切换,可以轻松实现“主表 — 详情”的联动交互。
- 生态成熟。官方有大量仪表板模板,社区方案也多,二次开发资料丰富。
JetLinks 的仪表板则更像是一个附加功能,能快速搭建简单看板,但复杂逻辑、细粒度状态控制、自由交互式组件布局,都远不如 TB 顺手。如果你是冲着仪表板状态展示的深度来的,ThingsBoard 是更合理的选择。
反过来讲,JetLinks 在协议平台化接入和设备管理上,对国内开发者更友好,比如它内置的 TCP 网关、MQTT 网关配置就比 TB 的同类配置更直观。如果团队目标是快速打通设备接入链路,并且仪表板需求不复杂,可以选 JetLinks。但凡是你要做一个可对外展示的运营大屏,或者状态联动逻辑比较深,那还是坚定地站在 ThingsBoard 这边。
6. 后续扩展思路与我的习惯
聊到这里,仪表板状态的核心链路已经清晰了。最后分享一个我自己在实际项目里反复用到的扩展习惯。
我做仪表板状态展示时,不会只依赖设备上报的数据。我更倾向于在规则链里多加几个“状态判活”节点:
- 每台设备上报数据后,规则链自动更新它的
lastReportTime属性。 - 仪表板上用
lastReportTime和当前时间做对比,超过某个阈值(比如 5 分钟没有上报)就判定为“数据超时”。这比单纯依赖 MQTT 会话的 online/offline 状态更贴近真实业务。
比如一台设备连接还挂着,但数据卡死不上报了,它的 active 状态可能是 online,但业务上它已经“失联”了。这种情况如果只盯在线状态,就会错失告警时机。所以我在仪表板卡片上经常会同时展示两个维度:平台连接状态(active)和数据新鲜度(lastReportTime),前者看连接,后者看业务活性,两个状态配合起来,判断设备健康度基本就够用了。
还有一个细节养成习惯:每次调整完仪表板配置,都会截图存一份版本。ThingsBoard 仪表板虽然没有非常细粒度的版本管理,但手动存档可以让你在改坏的时候迅速回退。仪表板配置实际上是一大段 JSON,直接导出备份也相对方便,这习惯帮我省过不少麻烦。
ThingsBoard 的仪表板状态,说穿了就是一套实体—数据—可视化之间的绑定关系。把这条链路理顺,往后真是越用越顺手。希望这篇内容能帮你把仪表板状态相关的坑填掉大半。