
# 快速接入
本章将使用SmokeDetector Demo 指导您快速体验产品模型的创建、Demo的配置与启动、以及SDK基本功能的使用。为了方便体验，提供了一个烟感的产品模型，烟感会上报烟雾值、温度、湿度、烟雾报警、还支持响铃报警命令。 以烟感例，体验消息上报、属性上报、命令响应等功能。
#### 创建产品
为了方便体验，提供了一个烟感的产品模型，烟感会上报烟雾值、温度、湿度、烟雾报警、还支持响铃报警命令。以烟感为例，体验消息上报、属性上报等功能。
1. 访问[设备接入服务](https://www.huaweicloud.com/product/iothub.html)，单击"管理控制台"进入设备接入控制台，选择您的实例，单击实例卡片进入。
2. 单击左侧导航栏"产品"，单击页面左侧的"创建产品"。 
   图1产品-创建产品   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002358714305.png "点击放大")
   
   
3. 根据页面提示填写参数，然后单击"确定"完成产品的创建。 
   
   |                                                                     **基本信息**                                                                     ||
   |---|---|
   | 所属资源空间 | 平台自动将新创建的产品归属在默认资源空间下。如需归属在其他资源空间下，下拉选择所属的资源空间。如无对应的资源空间，请先创建[资源空间](https://support.huaweicloud.com/usermanual-iothub/iot_01_0006.html)。 |
   | 产品名称   | 自定义。支持字母、数字、下划线（_）、连字符（-）的字符组合。                                                                                                          |
   | 协议类型   | 选择"MQTT"。                                                                                                                                |
   | 数据格式   | 选择"JSON"。                                                                                                                                |
   | 设备类型选择 | 选择"自定义类型"                                                                                                                                |
   | 设备类型   | 填写"smokeDetector"                                                                                                                        |
   | **高级配置**                                                                                                                                         ||
   | 产品ID   | 不填写                                                                                                                                      |
   | 产品描述   | 请根据实际情况填写。                                                                                                                               |
      
   图2创建产品-MQTT   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001981306829.png "点击放大")
   
   
 
#### 上传产品模型
1. 单击下载烟感产品模型[smokeDetector](https://iot-developer.obs.cn-north-4.myhuaweicloud.com:443/smokeDetector.zip)，获取产品模型文件。
2. 找到创建的产品，单击产品进入产品详情页。
3. 选择"基本信息"页签，单击"上传模型文件"，上传[1]获取的产品模型文件。
   
   图3产品-上传产品模型   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001981312633.png "点击放大")
   
   
 
#### 注册设备
1. 选择左侧导航栏"设备 \> 所有设备"，单击"注册设备"。
2. 根据页面提示信息填写参数，然后单击"确定"。 
   
   | 参数名称   | 说明                                |
   |:---|:---|
   | 所属资源空间 | 确保和创建的产品归属在同一个资源空间。               |
   | 所属产品   | 选择创建的产品。                          |
   | 设备标识码  | 即nodeID，设备唯一物理标识。可自定义，由英文字母和数字组成。 |
   | 设备名称   | 即device_name，可自定义。                |
   | 设备认证类型 | 选择"密钥"。                           |
   | 密钥     | 设备密钥，可自定义。若不填写密钥，物联网平台会自动生成密钥。    |
      
   设备注册成功后保存设备标识码、设备ID、密钥。
   
   
 
#### 设备初始化
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
设备初始化Demo，可参考[entry/src/main/ets/pages/Index.ets](https://github.com/huaweicloud/huaweicloud-iot-device-sdk-arkts/blob/main/entry/src/main/ets/pages/Index.ets)。
1. 获取接入地址。可在控制台的"总览 \> 接入信息"中查看。
   图4接入信息-设备侧MQTT接入地址   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002379668860.png "点击放大") 
2. 创建设备需要输入获取的设备ID、密码以及设备MQTT接入地址，注意格式为***ssl://域名信息:端口号*** 或 ***ssl://IP地址:端口号*** ，填入初始化方法内。
   ```
   private device: IoTDevice | null = null;
   // 用户请替换为自己的接入地址, 设备ID，设备密钥及证书路径（证书文件放在resource/resfile下，连接华为云时请使用对应的证书，可以在资源获取中下载证书文件）。
   this.device = new IoTDevice("ssl://域名信息:8883","deviceId","mySecret","filePath");
   ```
   
3. 调用init建立连接。您可以使用异步或同步方式初始化。
   ```
   // 使用异步方式初始化
   this.device.init().then((data: boolean) => {
     // 连接成功处理
   }).catch((err: string) => {
     // 连接失败处理
   })
   // 或使用同步方式初始化
   // await this.device.init();
   ```
   
