一、设备影子描述

设备影子是设备在云端的镜像,每个设备有且只有一个设备影子,影子存储设备最近的状态和应用程序期望,通过改变影子状态可以实现云端对对于设备的状态管控。

二、通讯协议

2.1 通讯方式

传输协议 MQTT
序列化方式 JSON
编码格式 UTF-8

2.2 Topic定义

设备影子数据通过以下Topic进行流转。

Topic名称 描述
/${productId}/${deviceId}/shadow/update 设备和应用程序发布消息到此Topic。设备平台收到该Topic的消息后,将消息中的状态更新到设备影子中。
/${productId}/${deviceId}/shadow/get 设备影子更新状态到该Topic,设备和应用订阅此Topic获取最新消息。

三、场景示例

示例以灯泡设备为例,属性为灯泡的颜色,定义属性名为 color ,值有 red、green等值。

下面将主要介绍以下几个场景,方便您快速了解设备影子的通讯机制:

  1. 应用程序改变设备状态

  2. 应用程序或设备获取设备影子最新状态

  3. 应用程序或设备删除影子信息

  4. 应用程序或设备设置影子错误信息

3.1 应用程序改变设备状态

1.【应用程序】设置影子属性期望值

应用程序更新期望状态,使用Topic /${productId}/${deviceId}/shadow/update 上报期望值。发送JSON消息格式如下:

{
    "method":"update",
    "messageId":"157889065984",
    "state":{
        "desired":{
            "power_setting": {
                "flag": true,
                "config": {
                  "icon": "/test.png"
                }
            }
        }
    },
    "timestamp":0
}

参数说明

字段名 类型 是否必须 说明
1 method String 表示设备或者应用程序请求设备影子时的操作类型。当执行更新操作时,method为必填字段,设置为update。
2 messageId String 消息ID,最长为64位字符,标识该消息的唯一ID,发送端进行定位消息使用
3 state Object 表示设备和应用程序发送给设备影子的状态信息。desired 为必填字段,状态信息会同步到设备影子的 desired 部分
4 timestamp Long 表示设备影子的最新时间戳,unix时间戳毫秒值。设备影子服务在收到更新请求后。先进行判断是否等于设备影子最新时间戳,不等于则判断是否大于等于该上报字段的metadata中的最后更新时间戳,如不满足,则提示版本冲突,不进行保存。

当前云鲸设备影子未对设备影子Key做数据大小或业务Key值的校验,但建议设备影子内业务Key不要超过128个。

2. 【设备影子服务】保存设备影子

设备影子接口到应用上报的期望值数据后,更新云端的设备影子文档

{
    "state":{
        "desired":{
            "power_setting": {
                "flag": true,
                "config": {
                  "icon": "/test.png"
                }
            }
        }
    },
    "metadata":{
        "desired":{
            "power_setting": {
                "timestamp": 1469564576000
             }
         }
    },
    "timestamp":1469564576000
 }

设备影子文档说明

字段名 类型 说明
1 state Object 表示设备影子当前状态的信息
2 state.desired Object 表示设备影子中属性的期望值信息
3 metadata Object 表示设备影子当前状态的元数据信息
4 metadata.desired Object 表示设备影子中属性的期望值元数据信息
5 metadata.desired.{flied}.timestamp Long 时间戳毫秒值,表示设备影子中属性的期望值数据的更新时间, {flied} 为设置的 JSON 第一层结构属性名称
6 timestamp Long 时间戳毫秒值,表示设备影子文档的更新时间

3. 【设备影子服务】下发期望值更新

设备影子收到更新请求后,进行验证更新,结果发送到Topic: /${productId}/${deviceId}/shadow/get

1)若成功更新,发送到该 Topic 中的消息为:

