设备投影
错峰上报策略
设备通过update或report报文上报数据时,需要进行错峰上报,从而平抑服务器的流量,避免报文拥堵后平台回复慢,导致设备重发或重连。云服务器带宽成本高,此问题表现较为明显。
错峰上报策略参考:
上报间隔 >= 5分钟:整点抄表后,在接下来1分钟内随机一个时间点上传;
1分钟 <= 上报间隔 < 5分钟:抄表后,在接下来10秒内随机一个时间点上传;
上报间隔 < 1分钟:通常不采用实时数据上报,而使用秒级监控方案。
实时数据report
新增method
为reported
,对原update
报文进行升级,主要改动是将仪表实时数据存储在固定的属性meters
中,数据结构为JSON数组,数组中的元素与原来保持一致。
{
"method": "report",
"reported": {
// 数据类型,REALTIME-实时数据,HISTORY-历史数据补传
"source": "REALTIME",
// 网关/4G表的基础数据,例如:信号强度,网关本身的数据都通过gateway上报
"gateway": {
"rssi": 77
},
// 仪表数据部分,结构为数组
"meters": [
{
"addr": "sub_dev_1",
"state": "ONLINE",
"Ua": 220.0,
"Ub": 220.0,
...
},
{
"addr": "sub_dev_1_1",
"state": "ONLINE",
"Ua": 220.0,
"Ub": 220.0,
...
}
]
},
/* ========== 以下部分与update报文相同 ========== */
"msgid": 123,
// 分包序号
"fragNo": 1,
// 总包数
"fragment": 5,
"timestamp": 1638869890,
"sn": "1234567890123",
"sendtime": 1638869890,
"version": 1
}
参数 | 说明 |
---|
msgid
| 可使用UUID、时间戳、流水号等作为msgid,只要保证设备端唯一即可。 |
reported
| 表示设备上报的最新状态。其中的具体属性属于业务层协议的范畴。 如果包含子设备,则以子设备的sn/addr为key,值为子设备的状态,其中固定使用state = "ONLINE" / "OFFLINE" 表示子设备的在线和离线。 |
reported.gateway
| 网关的状态数据,或4G表通讯模块相关数据,例如:实时信号强度。 |
reported.meters
| 仪表的实时状态数据,数组。 |
version
| 设备投影接收消息时,用于校验的版本信息,投影的初始版本为1 。 投影版本由中台管理,当update消息中存在desired属性时,中台会将自动投影版本+1 只有当上报的版本号等于或大于投影版本时,中台才会接受设备上报的状态,并更新到投影缓存中; 如果设备上报的版本小于投影版本,中台会返回错误码3003 ,此时设备应当主动请求投影 ,获取最新的版本号,并保存到本地,然后使用最新版本号重新上报状态。 |
timestamp
| 设备投影收到消息后,由于不能保证消息的全局有序,所以会根据此消息上报的属性,逐条与metadata中的时间戳进行比较,当timestamp晚于metadata中的时间戳时,才会更新投影中相应的属性。 |
sendtime
| 消息发送的时间,与timestamp可能存在时间差异,主要用于调试对照。 |
fragNo
| 分包上传的包序号,从1 开始编号,多包数据的timestamp必须保持一致。 |
fragment
| 分包上传的总包数,多包数据的timestamp必须保持一致。 |
实时数据update
设备主动上报设备状态,中台收到消息后,增量更新中台的设备投影缓存。

