设备影子概览
物联网平台提供设备影子功能,用于缓存设备状态。设备在线时,可以直接获取物联网平台指令;设备离线后,再次上线可以主动拉取物联网平台指令。
什么是设备影子
设备影子是一个JSON文档,用于存储设备上报状态、应用程序期望状态信息。
每个设备有且只有一个设备影子,设备可以通过MQTT获取和设置设备影子来同步状态,该同步可以是影子同步给设备,也可以是设备同步给影子。
应用场景
- 应用程序请求获取设备状态。场景描述:使用设备影子机制,设备状态变更,只需同步状态给设备影子一次,应用程序请求获取设备状态,不论应用程序请求数量,和设备是否联网在线,都可从设备影子中获取设备当前状态,实现应用程序与设备解耦。应用程序获取设备影子中状态的流程图如下。
- 设备网络不稳定,设备频繁上下线,无法正常响应应用程序的请求。
- 设备网络稳定,同时响应多个应用程序的请求,即使响应的结果一样,设备本身处理能力有限,也会无法负载多次请求。
- 应用程序下发指令给设备,变更设备状态。场景描述:设备处于下线状态,或设备网络不稳定,设备频繁上下线,应用程序发送控制指令给设备,设备不在线,指令就会发送失败。使用设备影子机制,可以将应用程序下发的指令,携带时间戳存储到设备影子中。设备再上线时,获取设备影子中指令,并根据时间戳确定是否执行。应用程序更新设备状态的流程图如下.
设备影子数据流
设备影子数据通过Topic 进行流转,主要包括设备上报状态到设备影子、应用程序更改设备状态、设备离线再上线后主动获取设备影子信息,和设备端请求删除设备影子中的属性信息。本文介绍设备影子Topic 及其数据格式。
设备影子Topic
物联网平台已为每个设备预定义了两个Topic ,用于实现设备影子数据流转。
- /keepsoft/{tenantKey}/shadow/update/{productKey}/{deviceKey} 设备和应用程序发布消息到此Topic 。物联网平台收到该Topic 的消息后,将消息中的状态更新到设备影子中。
- /keepsoft/{tenantKey}/keepsoft/{tenantKey}/shadow/get/{productKey}/{deviceKey}设备影子更新状态到该Topic ,设备订阅此Topic 获取最新消息。
使用示例
本文以灯泡设备为例,说明设备、设备影子以及应用程序之间的通信,主要介绍设备主动上报状态、应用程序改变设备状态、设备主动获取影子内容,和设备主动删除影子属性。
示例中,产品的ProductKey是a1PbRCF**;设备名称DeviceName**是lightbulb。设备以QoS=1发布消息和订阅两个设备影子Topic 。设备主动上报状态
设备在线时,主动上报设备状态到影子,应用程序主动获取设备影子状态。
数据流转过程如下图所示。
当灯泡lightbulb上线时,使用Topic /keepsoft/{tenantKey}/shadow/update/a1PbRCF**/lightbulb**上报最新状态到影子。发送的JSON消息格式:
{
"method": "update",
"state": {
"reported": {
"color": "red"
}
},
"version": 1
}
| 参数 | 说明 | | —- | —- | | method | 表示设备或者应用程序请求设备影子时的操作类型。
当执行更新操作时,method为必填字段,设置为update。 | | state | 表示设备发送给设备影子的状态信息。
reported为必填字段,状态信息会同步更新到设备影子的reported部分。 | | version | 表示设备影子检查请求中的版本信息。
只有当新版本大于当前版本时,设备影子才会接收设备端的请求,并更新设备影子版本。
如果version设置为-1时,表示清空设备影子数据,设备影子会接收设备端的请求,并将设备影子版本更新为0。 |设备影子接收到灯泡上报的状态数据后,更新影子文档。
{
"state": {
"reported": {
"color": "red"
}
},
"metadata": {
"reported": {
"color": {
"timestamp": 1469564492
}
}
},
"timestamp": 1469564492,
"version": 1
}
影子文件更新后,设备影子会返回结果给设备(灯泡),即发送消息到设备订阅的Topic /keepsoft/{tenantKey}/shadow/get/a1PbRCF**/lightbulb**中。
若更新成功,发送到该Topic 中的消息为:
{
"method": "reply",
"payload": {
"status": "success",
"version": 1
},
"timestamp": 1469564576
}
若更新失败,发送到该Topic 中的消息为:
{
"method": "reply",
"payload": {
"status": "error",
"content": {
"errorcode": "${errorcode}",
"errormessage": "${errormessage}"
}
},
"timestamp": 1469564576
}
| errorCode | errorMessage | | —- | —- | | 400 | 不正确的JSON格式。 | | 401 | 影子数据缺少method信息。 | | 402 | 影子数据缺少state字段。 | | 403 | 影子数据中version值不是数字。 | | 404 | 影子数据缺少reported字段。 | | 405 | 影子数据中 reported属性字段为空。 | | 406 | 影子数据中 method是无效的方法。 | | 407 | 影子内容为空。 | | 408 | 影子数据中reported属性个数超过128个。 | | 409 | 影子版本冲突。 | | 500 | 服务端处理异常。 |
应用程序改变设备状态
应用程序通过调用云端API下发期望状态给设备影子,设备影子再将文件下发给设备端。设备根据影子更新状态,并上报最新状态至影子。
数据流转流程如下图所示。
应用程序调用云端API UpdateDeviceShadow,下发消息更改灯泡状态,例如需将灯泡的color属性值改为green。调用API时,参数ShadowMessage的值为:
{
"method": "update",
"state": {
"desired": {
"color": "green"
}
},
"version": 2
}
设备影子接收到更新请求,更新其影子文档为:
{
"state": {
"reported": {
"color": "red"
},
"desired": {
"color": "green"
}
},
"metadata": {
"reported": {
"color": {
"timestamp": 1469564492
}
},
"desired": {
"color": {
"timestamp": 1469564576
}
}
},
"timestamp": 1469564576,
"version": 2
}
设备影子更新完成后,发送返回结果到Topic /keepsoft/{tenantKey}/shadow/get/a1PbRCF**/lightbulb**中。返回结果信息构成由设备影子决定。
{
"method": "control",
"payload": {
"state": {
"reported": {
"color": "red"
},
"desired": {
"color": "green"
}
},
"metadata": {
"reported": {
"color": {
"timestamp": 1469564492
}
},
"desired": {
"color": {
"timestamp": 1469564576
}
}
}
},
"version": 2,
"timestamp": 1469564576
}
如果设备灯泡在线,并且订阅了Topic /keepsoft/{tenantKey}/shadow/get/a1PbRCF**/lightbulb,则会立即收到消息。收到消息后,根据请求文档中desired**的值,将灯泡颜色变成绿色。灯泡更新完状态后,上报最新状态到物联网平台。
{
"method": "update",
"state": {
"reported": {
"color": "green"
}
},
"version": 3
}
说明 如果有时间戳判断指令过期,也可以选择不更新。
设备影子会返回响应结果给设备,发送消息到设备订阅的Topic /keepsoft/{tenantKey}/shadow/get/a1PbRCF**/lightbulb**中。详细说明,请参见设备主动上报状态。
最新状态上报成功后, 设备端和设备影子进行以下操作。
设备端发消息到Topic /keepsoft/{tenantKey}/shadow/update/a1PbRCF**/lightbulb中清空desired**属性。消息如下:
{
"method": "update",
"state": {
"desired": "null"
},
"version": 4
}
设备影子会同步更新影子文档,此时的影子文档如下:
{
"state": {
"reported": {
"color": "green"
}
},
"metadata": {
"reported": {
"color": {
"timestamp": 1469564577
}
},
"desired": {
"timestamp": 1469564576
}
},
"version": 4
}
设备主动获取影子内容
若应用程序发送指令时,设备离线。设备再次上线后,将主动获取设备影子内容。
数据流转过程如下图所示。
灯泡主动发送以下消息到Topic /keepsoft/{tenantKey}/shadow/update/a1PbRCF**/lightbulb**中,请求获取设备影子中保存的最新状态。
{
"method": "get"
}
当设备影子收到这条消息后,发送最新状态到Topic /keepsoft/{tenantKey}/shadow/get/a1PbRCF**/lightbulb**。灯泡通过订阅该Topic 获取最新状态。消息内容如下:
{
"method": "reply",
"payload": {
"status": "success",
"state": {
"reported": {
"color": "red"
},
"desired": {
"color": "green"
}
},
"metadata": {
"reported": {
"color": {
"timestamp": 1469564492
}
},
"desired": {
"color": {
"timestamp": 1469564492
}
}
}
},
"version": 2,
"timestamp": 1469564576
}
设备主动删除影子属性
若设备端已经是最新状态,设备端可以主动发送指令,删除设备影子中保存的某条属性状态。
数据流转过程如下图所示。
设备发送以下内容到Topic /keepsoft/{tenantKey}/shadow/update/a1PbRCF**/lightbulb中。
其中,method**为delete,属性的值为null。
删除影子中某一属性。
{
"method": "delete",
"state": {
"reported": {
"color": "null",
"temperature": "null"
}
},
"version": 1
}
删除影子全部属性。
{
"method": "delete",
"state": {
"reported": "null"
},
"version": 1
}