4. 查看设备日志打印，设备连接成功。
   ```
   IoTDA_SDK# connect result is {"code":0,"message":"Connect Success"}
   ```
   
5. 创建设备并连接成功后，可以开始进行设备通信。调用IoT Device 的client接口获取设备客户端，客户端提供了消息、属性、命令等通讯接口。
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/notice_3.0-zh-cn.png)
SDK默认提供断线重连功能，当调用device.init（）后，当由于网络不稳定、网络不可达、平台主动断开连接等，导致连接失败，会在后台自动申请重连。若是客户不需要该机制，请见：[断线重连](https://github.com/huaweicloud/huaweicloud-iot-device-sdk-arkts/blob/main/huaweicloud_iot_device_library/README.md#3.2)文档。
#### 消息上报
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
消息上报Demo，可参考entry/src/main/ets/pages/MessageSample.ets。
消息上报是指设备向平台上报消息。
1. 在初始化并连接平台成功后，调用客户端的reportDeviceMessage接口上报设备消息，publishRawMessage上报自定义Topic的消息。
   ```
   // 上报系统topic消息  
     const reportMessage: DeviceMessage = { content: this.message }
     this.device.client.reportDeviceMessage(reportMessage)
       .then((data: IoTMqttResponse) => {
         LogUtil.info(TAG, `report deviceMessage success ${JSON.stringify(data)}. DeviceMessage is ${JSON.stringify(reportMessage)}`);
       })
       .catch((error: IoTMqttResponse | string) => {
         LogUtil.error(TAG, `report deviceMessage failed ${JSON.stringify(error)}`);
       })
     // 上报自定义topic消息（$oc开头，注意需要先在平台配置自定义topic）
     const topic = `$oc/devices/${this.device?.deviceId}/user/test`;
     const rawMessage: RawMessage = {
       topic: topic,
       qos: 0,
       payload: this.message
     }
     this.device?.client.publishRawMessage((rawMessage)).then((res: IoTMqttResponse) => {
       LogUtil.info(TAG, `publish rawMessage(${rawMessage.topic}) success, message is ${JSON.stringify(rawMessage)}}`);
     }).catch((error: IoTMqttResponse | string) => {
       LogUtil.error(TAG, `publish rawMessage(${rawMessage.topic}) failed, error is ${JSON.stringify(error)}}`);
     });
     // 上报自定义topic消息（非$oc开头，可用设备topic策略控制权限）
     const topic = "hello/world";
     const rawMessage: RawMessage = {
       topic: topic,
       qos: 0,
       payload: this.message
     }
     this.device?.client.publishRawMessage((rawMessage)).then((res: IoTMqttResponse) => {
       LogUtil.info(TAG, `publish rawMessage(${rawMessage.topic}) success, message is ${JSON.stringify(rawMessage)}}`);
     }).catch((error: IoTMqttResponse | string) => {
       LogUtil.error(TAG, `publish rawMessage(${rawMessage.topic}) failed, error is ${JSON.stringify(error)}}`);
     });
   ```
   
2. 上报成功，查看日志发送消息成功。
   图5上报系统Topic消息日志   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002310940452.png "点击放大")
   图6上报自定义Topic（$oc开头) 消息日志   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002344979261.png "点击放大")
   图7上报自定义Topic（非$oc开头）消息日志   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002345099437.png "点击放大") 
3. 在设备接入控制台，选择"设备 \> 所有设备"-查看设备是否在线。
   图8设备列表-设备在线   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001950367902.png "点击放大") 
4. 选择对应设备，单击"详情"，进入设备详情页面启动设备消息跟踪。
   图9消息跟踪-启动消息跟踪   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001950378340.png "点击放大") 
5. 消息跟踪显示平台成功接收到设备的消息。
   图10消息跟踪-查看device_sdk_java消息跟踪   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001981497769.png "点击放大")
   ![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/notice_3.0-zh-cn.png)
   消息跟踪会有一定的延时，如果没有看到数据，请等待后刷新。
   
 