{
    "method":"control",
    "messageId":"157889065984",
    "payload":{
        "code":0,
        "state":{
           "desired":{
                "power_setting": {
                    "flag": true,
                    "config": {
                      "icon": "/test.png"
                    }
                }
            }
        },
        "metadata":{
            "desired":{
                "power_setting":{
                    "timestamp":1469564576000
                }
            }
        }
    },
    "timestamp":1469564576000
}
字段名称 类型 说明
1 method String 表示设备影子服务下发消息时的方法类型当执行下发期望值是,method 值为 control
2 messageId String 应用程序或设备上报消息时的消息ID,最长为64位字符,设备影子服务下发时将原值发送
3 payload Object 设备影子服务下发消息的内容
4 payload.code Int 表示设备影子处理该请求的状态,为0表示正常,不为0为异常
5 payload.state Object 设备影子文档当前状态
6 payload.state.desired Object 设备影子文档当前期望状态
7 payload.metadata Object 设备影子文档当前状态元数据
8 payload.metadata.desired Object 设备影子文档当前上报状态元数据
9 payload.metadata.desired.{flied}.timestamp Long unix时间戳毫秒值,表示设备影子中属性的期望值数据的更新时间, {flied} 为设置的 JSON 第一层结构属性名称
10 timestamp Long unix时间戳毫秒值,表示设备影子文档的最后更新时间,设备端应保存该值,后续更新时进行携带使用

2)若更新失败,发送到该 Topic 的消息为:

表示响应失败,并返回具体错误码和错误消息。

{
    "method":"reply",
    "messageId":"157889065985",
    "payload":{
        "code": ${errorcode},
        "msg": "${errormessage}"
     }
}

表示影子版本冲突导致响应失败。设备影子服务会返回云端设备影子更新时间,设备端应保存该设备影子最新更新时间。然后设备端应当检查当前messageId对应的上报数值是否与本地属性值一致,如一致则使用设备影子最新更新时间再次进行上报更新,如不一致则丢弃该上报消息。

{
    "method":"reply",
    "messageId":"157889065985",
    "payload":{
        "code":900010,
        "msg":"影子版本冲突。"
    },
    "timestamp":1626317187000
}
字段名称 类型 说明
1 method String 表示设备影子服务下发消息时的方法类型当执行下发期望值是,method 值为 control
2 messageId String 应用程序或设备上报消息时的消息ID,最长为64位字符,设备影子服务下发时将原值发送
3 payload Object 设备影子服务下发消息的内容
4 payload.code Int 表示设备影子处理该请求的状态,为0表示正常,不为0为异常,详看错误码
5 payload.msg String 表示设备影子处理该请求的错误消息
6 timestamp Long unix时间戳毫秒值,表示设备影子文档的最后更新时间,设备端应保存该值,后续更新时进行携带使用

4. 【设备】检测当前值和期望值,执行业务

设备订阅Topic: /${productId}/${deviceId}/shadow/get,接收到设备影子期望值更新消息后,进行检测后执行本地业务更新。

5. 【设备】上报设备影子当前状态

本地业务更新完成后上报当前状态到 Topic:/${productId}/${deviceId}/shadow/update。发送的JSON消息格式:

{
    "method":"update",
    "messageId":"157889065985",
    "state":{
        "reported":{
            "power_setting": {
                "flag": false,
                "config": {
                  "icon": "/test.png"
                }
            }
        }
    },
    "timestamp":1626317187000
}

参数说明

字段名 类型 是否必须 说明
1 method String 表示设备或者应用程序请求设备影子时的操作类型。当执行更新操作时,method为必填字段,设置为update。
2 messageId String 消息ID,最长为64位字符,标识该消息的唯一ID,发送端进行定位消息使用
3 state Object 表示设备发送给设备影子的状态信息。reported为必填字段,状态信息会同步到设备影子的 reported 部分,如该上报字段有对应期望值,设备影子服务在更新上报值的同时,对该字段的期望值进行移除
4 timestamp Long 表示设备影子的最新时间戳,毫秒值。设备影子服务在收到更新请求后。先进行判断是否等于设备影子最新时间戳,不等于则判断是否大于等于该上报字段的metadata中的最后更新时间戳,如不满足,则提示版本冲突,不进行保存。

