IoT Device SDK使用指南(ArkTS)
IoT Device SDK(ArkTS)提供设备接入华为云IoT物联网平台的ArkTS版本的SDK,提供设备和平台之间通讯能力,并且针对各种场景提供了丰富的demo代码。相关集成指导请参考IoT Device SDK(ArkTS)使用指南。
准备工作
- 已安装 DevEco Studio 5.0.0及以上版本。
- 已安装配套的Node.js。
使用说明
- 下载安装:在DevEco Studio中执行以下命令引入并安装SDK。
ohpm install @huaweicloud/iot-device-sdk
- 权限配置:使用SDK需要网络连接的权限,需要在module.json5的requestPermissions中增加"ohos.permission.INTERNET"的权限,如下所示:
{ "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ] } }
具体使用方式请看gitHub上的README文档。
创建产品
为了方便体验,我们提供了一个烟感的产品模型,烟感会上报烟雾值、温度、湿度、烟雾报警、还支持响铃报警命令。以烟感例,体验消息上报、属性上报等功能。
- 访问设备接入服务,单击“管理控制台”进入设备接入控制台,选择您的实例,单击实例卡片进入。查看MQTTS设备接入域名,保存该地址。
- 单击左侧导航栏“产品”,单击页面左侧的“创建产品”。
- 根据页面提示填写参数,然后单击“确定”完成产品的创建。
基本信息
所属资源空间
平台自动将新创建的产品归属在默认资源空间下。如需归属在其他资源空间下,下拉选择所属的资源空间。如无对应的资源空间,请先创建资源空间。
产品名称
自定义。支持字母、数字、下划线(_)、连字符(-)的字符组合。
协议类型
选择“MQTT”。
数据格式
选择“JSON”。
设备类型选择
选择”自定义类型”
设备类型
填写“smokeDetector”
高级配置
产品ID
不填写
产品描述
请根据实际情况填写。
上传产品模型
- 单击下载烟感产品模型smokeDetector,获取产品模型文件。
- 找到步骤3创建的产品,单击产品进入产品详情页。
- 选择“基本信息”页签,单击“上传模型文件”,上传步骤1获取的产品模型文件。
图1 产品-上传产品模型
注册设备
设备初始化
设备初始化Demo,可参考entry/src/main/ets/pages/Index.ets。
- 创建设备需要输入注册设备时获取的设备ID、密码,以及1中获取的设备对接信息,注意格式为ssl://域名信息:端口号 或 ssl://IP地址:端口号
1 2 3 4
private device: IoTDevice | null = null; // 用户请替换为自己的接入地址, 设备ID,设备密钥及证书路径(证书文件放在resource/resfile下,连接华为云时请使用对应的证书,可以在资源获取中下载证书文件)。 this.device = new IoTDevice("ssl://域名信息:8883","deviceId", "mySecret", "filePath");
- 调用init建立连接。您可以使用异步方式初始化或使用同步方式初始化。
1 2 3 4 5 6 7 8 9
// 使用异步方式初始化 this.device.init().then((data: boolean) => { // 连接成功处理 }).catch((err: string) => { // 连接失败处理 }) // 或使用同步方式初始化 // await this.device.init();
- 查看设备日志打印,设备连接成功。
1
IoTDA_SDK# connect result is {"code":0,"message":"Connect Success"}
- 创建设备并连接成功后,可以开始进行设备通信。调用IoT Device 的client接口获取设备客户端,客户端提供了消息、属性、命令等通讯接口。
消息上报
消息上报Demo,可参考entry/src/main/ets/pages/MessageSample.ets。
消息上报是指设备向平台上报消息。
- 在初始化并连接平台成功后,调用客户端的reportDeviceMessage接口上报设备消息,publishRawMessage上报自定义Topic的消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// 上报系统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 上报系统Topic消息日志
图3 上报自定义Topic($oc开头) 消息日志
图4 上报自定义Topic(非$oc开头)消息日志
- 在设备接入控制台,选择图5 设备列表-设备在线
-查看设备是否在线。
- 选择对应设备,单击“详情”,进入设备详情页面启动设备消息跟踪。
图6 消息跟踪-启动消息跟踪
- 消息跟踪显示平台成功接收到设备的消息。
图7 消息跟踪-查看device_sdk_java消息跟踪
消息跟踪会有一定的延时,如果没有看到数据,请等待后刷新。
属性上报
属性上报Demo,可参考entry/src/main/ets/pages/PropertySample.ets文件。
1. 在初始化并连接平台成功后,调用客户端的reportProperties接口上报设备属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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. 上报成功,查看日志发送属性成功。
3. 在设备接入控制台,选择“详情”,进入设备详情页面可以看到最新上报的属性值。
,选择对应设备,单击属性读写
属性读写Demo,可参考entry/src/main/ets/pages/PropertySample.ets。
- 在初始化连接成功后,调用客户端的propertyListener方法来设置属性回调接口。
- 写属性处理:实现了alarm属性的写操作,其他属性不支持写操作。
- 读属性处理:将本地属性值按照接口格式进行拼装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
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;
- 属性读写接口需要调用respondPropsGet和respondPropsSet接口来上报操作结果。
- 如果设备不支持平台主动到设备读,onPropertiesGet接口可以空实现。
- 执行上述代码,设置属性监听器,在平台上设备影子页面查看当前alarm属性值为1,修改alarm属性为0后,查看设备侧日志,看到设备收到属性设置alarm属性为0。
图10 设备影子-查看alarm属性
图11 设备影子-属性配置alarm
图12 查看属性设置alarm为0
命令下发
命令下发Demo,可参考entry/src/main/ets/pages/CommandSample.ets。
设置命令监听器用来接收平台下发的命令,在回调接口里,需要对命令进行处理,并上报响应。
- 在CommandSample例子中实现了命令的处理,收到命令后仅进行打印,然后调用respondCommand上报响应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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;
- 执行上述代码设置命令监听后,在平台执行命令下发,其中serviceId为“smokeDetector”、命令名为“ringAlarm”、参数携带duration为整数20。
- 查看日志,设备收到命令并成功上报响应。
面向物模型编程
面向物模型编程Demo,可参考entry/src/main/ets/pages/ProfileSample.ets。
前面介绍了直接调用设备客户端的接口和平台进行通讯的方法,这种方式比较灵活,但用户需要妥善处理每一个接口,实现比较复杂。
SDK提供了一种更简单的方式,即面向物模型编程。面向物模型编程指基于SDK提供的物模型抽象能力,设备代码按照物模型定义设备服务,然后可以直接访问设备服务(即调用设备服务的属性读写接口),SDK就能自动和平台通讯,完成属性的同步和命令的调用。
相比直接调用客户端接口和平台进行通讯,面向物模型编程更简单,它简化了设备侧代码的复杂度,让设备代码只需要关注业务,而不用关注和平台的通讯过程。这种方式适合多数场景。
ProfileSample例子演示了如何面向物模型编程:
- 首先定义一个烟感服务类,继承自AbstractService。(如果有多个服务,则需要定义多个服务类):
1 2 3
class SmokeDetector extends AbstractService { }
- 定义服务属性,私有变量以下划线开头,使用@Reflect.metadata("Property", { name: "string", writeable: boolean })注解表示一个属性,其中中name和产品模型中属性名保持一致。writeable用来标识属性是否可写
1 2 3 4 5 6 7 8 9 10 11
@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;
- 定义服务的命令。设备收到平台下发的命令时,SDK会自动调用这里定义的命令。注解中name对应物模型的command_name,method对应接收命令的处理方法,命令的入参和返回值类型固定不能修改。
这里定义的是一个响铃报警命令,命令名为ringAlarm,下发参数为”duration”,表示响铃报警的持续时间。
1 2 3 4 5 6 7 8 9
@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 = () => {};
- 定义getter和setter接口。
- 当设备收到平台下发的查询属性以及设备上报属性时,会自动调用getter方法。getter方法需要读取设备的属性值,可以实时到传感器读取或者读取本地的缓存
- 当设备收到平台下发的设置属性时,会自动调用setter方法。setter方法需要更新设备本地的值。如果属性不支持写操作,setter保留空实现。
- setter和getter接口使用DevEco Studio右键的Generate的Getter and Setter自动生成,然后修改方法实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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); }
- 实现构造函数,完成属性和命令的初始化。
constructor() { super(); const fields = Object.getOwnPropertyNames(this); this.init(fields); }
- 创建设备,注册烟感服务。
1 2 3
//创建设备服务 const smokeDetector = new SmokeDetector(); this.device.addService("smokeDetector", smokeDetector);
- 开启周期上报。
1 2
//启动自动周期上报 this.device.getService("smokeDetector")?.enableAutoReport(10000);
- 执行上述代码,查看日志上报属性。
- 在平台侧查看设备影子中属性alarm为1,修改alarm为0后,查看设备日志收到属性设置
图13 设备影子-查看alarm属性
图14 查看设备日志属性设置成功
- 在平台下发ringAlarm命令,查看设备日志看到ringAlarm命令被调用,并且成功上报响应。
版本更新说明
版本号 |
变更类型 |
功能描述说明 |
---|---|---|
0.0.1 |
新增功能 |
提供对接华为云物联网平台能力,方便用户实现接入、设备管理、命令下发等业务场景 |