# 属性下发
#### 概述
属性下发分为查询设备属性和修改属性参数两种，查询设备属性用于应用侧或平台主动获取设备属性数据，修改属性参数用于应用侧或平台设置设备属性值并同步到设备侧。设备接收到属性下发指令后需要立即响应，如果设备没有响应，平台会认为属性下发执行超时。
#### 使用场景
- 用于平台主动获取或修改设备属性值。
- 平台规范、解析、过滤的数据。
 
#### 使用限制
- 单个消息内容不大于64K。
- 需要定义[产品模型](https://support.huaweicloud.com/devg-iothub/iot_02_0005.html)。
 
#### 相关API接口
- [平台设置设备属性](https://support.huaweicloud.com/api-iothub/iot_06_v5_3008.html)
- [平台查询设备属性](https://support.huaweicloud.com/api-iothub/iot_06_v5_3011.html)
 
#### 属性下发使用说明
属性下发分为修改属性与获取属性值，下列以修改属性为例，介绍属性下发。
图1属性下发流程图   
![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001874203614.png "点击放大")
1. 应用调用[修改设备属性](https://support.huaweicloud.com/api-iothub/iot_06_v5_0035.html)接口，下发请求到物联网平台，属性下发消息样例如下：
   ```
   PUT https://{endpoint}/v5/iot/{project_id}/devices/{device_id}/properties  
   {   
       "services" : [ {     
           "service_id" : "Temperature",     
           "properties" : {
               "value" : 57     
           }  
        }, {     
           "service_id" : "Battery",     
           "properties" : { 
               "level" : 80     
           }   
       } ] 
   }
   ```
   
2. 物联网平台根据协议规范下发属性给设备。通过MQTT协议中[平台设置设备属性](https://support.huaweicloud.com/api-iothub/iot_06_v5_3008.html)接口下发属性为样例：
   ```
   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
               }
           }
       ]
   }
   ```
   
3. 设备执行属性下发命令后返回命令执行结果，消息样例如下：
   ```
   Topic：$oc/devices/{device_id}/sys/properties/set/response/request_id={request_id} 
   数据格式：
   {
       "result_code": 0,
       "result_desc": "success"
   }
   ```
   
4. 应用侧收到发送HTTP下发命令的同步响应结果。消息样例如下：
   ```
   Status Code: 200 OK
   Content-Type: application/json
   {   
       "response" : {     
           "result_code" : 0,     
           "result_desc" : "success"   
       } 
   }
   ```
   
 
#### 属性下发Java SDK使用示例
本部分介绍如何使用JAVA SDK进行属性配置的开发。SDK代码获取：[SDK下载](https://support.huaweicloud.com/sdkreference-iothub/iot_10_1002.html)。本示例使用的开发环境为JDK 1.8及以上版本。
配置应用侧SDK步骤如下：
1. 配置Maven依赖。 
   ```
   <dependency>
       <groupId>com.huaweicloud.sdk</groupId>
       <artifactId>huaweicloud-sdk-core</artifactId>
       <version>[3.0.40-rc, 3.2.0)</version>
   </dependency>
   <dependency>
       <groupId>com.huaweicloud.sdk</groupId>
       <artifactId>huaweicloud-sdk-iotda</artifactId>
       <version>[3.0.40-rc, 3.2.0)</version>
   </dependency>
   ```
   
   
2. 应用侧设置某个设备的属性值，样例如下： 
   ```
   public class AttributeDistributionSolution {
       // REGION_ID：如果是上海一，请填写"cn-east-3"；如果是北京四，请填写"cn-north-4";如果是华南广州，请填写"cn-south-4"
       private static final String REGION_ID = "<YOUR REGION ID>";
       // ENDPOINT：请在控制台的"总览"界面的"平台接入地址"中查看“应用侧”的https接入地址。
       private static final String ENDPOINT = "<YOUR ENDPOINT>";
       // 标准版/企业版：需自行创建Region对象
       public static final Region REGION_CN_NORTH_4 = new Region(REGION_ID, ENDPOINT);
       public static void main(String[] args) {
           String ak = "<YOUR AK>";
           String sk = "<YOUR SK>";
           String projectId = "<YOUR PROJECTID>";
           // 创建认证
           ICredential auth = new BasicCredentials().withDerivedPredicate(AbstractCredentials.DEFAULT_DERIVED_PREDICATE)
               .withAk(ak)
               .withSk(sk)
               .withProjectId(projectId);
           // 创建IoTDAClient实例并初始化
           IoTDAClient client = IoTDAClient.newBuilder().withCredential(auth)
               // 基础版：请选择IoTDARegion中的Region对象
               //.withRegion(IoTDARegion.CN_NORTH_4)
               // 标准版/企业版：需自行创建Region对象
               .withRegion(REGION_CN_NORTH_4).build();
           // 实例化请求对象
           UpdatePropertiesRequest request = new UpdatePropertiesRequest();
           request.withDeviceId("<YOUR DEVICE_ID>");
           DevicePropertiesRequest body = new DevicePropertiesRequest();
           body.withServices("[{\"service_id\":\"smokeDetector\",\"properties\":{\"alarm\":\"hello\"," +
                   "\"temperature\":10.323,\"humidity\":654.32,\"smokeConcentration\":342.4}}]");
           request.withBody(body);
           try {
               UpdatePropertiesResponse response = client.updateProperties(request);
               System.out.println(response.toString());
           } catch (ConnectionException e) {
               e.printStackTrace();
           } catch (RequestTimeoutException e) {
               e.printStackTrace();
           } catch (ServiceResponseException e) {
               e.printStackTrace();
               System.out.println(e.getHttpStatusCode());
               System.out.println(e.getRequestId());
               System.out.println(e.getErrorCode());
               System.out.println(e.getErrorMsg());
           }
       }
   }
   ```
   表1参数说明 
   | 参数                      | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   |:---|:---|
   | ak                     | 您的华为云账号访问密钥ID（Access Key ID）。请在华为云控制台"我的凭证 \> 访问密钥"页面上创建和查看您的 AK/SK。更多信息请查看[访问密钥](https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html)。                                                                                                                                                                                                                                                                                                                             |
   | sk                     | 您的华为云账号秘密访问密钥（Secret Access Key）。                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   | projectId               | 项目ID。获取方法请参见[获取项目ID](https://support.huaweicloud.com/api-iothub/iot_06_v5_1001.html)。                                                                                                                                                                                                                                                                                                                                                                                          |
   | IoTDARegion.CN_NORTH_4 | 请替换为您要访问的物联网平台的区域，当前物联网平台可以访问的区域，在SDK代码[IoTDARegion.java](https://github.com/huaweicloud/huaweicloud-sdk-java-v3/tree/master/services/iotda/src/main/java/com/huaweicloud/sdk/iotda/v5/region/IoTDARegion.java)中已经定义。 您可以在控制台上查看当前服务所在区域名称，区域名称、区域和终端节点的对应关系，具体步骤请参考[平台对接信息](https://support.huaweicloud.com/usermanual-iothub/iot_01_01271.html#ZH-CN_TOPIC_0000001514571325__section436212919379)。 |
   | REGION_ID              | 请替换为您要访问的物联网平台的区域。如果是上海一，请填写"cn-east-3"；如果是北京四，请填写"cn-north-4";如果是华南广州，请填写"cn-south-4"。                                                                                                                                                                                                                                                                                                                                                                                         |
   | ENDPOINT                 | 请在控制台的"总览"界面的"接入信息"中查看"应用接入"的https接入地址。                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   | DEVICE_ID              | 下发消息的设备ID，用于唯一标识一个设备，在注册设备时由物联网平台分配获得。 取值范围：长度不超过128，只允许字母、数字、下划线（_）、连接符（-）的组合。                                                                                                                                                                                                                                                                                                                                                                                                |
      
   
   
 
#### 配置设备侧SDK
1. 配置设备侧SDK的Maven依赖。 
   ```
   <dependency>
   <groupId>com.huaweicloud</groupId>
   <artifactId>iot-device-sdk-java</artifactId>
   <version>1.1.4</version>
   </dependency>
   ```
   
   
2. 配置设备侧SDK，设备连接参数。 
   ```
   //加载iot平台的ca证书，获取链接参考：证书资源。
   URL resource = AttributeSample.class.getClassLoader().getResource("ca.jks");
   File file = new File(resource.getPath());
   //注意格式为：ssl://域名信息:端口号。
   //域名获取方式：登录华为云IoTDA控制台左侧导航栏“总览”页签，在选择的实例基本信息中，单击“接入信息”。选择8883端口对应的接入域名。
   String serverUrl = "ssl://<localhost>:8883";
   //在IoT平台创建的设备ID。
   String deviceId = "<deviceId>";
   //设备ID对应的密钥。
   String deviceSecret = "<secret>";
   //创建设备
   IoTDevice device = new IoTDevice(serverUrl, deviceId, deviceSecret, file);
   if (device.init() != 0) {
       return;
   }
   ```
   
   
3. 定义属性下发回调函数。 
   ```
   device.getClient().setPropertyListener(new PropertyListener() {
       //处理写属性
       @Override
       public void onPropertiesSet(String requestId, List<ServiceProperty> services) {
           //遍历service
           for (ServiceProperty serviceProperty: services){
               log.info("OnPropertiesSet, serviceId =  " + serviceProperty.getServiceId());
               //遍历属性
               for (String name :serviceProperty.getProperties().keySet()){
                   log.info("property name = "+ name);
                   log.info("set property value = "+ serviceProperty.getProperties().get(name));
                   if (name.equals("alarm")){
                       //修改本地值
                       alarm = (Integer) serviceProperty.getProperties().get(name);
                   }
               }
           }
           //设置属性响应
           device.getClient().respondPropsSet(requestId, IotResult.SUCCESS);
       }
       //处理读属性
       @Override
       public void onPropertiesGet(String requestId, String serviceId) {
           log.info("OnPropertiesGet " + serviceId);
           Map<String ,Object> json = new HashMap<>();
           Random rand = new Random();
           json.put("alarm", alarm);
           json.put("temperature", rand.nextFloat()*100.0f);
           json.put("humidity", rand.nextFloat()*100.0f);
           json.put("smokeConcentration", rand.nextFloat() * 100.0f);
           ServiceProperty serviceProperty = new ServiceProperty();
           serviceProperty.setProperties(json);
           serviceProperty.setServiceId("smokeDetector");
           
           //上报读属性响应
           device.getClient().respondPropsGet(requestId, Arrays.asList(serviceProperty));
       }
   });
   ```
   
   
 
#### 测试验证
1. 在设备接入控制台，选择您的实例，单击实例卡片进入。选择左侧导航栏的"设备 \> 所有设备"，单击具体设备"详情"进入设备详情，在"消息跟踪"页签内，启动"消息跟踪"。 
   图2消息跟踪-启动消息跟踪   
   ![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001950378340.png "点击放大")
   
   
2. 运行设备侧 SDK代码，使设备上线。
3. 运行应用侧SDK代码，调用修改设备属性接口向设备发送请求，设备侧收到的结果如下： 
   图3处理修改属性设备侧结果   
   ![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001890919830.png "点击放大")
   
   
4. "消息跟踪"查看下发结果。 
   图4消息跟踪-属性下发   
   ![](https://support.huaweicloud.com/usermanual-iothub/figure/zh-cn_image_0000001982096441.png "点击放大")
   
   
 