6. 【设备影子服务】保存设备影子

设备影子收到更新请求后,进行验证更新,更新通过后更新云端的设备影子文档如下:

{
    "state":{
        "desired":{
            "power_setting": {
                "flag": true,
                "config": {
                  "icon": "/test.png"
                }
            }
        },
        "reported":{
            "power_setting": {
                "flag": false,
                "config": {
                  "icon": "/test.png"
                }
            }
        }
    },
    "metadata":{
        "desired":{
            "power_setting":{
                "timestamp":1469565576000
            }
        },
        "reported":{
            "power_setting":{
                "timestamp":1469565576000
            }
        }
    },
    "timestamp":1469565576000
}

设备影子文档说明

字段名 类型 说明
1 state Object 表示设备影子当前状态的信息
2 state.desired Object 表示设备影子中属性的期望值信息
3 state.reported Object 表示设备影子中属性的当前上报值信息
4 metadata Object 表示设备影子当前状态的数据解释信息
5 metadata.desired Object 表示设备影子中属性的期望值元数据信息
6 metadata.reported Object 表示设备影子中属性的当前上报值元数据信息
7 metadata.desired.{flied}.timestamp Long unix时间戳毫秒值,表示设备影子中属性的期望值数据的更新时间, {flied} 为设置的 JSON 第一层结构属性名称
8 metadata.reported.{flied}.timestamp Long unix时间戳毫秒值,表示设备影子中属性的上报值数据的更新时间, {flied} 为设置的 JSON 第一层结构属性名称
9 timestamp Long 时间戳毫秒值,表示设备影子文档的更新时间

7. 【设备影子服务】下发设备当前值更新

设备影子文档更新后,结果发送到Topic: /${productId}/${deviceId}/shadow/get

1)若成功更新,发送到该 Topic 中的消息为:

{
    "method":"update",
    "messageId":"157889065985",
    "payload":{
        "code":0,
        "state":{
            "reported":{
                "power_setting":{
                    "flag":false,
                    "config":{
                        "icon":"/test.png"
                    }
                }
            }
        },
        "metadata":{
            "reported":{
                "color":{
                    "timestamp":1469565576000
                }
            }
        }
    },
    "timestamp":1469565576000
}

2)若更新失败,发送到该 Topic 的消息为:

表示响应失败,并返回具体错误码和错误消息。

{
    "method":"reply",
    "messageId":"157889065985",
    "payload":{
        "code": ${errorcode},
        "msg": "${errormessage}"
     }
}

表示影子版本冲突导致响应失败。设备影子服务会返回云端设备影子更新时间,设备端应保存该设备影子最新更新时间。然后设备端应当检查当前messageId对应的上报数值是否与本地属性值一致,如一致则使用设备影子最新更新时间再次进行上报更新,如不一致则丢弃该上报消息。

{
    "method":"reply",
    "messageId":"157889065985",
    "payload":{
        "code":900010,
        "msg":"影子版本冲突。"
    },
    "timestamp":1469565576000
}
字段名称 类型 说明
1 method String 表示设备影子服务下发消息时的方法类型当执行下发期望值是,method 值为 control
2 messageId String 应用程序或设备上报消息时的消息ID,最长为64位字符,设备影子服务下发时将原值发送
3 payload Object 设备影子服务下发消息的内容
4 payload.code Int 表示设备影子处理该请求的状态,为0表示正常,不为0为异常,详看错误码
5 payload.msg String 表示设备影子处理该请求的错误消息
6 timestamp Long unix时间戳毫秒值,表示设备影子文档的最后更新时间,设备端应保存该值,后续更新时进行携带使用

3.2 应用程序或设备获取设备影子最新状态

1. 【设备或应用程序】重新连接MQTT Broker

应用程序或设备重新联网后,与MQTT Broker 重新建立连接

2.【设备或应用程序】发起获取最新设备影子状态