1.设备在线时,使用Topic data/up/{productKey}/{sn}
, method
为update
,上报最新状态,消息格式如下:
{
"msgid": 123,
"reported": {
// 数据类型,REALTIME-实时数据,HISTORY-历史数据补传,
// source不声明或为空时,默认为实时数据REALTIME
"source": "REALTIME",
// 网关/4G表的基础数据,例如:信号强度
"base": {
"rssi": 77
},
// 一级子设备
"sub_sn_1_1": {
"Ua": 220.0,
"state": "ONLINE"
},
// 二级子设备
"sub_sn_1_1_1": {
"Ua": 220.0,
"state": "ONLINE"
}
},
// 分包序号
"fragNo": 1,
// 总包数
"fragment": 5,
"timestamp": 1638869890,
"method": "update",
"sn": "1234567890123",
"sendtime": 1638869890,
"version": 1
}
参数 | 说明 |
---|
msgid
| 可使用UUID、时间戳、流水号等作为msgid,只要保证设备端唯一即可。 |
reported
| 表示设备上报的最新状态。其中的具体属性属于业务层协议的范畴。 如果包含子设备,则以子设备的sn/addr为key,值为子设备的状态,其中固定使用state = "ONLINE" / "OFFLINE" 表示子设备的在线和离线。 |
reported.base
| 网关/4G表的基础数据,例如:实时信号强度。 |
version
| 设备投影接收消息时,用于校验的版本信息,投影的初始版本为1 。 投影版本由中台管理,当update消息中存在desired属性时,中台会将自动投影版本+1 只有当上报的版本号等于或大于投影版本时,中台才会接受设备上报的状态,并更新到投影缓存中; 如果设备上报的版本小于投影版本,中台会返回错误码3003 ,此时设备应当主动请求投影 ,获取最新的版本号,并保存到本地,然后使用最新版本号重新上报状态。 |
timestamp
| 设备投影收到消息后,由于不能保证消息的全局有序,所以会根据此消息上报的属性,逐条与metadata中的时间戳进行比较,当timestamp晚于metadata中的时间戳时,才会更新投影中相应的属性。 |
sendtime
| 消息发送的时间,与timestamp可能存在时间差异,主要用于调试对照。 |
fragNo
| 分包上传的包序号,从1 开始编号,多包数据的timestamp必须保持一致。 |
fragment
| 分包上传的总包数,多包数据的timestamp必须保持一致。 |
2.中台收到消息后,更新设备状态,如下:
{
"reported": {
"ua": 220.0
},
"metadata": {
"reported": {
"ua": {
"timestamp": 1638869890
}
}
},
"timestamp": 1638869890,
"state": "ONLINE",
"version": 1
}
3.投影更新完成后,中台会使用Topic data/down/{productKey}/{sn}
, method
为update
,返回结果给设备。
{
"msgid": 123,
"method": "update",
"sn": "1234567890123",
"res": 1,
"timestamp": 1638869990
}
{
"msgid": 123,
"method": "update",
"sn": "1234567890123",
"res": 0,
"errcode": "3003",
"timestamp": 1638869990
}
修改设备期望状态update->desired
应用程序或其他设备可以下发期望状态给设备投影,设备投影再将状态下发给相应设备。设备根据收到的消息更新状态,然后上报最新状态。

