# 设备影子
#### 概述
物联网平台支持创建设备的"影子"。设备影子是一个JSON文件，用于存储设备的在线状态、设备最近一次上报的设备属性值、应用服务器期望下发的配置。每个设备有且只有一个设备影子，设备可以获取和设置设备影子以此来同步设备属性值，这个同步可以是影子同步给设备，也可以是设备同步给影子。
设备影子上有desired区和reported区。
- desired区用于存储对设备属性的配置，即期望值。当需要修改设备的服务属性值时，可修改设备影子的desired区的属性值，设备在线时，desired属性值立即同步到设备。如果设备不在线，待设备上线或上报数据时，desired属性值同步到设备。
- reported区用于存储设备最新上报的设备属性值，即上报值。当设备上报数据时，平台刷新reported区属性值为设备上报的设备属性值。
  ![](https://support.huaweicloud.com/usermanual-iothub/public_sys-resources/note_3.0-zh-cn.png)
  - 设备影子可以通过调用应用侧API接口配置，也可以通过登录控制台，在设备详情-\>设备影子-\>属性配置页面配置。（设备影子主要针对设备属性配置，它的配置依赖[产品模型](https://support.huaweicloud.com/usermanual-iothub/iot_01_0054.html#ZH-CN_TOPIC_0221225203__section5477105165913)）。
  
  - 设备影子配置属于异步命令，物联网平台会直接回复配置响应，然后平台通过设备在线状态，决定立即下发还是缓存下发。
  
  - 设备上线后，影子服务会下发desired值给设备，待设备属性上报时，影子服务检查属性值与下发的desired值是否匹配。若匹配，则说明影子数据在设备侧配置成功，缓存清除；若不匹配，则说明影子数据在设备侧未配置成功，在下次设备上线或属性上报时，会继续下发缓存desired值给设备，直到下发配置成功。
  
  - 限制：设备影子JSON文档中的key不允许特殊字符：点(.)、dollar符号($)、空char(十六进制的ASCII码为00)。如果包含了以上特殊字符则无法正常刷新影子文档。
  
  - 设备影子desired配置给设备后，需要设备回响应表示已收到请求。如果设备不回响应(平台则认为设备侧未适配影子设置流程，[平台设置设备属性](https://support.huaweicloud.com/api-iothub/iot_06_v5_3008.html))，则平台有个5 分钟的保护期，避免过多流量冲击设备，保护期内设备属性上报时，平台比对reported和desired即使有差异，也不会下发差值。设备正常适配下发流程中的属性设置响应，平台则每次属性上报都会将差值下发给设备。
  
  - 设备影子中的属性需要在产品中定义才能使用，设备上报非产品中定义的属性可能会被设备影子丢弃。
  
  - 当产品属性变化时（如属性删除，名称变化时），设备影子不会联动删除。
  
  - 设备影子适用于低频率上报的场景，设备频繁上报（超过1tps）的场景可能会导致设备影子刷新不准确。
   
  ![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001223315322.png "点击放大")
  
 
#### 应用场景
适合资源受限低功耗设备，长期处于休眠状态的场景。
- 查询设备最新上报数据和设备最新在线状态：
  - 当在控制台上查询设备上报数据时，由于设备可能长时间处于离线状态或因网络不稳定掉线，而无法获取到最新数据。通过设备影子机制，设备影子中始终保持设备最新上报的数据和设备当前状态，控制台上只需要查询设备影子中存储的数据，即可获取设备最新上报的数据和设备状态。
    
  
  - 很多应用服务器频繁地查询设备在线状态，由于设备处理能力有限，频繁查询会损耗设备性能。使用设备影子机制，设备只需要主动同步状态给设备影子一次，多个应用程序请求设备影子获取设备状态，即可获取设备最新状态，从而将应用程序和设备解耦。
    
- 修改设备属性值：用户通过"设备 \> 设备详情 \> 设备影子"修改设备的属性值。由于设备可能长时间处于离线状态，修改设备属性值的操作不能及时下发给设备。在这种情况下，物联网平台可以将修改设备的属性信息存储在设备影子中，待设备上线后，将修改的设备属性值同步给设备，从而完成设备属性值的修改。
  
 
#### 业务流程
**修改设备属性值**
修改desired区属性值，如果设备在线，则设备影子直接同步设备属性值到设备，否则等待设备上线或上报数据时，再同步设备属性值到设备。
![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001223795254.png "点击放大")
1. 用户通过控制台或应用服务器修改设备属性值。消息样例如下：
   ```
   PUT https://{Endpoint}/v5/iot/{project_id}/devices/{device_id}/shadow
   Content-Type: application/json
   X-Auth-Token: ********
   Instance-Id: ********
   {
     "shadow" : [ {
       "desired" : {
         "temperature" : "60"
       },
       "service_id" : "WaterMeter",
       "version" : 1
     } ]
   }
   ```
   
2. 物联网平台修改desired区属性值。
3. 物联网平台返回响应消息。
4. 物联网平台判断设备上线或上报数据。
5. 物联网平台将设备属性同步到设备。消息样例如下：
   ```
   Topic: $oc/devices/{device_id}/sys/properties/set/request_id={request_id} 
   数据格式：  
   {
       "object_device_id": "{object_device_id} ",
       "services": [
           {
               "service_id": "Temperature",
               "properties": {
                   "value": 57,
                   "value2": 60
               }
           },
           {
               "service_id": "Battery",
               "properties": {
                   "level": 80,
                   "level2": 90
               }
           }
       ]
   }
   ```
   
6. 设备返回响应消息。设备影子desired区的属性值发送给设备后，需要设备回响应表示已收到请求。消息样例如下：
   ```
   Topic：$oc/devices/{device_id}/sys/properties/set/response/request_id={request_id}
   数据格式：  
   {
       "result_code": 0,
       "result_desc": "success"
   }
   ```
   
7.设备上报数据，当设备进行属性上报时，平台会存储设备最新上报的设备属性值。
- 设备上报属性时，物联网平台修改设备影子reported区属性值为设备上报的设备属性值。消息样例如下：
```
Topic: $oc/devices/{device_id}/sys/properties/report   
数据格式：
{
    "services": [
        {
            "service_id": "Temperature",
            "properties": {
                "value": 57,
                "value2": 60
            },
            "event_time": "20151212T121212Z"
        },
        {
            "service_id": "Battery",
            "properties": {
                "level": 80,
                "level2": 90
            },
            "event_time": "20151212T121212Z"
        }
    ]
}
```
- 设备主动删除设备影子的reported区
  - 设备主动删除reported区service下的单个属性
    设备上报属性时，将属性设置为null，平台会将该属性从设备影子reported区删除，消息样例如下：
    ```
    Topic: $oc/devices/{device_id}/sys/properties/report  
    {
        "services": [
            {
                "service_id": "Temperature",
                "properties": {
                    "value": null,
                    "value2": 60
                },
                "event_time": "20151212T121212Z"
            }
        ]
    }
    ```
    
  
  - 设备主动删除影子reported区的service下的全部的属性
    设备上报属性时，将service对应的properties设置为{}时，平台会将reported区该service模块下所有属性从设备影子reported区删除，消息样例如下:
    ```
    Topic: $oc/devices/{device_id}/sys/properties/report 
    {
        "services": [
            {
                "service_id": "Temperature",
                "properties": {},
                "event_time": "20151212T121212Z"
            }
        ]
    }
    ```
    
   
**查询设备属性值**
设备影子保存的是设备最新的设备属性值，一旦设备属性值产生变化，设备会将设备属性值同步到设备影子。用户便可以及时获取查询结果，无需关注设备是否在线。
![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001223635270.png "点击放大")
1. 用户通过控制台或应用服务器查询设备属性值。消息样例如下：
   ```
   GET https://{Endpoint}/v5/iot/{project_id}/devices/{device_id}/shadow
   Content-Type: application/json
   X-Auth-Token: ********
   Instance-Id: ********
   ```
   
2. 物联网平台返回desired属性值和report属性值，即期望值和上报值。消息样例如下： Status Code: 200 OK
   ```
   Content-Type: application/json
   {
     "device_id" : "********",
     "shadow" : [ {
       "desired" : {
         "properties" : {
           "temperature" : "60"
         },
         "event_time" : "20151212T121212Z"
       },
       "service_id" : "WaterMeter",
       "reported" : {
         "properties" : {
           "temperature" : "60"
         },
         "event_time" : "20151212T121212Z"
       },
       "version" : 1
     } ]
   }
   ```
   
 
#### 查询、修改、删除设备影子
**查询设备影子**
方法1：应用服务器调用[查询设备影子数据](https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html)接口。
方法2：登录[管理控制台](https://console.huaweicloud.com/iotdm/#/dm-portal/home)，选择您的实例，单击实例卡片进入。在左侧导航栏选择"设备"，单击具体的设备进入到设备的详情页面，在"设备影子"页签中，可以查看当前设备属性数据，包括"上报值"和"期望值"。
- 如果当前界面中看到"上报值"与"期望值"不一致，原因可能是设备未在线，暂时存储在设备影子中，待同步给设备，期望值会存在深色底纹。
- 如果当前界面看到的"上报值"与"期望值"一致，则表示设备最近一次上报的属性值与用户期望下发的属性值一致，期望值为白色底纹。
  图1设备影子-查看   
  ![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001950378316.png "点击放大") 
 
**修改设备影子**
方法1：应用服务器调用[配置设备影子预期数据](https://support.huaweicloud.com/api-iothub/iot_06_v5_0072.html)接口。
方法2：登录[管理控制台](https://console.huaweicloud.com/iotdm/#/dm-portal/home)，选择您的实例，单击实例卡片进入。在左侧导航栏选择"设备-所有设备"，在设备列表中单击具体的设备进入到设备的详情页面，在"设备影子"页面，单击"属性配置"，在弹出窗口中输入服务属性对应的期望值，单击"确定"完成设备影子的修改。
图2设备影子-属性配置   
![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001981577901.png "点击放大")
**删除设备影子**
用户删除设备影子，平台将会将设备影子中的所有数据（包含上报值和期望值）清空。
图3删除设备影子   
![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000002041303274.png "点击放大")
#### 相关API接口
[查询设备影子数据](https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html)
[配置设备影子预期数据](https://support.huaweicloud.com/api-iothub/iot_06_v5_0072.html)