应用程序或设备发送主动获取设备影子消息到Topic:/${productId}/${deviceId}/shadow/update ,发送的消息格式:

{
  "method":"get",
  "messageId":"157065985"
}

3. 【设备影子服务】查询设备影子最新状态

设备影子服务接收到请求后,查询最新的设备影子文档

4. 【下发设备影子最新状态】

设备影子服务发送设备影子最新状态到Topic: /${productId}/${deviceId}/shadow/get ,发送的消息格式:

{
    "method": "reply",
    "messageId": "157065985",
    "payload": {
        "code": 0,
         "state": {
            "desired": {
                "color": "green"
            },
            "reported": {
                "color": "red"
            }
        },
        "metadata": {
            "desired": {
                "color": {
                    "timestamp": 1469564576000
                }
            },
            "reported": {
                "color": {
                    "timestamp": 1469565576000
                }
            }
        }
    },
    "timestamp": 1469565576000
}

5. 【检查设备影子状态、执行业务】

应用程序或设备获取到设备影子最新状态后,执行业务

3.3 应用程序或设备删除影子信息

1.【应用程序或设备】触发清除设备影子信息逻辑

应用程序或者设备在处理逻辑时,检测到设备影子当前值或期望值已经无效时或需要重置设备影子进行触发清除操作。

2.【应用程序或设备】发送清除设备影子消息

发送清除设备影子消息到到Topic:/${productId}/${deviceId}/shadow/update

清空设备影子信息消息内容如下:

当进行清空或者删除全部上报值或期望值是,设备影子服务判断传递的timestamp是否等于设备影子最新时间戳,如不满足,则提示版本冲突,不进行删除

{
    "method": "clean",
    "messageId":"1241121"
}

清除上报全部属性值消息内容如下:

{
    "method": "delete",
    "messageId":"1241121",
    "state": {
        "reported": "null"
    },
    "timestamp": 1469565576000
}

清除期望全部属性值消息内容如下:

{
    "method": "delete",
    "messageId":"1241121",
    "state": {
        "desired": "null"
    },
    "timestamp": 1469565576000
}

当删除具体属性值时,设备影子服务先进行判断传递的timestamp是否等于设备影子最新时间戳,不等于则判断是否大于等于该字段的metadata中的最后更新时间戳,如不满足,则提示版本冲突,不进行删除

清除上报某一属性值消息内容如下:

{
    "method": "delete",
    "messageId":"1241121",
    "state": {
        "reported": {
            "color": "null"
        }
    },
    "timestamp": 1469565576000
}

清除期望某一属性值消息内容如下:

{
    "method": "delete",
    "messageId":"1241121",
    "state": {
        "desired": {
            "color": "null"
        }
    },
    "timestamp": 1469565576000
}

为满足部分业务在处理完成期望值后,需要将相同key的期望值删除并同时上报上报值的业务,提供一个原子方法同时进行处理。
当进行该业务处理时,设备影子服务先判断传递的timestamp是否等于设备影子最新时间戳,不等于则同时判断是否大于等于该字段上报值和期望值的metadata中的最后更新时间戳,如不满足,则提示版本冲突,不进行处理

删除期望值并更新上报值消息内容如下:

{
    "method": "updateAndDelete",
    "messageId":"1241121",
    "state": {
        "reported": {
            "color": "red"
        }
    },
    "timestamp": 1469565576000
}

删除上报值并更新期望值消息内容如下:

{
    "method": "updateAndDelete",
    "messageId":"1241121",
    "state": {
        "desired": {
            "color": "red"
        }
    },
    "timestamp": 1469565576000
}

3. 【设备影子服务】更新设备影子消息

设备影子服务在接收到更新设备影子消息时,进行更新设备影子文档信息。

{
    "state":{
        "desired":{
        },
        "reported": {
        }
    },
    "metadata":{
        "desired":{
            "color": {
                "timestamp": 1469566876000
             }
         },
        "reported": {
           "color": {
                "timestamp": 1469566876000
             }
        }
    }
    "timestamp":1469566876000
 }