#### 属性上报
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
属性上报Demo，可参考entry/src/main/ets/pages/PropertySample.ets文件。
1. 在初始化并连接平台成功后，调用客户端的reportProperties接口上报设备属性。
```
const properties: ServiceProperty[] = 
[
  {
"service_id": "smokeDetector",
"properties": {
  "alarm": 1,
  "temperature": Math.random() * 100,
  "humidity": Math.random() * 100,
  "smokeConcentration": Math.random() * 100,
}
  }
]
;
this.device.client.reportProperties(properties)
  .then((data: IoTMqttResponse) => {
LogUtil.info(TAG, `report properties success ${JSON.stringify(data)}, properties is ${JSON.stringify(properties)}}`);  })
  .catch((error: IoTMqttResponse | string) => {
LogUtil.error(TAG, `report properties failed ${JSON.stringify(error)}`);
  })
```
2. 上报成功，查看日志发送属性成功。
图11上报属性日志   
![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002311100224.png "点击放大")
3. 在设备接入控制台，选择"设备 \> 所有设备"，选择对应设备，单击"详情"，进入设备详情页面可以看到最新上报的属性值。
图12物模型-属性上报   
![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002039398625.png "点击放大")
#### 属性读写
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
属性读写Demo，可参考entry/src/main/ets/pages/PropertySample.ets。
1. 在初始化连接成功后，调用客户端的propertyListener方法来设置属性回调接口。
   - 写属性处理：实现了alarm属性的写操作，其他属性不支持写操作。
   
   - 读属性处理：将本地属性值按照接口格式进行拼装。
   
   
   ```
   let propertyListener: PropertyListener = {
     onPropertiesSet: (requestId: string, services: ServiceProperty[]): void => {
   this.logArr.unshift(`${new Date()}: onPropertiesSet requestId is ${requestId}, services is ${JSON.stringify(services)}`)
   // 遍历services
   services.forEach(serviceProperty => {
     LogUtil.info("onPropertiesSet, serviceId is ", serviceProperty.service_id);
     // 遍历属性
     Object.keys(serviceProperty.properties).forEach(name => {
   LogUtil.log(TAG, `property name is ${name}`);
   LogUtil.log(TAG, `set property value is ${serviceProperty.properties[name]}`);
     })
   })
   // 修改本地的属性
   this.device?.client.respondPropsSet(requestId, IotResult.SUCCESS);
     },
     onPropertiesGet: (requestId: string, serviceId?: string): void => {
   this.logArr.unshift(`${new Date()}: onPropertiesGet requestId is ${requestId}, serviceId is ${serviceId} and respondPropsGet`)
   LogUtil.info(TAG, `onPropertiesGet, the serviceId is ${serviceId}`);
   const serviceProperties: ServiceProperty[] = [
     {
   "service_id": "smokeDetector",
   "properties": {
     "alarm": 1,
     "temperature": Math.random() * 100,
     "humidity": Math.random() * 100,
     "smokeConcentration": Math.random() * 100,
   }
     }
   ];
   this.device?.client.respondPropsGet(requestId, serviceProperties);
     }
   }
   // 设置属性监听器
   this.device.client.propertyListener = propertyListener;
   ```
   ![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
   - 属性读写接口需要调用respondPropsGet和respondPropsSet接口来上报操作结果。
   
   - 如果设备不支持平台主动到设备读，onPropertiesGet接口可以空实现。
     
2. 执行上述代码，设置属性监听器，在平台上设备影子页面查看当前alarm属性值为1，修改alarm属性为0后，查看设备侧日志，看到设备收到属性设置alarm属性为0。
   图13设备影子-查看alarm属性   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001981497737.png "点击放大")
   图14设备影子-属性配置alarm   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001950378332.png "点击放大")
   图15查看属性设置alarm为0   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002310940460.png "点击放大") 
 
#### 命令下发
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
命令下发Demo，可参考entry/src/main/ets/pages/CommandSample.ets。
设置命令监听器用来接收平台下发的命令，在回调接口里，需要对命令进行处理，并上报响应。
1. 在CommandSample例子中实现了命令的处理，收到命令后仅进行打印，然后调用respondCommand上报响应。
   ```
   let commandListener: CommandListener = {
       onCommand: (requestId: string, serviceId: string, commandName: string, paras: object): void => {
         const command = `requestId is ${requestId}, serviceId is ${serviceId}, commandName is ${commandName}, paras is ${JSON.stringify(paras)}`;
         LogUtil.info(TAG, `received command is ${command}`);
         // 用户可以在该处进行命令处理
         const commandRsp: CommandRsp = {
           result_code: 0
         }
         this.device?.client.respondCommand(requestId, commandRsp).then((data: IoTMqttResponse) => {
            LogUtil.info(TAG, `respond command success ${JSON.stringify(data)}, commandRsp is ${commandRsp}}`);      
         }).catch((err: IoTMqttResponse | string) => {
           LogUtil.error(TAG, `respond command failed ${JSON.stringify(err)}`);
         })
       }
     }
     this.device.client.commandListener = commandListener;
   ```
   
