4、设备影子API概览:获取影子、更新影子、删除影子、订阅影子变更
好,咱们进入正题。设备影子这东西,说白了就是一个 JSON 文件,躺在服务端,随时反映你设备的「最新状态」。你想想看,设备可能离线,可能网络不好,但影子一直在。这就是它的价值。
我刚开始接触 ThingsBoard 时,总觉得影子 API 很神秘。后来用多了才发现,核心就四个操作:查、改、删、听。嗯,咱们一个一个来。
4.1 获取影子:看看设备现在啥样
获取影子,就是问服务端:「嘿,这个设备的最新状态是什么?」
我个人习惯用 REST API 来查,简单直接。你只需要知道设备的实体 ID(就是那个 UUID),然后发一个 GET 请求。
GET /api/plugins/telemetry/DEVICE/{entityId}/attributes/CLIENT_SCOPE
这里有个坑,我一开始没注意——影子数据存在 CLIENT_SCOPE 下。不是 SHARED_SCOPE,也不是 SERVER_SCOPE。你如果查错了 scope,返回的就是空数组。
返回的数据长这样:
{
"temperature": 25.6,
"humidity": 68,
"lastUpdate": 1695000000000
}
我在项目中遇到过一个问题:设备上报频率很高,每次查影子都拿到一堆旧数据。后来我加了个时间戳字段,每次更新时带上,查的时候比对一下,就知道数据是不是最新的了。
v1/devices/me/attributes。设备上线后,服务端会自动推送一次全量影子数据。
4.2 更新影子:把新状态写进去
更新影子,就是告诉服务端:「设备现在的状态变了,你记一下。」
更新用 POST 请求,数据格式也是 JSON。注意,更新是覆盖式的——你传什么,服务端就存什么。不会自动合并。
POST /api/plugins/telemetry/DEVICE/{entityId}/attributes/CLIENT_SCOPE
{
"temperature": 26.1,
"humidity": 65,
"fanSpeed": 3
}
我曾经踩过一个坑:设备上报时只传了 temperature,没传 humidity。结果 humidity 在服务端被清空了。为什么?因为更新是整体替换,不是局部更新。
我个人习惯在设备端维护一个「全量状态缓存」,每次上报前,把当前所有状态打包成一个 JSON,再发出去。这样就不会丢字段了。
4.3 删除影子:清理不需要的数据
删除影子,说实话,我用得不多。但有些场景确实需要:比如设备报废了、设备被重置了、或者你想清理测试数据。
删除操作也是 REST API,用 DELETE 方法:
DELETE /api/plugins/telemetry/DEVICE/{entityId}/attributes/CLIENT_SCOPE
注意,这个操作会清空整个 CLIENT_SCOPE 下的所有属性。不是只删一个字段,是全部删掉。
我记得有一次,测试环境里有个设备影子数据乱了,我直接删了重新创建。嗯,简单粗暴,但有效。
4.4 订阅影子变更:实时感知变化
订阅影子变更,这才是 IoT 场景里的核心能力。你想想看,如果每次都要轮询查影子,那效率多低?而且实时性也差。
ThingsBoard 支持通过 WebSocket 或 MQTT 订阅影子变更。我个人更推荐 MQTT,因为它在弱网环境下表现更好。
订阅的主题是:
v1/devices/me/attributes
设备端订阅这个主题后,只要影子数据有变化,服务端就会主动推送。推送的数据格式和 GET 返回的一样。
我在项目中遇到过一个问题:设备订阅了影子变更,但有时候收不到推送。排查了半天,发现是 MQTT 的 QoS 设置成了 0(最多一次)。改成 QoS 1(至少一次)后,问题就解决了。
另外,订阅变更时,你可以指定只关注某些字段。比如我只关心 temperature 的变化,可以这样:
v1/devices/me/attributes/temperature
这样推送的数据里就只有 temperature 字段,省流量,也省解析时间。
4.5 四个操作的对比
| 操作 | HTTP 方法 | MQTT 主题 | 说明 |
|---|---|---|---|
| 获取影子 | GET | 订阅 v1/devices/me/attributes |
获取设备最新状态 |
| 更新影子 | POST | 发布到 v1/devices/me/attributes |
覆盖式更新,注意保留所有字段 |
| 删除影子 | DELETE | 无 | 清空整个 CLIENT_SCOPE,谨慎使用 |
| 订阅变更 | WebSocket | 订阅 v1/devices/me/attributes |
实时推送,推荐 QoS 1 |
核心要点:
- 影子数据存在 CLIENT_SCOPE 下,别搞错 scope
- 更新是覆盖式的,记得传全量数据
- 删除操作不可逆,慎用
- 订阅变更用 MQTT + QoS 1,稳得很
好了,这四个 API 就是设备影子的核心操作。说白了,就是增删改查加一个订阅。你只要掌握了这些,设备影子这块就基本拿下了。下一节咱们会动手写代码,把这些 API 串起来,做一个完整的远程控制 demo。