4. 【设备影子服务】返回清除设备影子消息结果

设备影子服务在更新设备影子文档结束后,发送处理结果到Topic:/${productId}/${deviceId}/shadow/get

更新成功返回结果如下:

{
    "method":"reply",
    "messageId":"1241121",
    "payload":{
        "code":0
    }
}

更新失败返回结果如下:

{
    "method":"reply",
    "messageId":"1241121",
    "payload":{
        "code": ${errorcode},
        "msg": "${errormessage}"
     }
}

3.4 应用程序或设备设置影子错误信息

1. 【应用程序】执行业务,设置期望值

应用程序在执行相应业务后,对属性期望值进行更新。

2. 【应用程序】发送设置期望值信息

进行设置期望值动作,动作内容同本文档中3.1.1示例,

3. 【设备影子服务】更新设备影子信息

设备影子服务在收到应用程序设备期望值信息后,保存到设备影子中,动作内容同本文档中3.1.2示例

4. 【设备影子服务】广播期望值更新信息

设备影子服务保存期望到设备影子后,进行广播期望值更新信息,动作内容同本文档中3.1.3示例

5. 【设备】获取期望值信息后执行业务,发现期望值无法执行

设备在获取到期望值的更新后,根据设置的期望值进行执行业务,发现期望值数据因某种原因无法执行成功。

6. 【设备】上报期望值错误信息

设备更新错误信息到 Topic:/${productId}/${deviceId}/shadow/update。发送的JSON消息格式:

{
    "method":"setError",
    "messageId":"157889065987",
    "state":{
        "desired":{
            //对应执行错误的字段,错误信息由业务决定
            "power_setting": {
              "code": 1
            }
        }
    },
    "timestamp":1469566876000
}

参数说明

字段名 类型 是否必须 说明
1 method String 表示设备或者应用程序请求设备影子时的操作类型。当执行设置错误操作时,method设置为setError。
2 messageId String 消息ID,最长为64位字符,标识该消息的唯一ID,发送端进行定位消息使用
3 state Object 表示设备和应用程序发送给设备影子的状态信息
5 state.desired Object 表示设备或应用程序要设置期望值的错误信息,如设置上报值,则为state.reported
5 state.desired.{flied} Object 表示要设置错误信息的字段名称,值为对应错误信息,由业务进行定义
4 timestamp Long 表示设备影子的最新时间戳,unix时间戳毫秒值。设备影子服务在收到更新请求后。先进行判断是否等于设备影子最新时间戳,不等于则判断是否大于等于该字段的metadata中的最后更新时间戳,如不满足,则提示版本冲突,不进行保存。

7. 【设备影子服务】更新设备影子信息

设备影子服务在接受到上报错误信息后,将其保存到设备影子中。

{
    "state":{
        "desired":{
            "power_setting": {
                "flag": true,
                "config": {
                  "icon": "/test.png"
                }
            }
        }
    },
    "metadata":{
        "desired":{
            "power_setting": {
                "timestamp": 1469564586000,
                //该字段的错误信息
                "error":{
                    "code": 1
                }
             }
         }
    }
    "timestamp":1469564576000,
 }

设备影子文档说明

字段名 类型 说明
1 state Object 表示设备影子当前状态的信息
2 state.desired Object 表示设备影子中属性的期望值信息
3 metadata Object 表示设备影子当前状态的元数据信息
4 metadata.desired Object 表示设备影子中属性的期望值元数据信息
5 metadata.desired.{flied}.timestamp Long 时间戳毫秒值,表示设备影子中属性的期望值数据的更新时间, {flied} 为设置的 JSON 第一层结构属性名称
6 metadata.desired.{flied}.error Object 错误描述信息,具体值和格式由业务决定,只有在进行设置错误信息后才有该值,{flied} 为设置的 JSON 第一层结构属性名称
7 timestamp Long 时间戳毫秒值,表示设备影子文档的更新时间

8. 【设备影子服务】广播期望值错误信息更新