2. 执行上述代码设置命令监听后，在平台执行命令下发，其中serviceId为"smokeDetector"、命令名为"ringAlarm"、参数携带duration为整数20。
3. 查看日志，设备收到命令并成功上报响应。 ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002344979265.png "点击放大")
   
 
#### 面向物模型编程
![](https://support.huaweicloud.com/sdkreference-iothub/public_sys-resources/note_3.0-zh-cn.png)
面向物模型编程Demo，可参考entry/src/main/ets/pages/ProfileSample.ets。
前面介绍了直接调用设备客户端的接口和平台进行通讯的方法，这种方式比较灵活，但用户需要妥善处理每一个接口，实现比较复杂。
SDK提供了一种更简单的方式，即面向物模型编程。面向物模型编程指基于SDK提供的物模型抽象能力，设备代码按照物模型定义设备服务，然后可以直接访问设备服务（即调用设备服务的属性读写接口），SDK就能自动和平台通讯，完成属性的同步和命令的调用。
相比直接调用客户端接口和平台进行通讯，面向物模型编程更简单，它简化了设备侧代码的复杂度，让设备代码只需要关注业务，而不用关注和平台的通讯过程。这种方式适合多数场景。
ProfileSample例子演示了如何面向物模型编程：
1. 首先定义一个烟感服务类，继承自AbstractService。（如果有多个服务，则需要定义多个服务类）：
   ```
   class SmokeDetector extends AbstractService  {
   }
   ```
   
2. 定义服务属性，私有变量以下划线开头，使用@Reflect.metadata("Property"， { name: "***string*** ", writeable: ***boolean*** })注解表示一个属性，其中中name和产品模型中属性名保持一致。writeable用来标识属性是否可写
   ```
   @Reflect.metadata("Property", { name: "alarm", writeable: true })
       private _smokeAlarm: number = 1;
       @Reflect.metadata("Property", { name: "smokeConcentration", writeable: false })
       private _concentration: number = 0;
       @Reflect.metadata("Property", { name: "humidity", writeable: false })
       private _humidity: number = 0;
       @Reflect.metadata("Property", { name: "temperature", writeable: false })
       private _temperature: number = 10;
   ```
   
3. 定义服务的命令。设备收到平台下发的命令时，SDK会自动调用这里定义的命令。注解中name对应物模型的command_name，method对应接收命令的处理方法，命令的入参和返回值类型固定不能修改。 这里定义的是一个响铃报警命令，命令名为ringAlarm，下发参数为"duration"，表示响铃报警的持续时间。
   ```
   @Reflect.metadata("DeviceCommand", {
       name: "ringAlarm",
       method: (paras: object): CommandRsp => {
         let duration: number = paras['duration'];
         LogUtil.log(TAG, `duration is ${duration}`);
   return IotResult.SUCCESS;
   }
     })
     private _alarm: Function = () => {};
   ```
   
4. 定义getter和setter接口。
   - 当设备收到平台下发的查询属性以及设备上报属性时，会自动调用getter方法。getter方法需要读取设备的属性值，可以实时到传感器读取或者读取本地的缓存
   
   - 当设备收到平台下发的设置属性时，会自动调用setter方法。setter方法需要更新设备本地的值。如果属性不支持写操作，setter保留空实现。
   
   - setter和getter接口使用DevEco Studio右键的Generate的Getter and Setter自动生成，然后修改方法实现。
   
   
   ```
   public set smokeAlarm(value: number) {
       this._smokeAlarm = value;
       if (value == 0) {
         LogUtil.info(TAG, "alarm is cleared by app");
       }
     }
     public get smokeAlarm(): number {
       return this._smokeAlarm;
     }
     public set concentration(value: number) {
       // 只读字段不需要实现set接口
     }
     public get concentration(): number {
       return Math.floor(Math.random() * 100);
     }
     public set humidity(value: number) {
       // 只读字段不需要实现set接口
     }
     public get humidity(): number {
       return Math.floor(Math.random() * 100);
     }
     public set temperature(value: number) {
       // 只读字段不需要实现set接口
     }
     public get temperature(): number {
       return Math.floor(Math.random() * 100);
     }
   ```
   
5. 实现构造函数，完成属性和命令的初始化。
   ```
   constructor() {
       super();
       const fields = Object.getOwnPropertyNames(this);
       this.init(fields);
     }
   ```
   
6. 创建设备，注册烟感服务。
   ```
   //创建设备服务
   const smokeDetector = new SmokeDetector();
   this.device.addService("smokeDetector", smokeDetector);
   ```
   
7. 开启周期上报。
   ```
   //启动自动周期上报
   this.device.getService("smokeDetector")?.enableAutoReport(10000);
   ```
   
8. 执行上述代码，查看日志上报属性。 ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002345099441.png "点击放大")
   
9. 在平台侧查看设备影子中属性alarm为1，修改alarm为0后，查看设备日志收到属性设置
   图16设备影子-查看alarm属性   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000001981497737.png "点击放大")
   图17查看设备日志属性设置成功   
   ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002311100232.png "点击放大") 
10. 在平台下发ringAlarm命令，查看设备日志看到ringAlarm命令被调用，并且成功上报响应。 ![](https://support.huaweicloud.com/sdkreference-iothub/figure/zh-cn_image_0000002310940468.png "点击放大")
    
 