1.设备向Topic data/up/{productKey}/{sn}
发送如下消息, method
为update
:
{
"msgid": 123,
"desired": {
"price": 1.0
},
"method": "update",
"sn": "1234567890123",
"timestamp": 1638869890,
"sendtime": 1638869890,
"version": 1
}
参数 | 说明 |
---|
desired
| 必填,用于上报期望这个设备变成什么状态。其中的具体属性属于业务层协议的范畴。 |
timestamp
| 更新desired时,同样也会逐条比对timestamp与metadata中的时间戳。 |
2.中台收到消息后,更新投影缓存为如下状态,其中的版本version
会进行+1
:
{
"desired": {
"price": 1.0
},
"reported": {
"ua": 220.0
},
"metadata": {
"desired": {
"price": {
"timestamp": 1638869890
}
},
"reported": {
"ua": {
"timestamp": 1638869790
}
}
},
"timestamp": 1638869890,
"state": "ONLINE",
"version": 2
}
3.中台会使用Topic data/down/{productKey}/{sn}
,返回结果给设备。
{
"msgid": 123,
"method": "update",
"sn": "1234567890123",
"res": 1,
"timestamp": 1638869990
}
{
"msgid": 123,
"method": "update",
"sn": "1234567890123",
"res": 0,
"errcode": "3003",
"timestamp": 1638869990
}
4.设备如果收到了更新成功的相应消息,此时是不建议在设备端对version
进行+1
,因为接下来设备会调用下发投影流程,对投影的desired
部分进行下发。
设备静默上报状态update_silent
有时候,用户希望手动发送刷新指令给设备,使设备上报一次最新状态并更新到投影中。此时,刷新指令是通过中台标准协议中的操作指令进行下发,然后设备需要发出2条回复消息:
正常情况下,第2条消息直接使用method: update
上报即可,中台在收到消息后会给予应答。但对于一些已有的设备和协议,在通过协议网关接入时,可能并不希望接收中台的应答,或者很难评估这次应答会出现何种问题。
针对以上场景,中台提供了静默更新投影的method——update_silence
,通过此方式上报的消息,中台不会进行应答。但这也会导致设备端无法知道中台是否确实收到了消息。所以, 这是一种非标准化的处理逻辑,通常不建议使用。
1.设备使用Topic data/up/{productKey}/{sn}
, method
为update_silent
,上报最新状态,消息格式如下:
{
"msgid": 123,
"reported": {
"ua": 220.0
},
"method": "update_silent",
"sn": "1234567890123",
"timestamp": 1638869890,
"sendtime": 1638869890,
"version": 1
}
2.中台收到消息后,更新设备投影缓存,但不给予回复。
中台下发期望状态control
设备投影在发现desired
被更新时,会将投影中的desired
主动下发给设备。
1.中台使用Topic data/down/{productKey}/{sn}
, method
为control
,将投影推送给设备,消息如下,其中可以看到version
为2
:
{
"msgid": 628131887239491584,
"desired": {
"price": 1.0
},
"method": "control",
"sn": "1234567890123",
"timestamp": 1638870890,
"version": 2
}
2.设备收到消息后,可以通过校验消息的version
和timestamp
,来确定是否执行该指令和更新本地version
。
3.设备端使用Topic data/up/{productKey}/{sn}
, method
为control
,对消息进行响应。
{
"msgid": 628131887239491584,
"method": "control",
"sn": "1234567890123",
"res": 1,
"timestamp": 1638869990
}
{
"msgid": 628131887239491584,
"method": "control",
"sn": "1234567890123",
"res": 0,
"timestamp": 1638869990
}
4.如果设备端更新成功,中台会删除设备投影中desired
已下发的属性。
设备主动请求投影get
设备首次连接平台时,或者上报状态发现版本错误后,可以向平台主动请求投影,以便于后续能够正常上报最新状态。

1.设备端使用Topic data/up/{productKey}/{sn}
, method
为get
,消息格式如下:
{
"msgid": 234,
"method": "get",
"sn": "1234567890123",
"timestamp": 1638870990,
"property": "price"
}
参数 | 说明 |
---|
property
| 表示设备想要请求desired中的哪个属性值,如果为null 或空字符串"" 时,下发整个desired。 property的属性路径规范参考JSONpath。 |
2.中台收到消息后 ,使用Topic data/down/{productKey}/{sn}
下发相应的属性, method
为get
:
{
"msgid": 234,
"method": "get",
"sn": "1234567890123",
"timestamp": 1638871090,
"desired": {
"price": 1.0
},
"version": 2
}
3.设备得到中台的响应,并更新完设备状态后,应当删除设备投影。
删除设备投影delete
设备主动删除设备投影。例如在设备主动请求投影,或者固件升级后,需要主动删除中台上的设备投影,或其中部分属性。
1.设备端使用Topic data/up/{productKey}/{sn}
, method
为delete
,消息格式如下:
{
"msgid": 345,
"method": "delete",
"sn": "1234567890123",
"timestamp": 1638871990,
"property": "desired.price",
"version": 2
}
参数 | 说明 |
---|
property
| 表示设备要删除的设备投影属性。 此处与请求投影中的property不同,需要声明删除reported还是desired中的属性。 property的属性路径规范参考JSONpath。 |
2.中台收到消息后,删除设备投影中的desired.price
属性,并删除metadata中相应的元数据信息。
{
"reported": {
"ua": 220.0
},
"metadata": {
"reported": {
"ua": {
"timestamp": 1638869790
}
}
},
"timestamp": 1638871990,
"state": "ONLINE",
"version": 2
}
3.中台会使用Topic data/down/{productKey}/{sn}
,返回结果给设备。
{
"msgid": 345,
"method": "delete",
"sn": "1234567890123",
"res": 1,
"timestamp": 1638872990
}
{
"msgid": 345,
"method": "delete",
"sn": "1234567890123",
"res": 0,
"timestamp": 1638872990
}
19 六月 2024