设备影子文档更新后,结果发送到Topic: /${productId}/${deviceId}/shadow/get

1)若成功更新,发送到该 Topic 中的消息为:

{
    "method":"setError",
    "messageId":"157889065987",
    "payload":{
        "code":0,
        "state":{
            "desired":{
                "power_setting":{
                    "flag":true,
                    "config":{
                        "icon":"/test.png"
                    }
                }
            }
        },
        "metadata":{
            "desired":{
                "color":{
                    "timestamp":1469565576000,
                    "error": {
                        "code": 1
                    }
                }
            }
        }
    },
    "timestamp":1469565596000
}

2)若更新失败,发送到该 Topic 的消息为:

表示响应失败,并返回具体错误码和错误消息。

{
    "method":"reply",
    "messageId":"157889065987",
    "payload":{
        "code": ${errorcode},
        "msg": "${errormessage}"
     }
}

表示影子版本冲突导致响应失败。设备影子服务会返回云端设备影子更新时间,设备端应保存该设备影子最新更新时间。然后设备端应当检查当前messageId对应的上报数值是否与本地属性值一致,如一致则使用设备影子最新更新时间再次进行上报更新,如不一致则丢弃该上报消息。

{
    "method":"reply",
    "messageId":"157889065987",
    "payload":{
        "code":900010,
        "msg":"影子版本冲突。"
    },
    "timestamp":1469565596000
}
字段名称 类型 说明
1 method String 表示设备影子服务下发消息时的方法类型当执行下发期望值是,method 值为 control
2 messageId String 应用程序或设备上报消息时的消息ID,最长为64位字符,设备影子服务下发时将原值发送
3 payload Object 设备影子服务下发消息的内容
4 payload.code Int 表示设备影子处理该请求的状态,为0表示正常,不为0为异常,详看错误码
5 payload.msg String 表示设备影子处理该请求的错误消息
6 timestamp Long unix时间戳毫秒值,表示设备影子文档的最后更新时间,设备端应保存该值,后续更新时进行携带使用

9. 【应用程序】获取到设置错误广播消息,执行业务

应用程序在获取到设置错误的广播消息之后,根据错误信息进行对应业务的执行

10. 【应用程序】更新错误期望值信息

进行设置期望值动作,动作内容同本文档中3.1.1示例

11. 【设备影子服务】更新设备影子信息

设备影子服务在收到应用程序设备期望值信息后,保存到设备影子中,动作内容同本文档中3.1.2示例

四、错误码

errorCode errorMessage
900001 不正确的JSON格式。
900002 影子数据缺少method信息。
900003 影子数据缺少state字段。
900004 影子数据中timestamp值不是数字。
900005 影子数据缺少reported与desired字段。
900006 影子数据中 reported或desired属性字段为空。
900007 影子数据中 method是无效的方法。
900008 影子内容为空。
900009 影子数据中 reported或desired属性字段不能同时更新
900010 影子版本冲突。
900011 消息ID不存在
900012 消息ID长度不符合
900016 字段值不存在
900017 影子数据缺少timestamp字段
500 服务端处理异常。

五、method枚举

/${productId}/${deviceId}/shadow/update Topic 使用method:

method名称 说明
update 表示应用程序或设备更新设备影子文档信息
get 表示应用程序或设备获取设备影子文档最新信息
delete 表示应用程序或设备删除设备影子文档信息
setError 表示应用程序或设备设置设备影子的错误信息
updateAndDelete 表示应用程序或设备更新并删除设备影子文档信息
clean 表示应用程序或设备清空设备影子信息

/${productId}/${deviceId}/shadow/get Topic 使用method:

method名称 说明
update 表示设备影子上报值被更新
control 表示设备影子期望值被更新
reply 表示设备影子服务对应用程序或设备的请求进行响应
setError 表示设备影子上报值或期望值有错误信息更新
 创建时间:2023-03-23 19:37
最后编辑:陈勇琦  更新时间:2024-10-18 10:58