设备物模型开发
UIoT-Core 通过物模型功能简化用户应用程序的开发。本章描述如何利用设备端 C-SDK 提供的API 进行设备端的物模型开发。下面的讲解对应于 C-SDK 示例代码 samples/devmodel/devmodel_sample.c
功能说明
- C-SDK 支持物模型七种消息类型,对应于 uiotexportdm.h 中枚举类型 DM_Type
typedef enum _dm_type { PROPERTY_RESTORE, //设备恢复属性 PROPERTY_POST, //设备上报属性 PROPERTY_SET, //云端下发属性 PROPERTY_DESIRED_GET, //设备获取desire属性 PROPERTY_DESIRED_DELETE, //删除云端desire属性 EVENT_POST, //设备上报事件 COMMAND, //命令下发 DM_TYPE_MAX }DM_Type;
示例代码展示其中设备上报属性、云端下发属性、设备上报事件、命令下发四种操作。
* 目前用户需要根据物模型定义自行装配及解析部分 Json 消息,具体格式可参照物模型消息协议。
开发步骤
场景
示例代码基于一个”智能音箱“的场景,分别定义了一个”音量“属性,一个”低电量告警“事件,以及一个”下载音乐“命令。具体的物模型 json 文档如下所示:
{ "Property": [ { "PropertyID": 82, "Identifier": "volume", "Name": "音量", "AccessMode": "rw", "Description": "智能音箱音量,数值表示音量百分比", "DataType": { "Type": "int32", "Spec": { "Max": 100, "Min": 0, "Step": 1, "UnitName": "" } } } ], "Event": [ { "EventID": 39, "Identifier": "low_power_alert", "Name": "低电量告警", "Type": "warning", "Description": "当电量小于10%触发低电量告警", "Output": [ { "Identifier": "power", "Name": "电量百分比", "DataType": { "Type": "int32", "Spec": { "Max": 10, "Min": 0, "Step": 1, "UnitName": "" } } } ] } ], "Command": [ { "CommandID": 47, "Identifier": "download_music", "Name": "下载音乐", "Description": "控制智能音箱从指定URL下载音乐资源", "Input": [ { "Identifier": "url", "Name": "音乐资源URL", "DataType": { "Type": "string", "Spec": { "Length": 255 } } } ], "Output": [ { "Identifier": "result", "Name": "执行结果", "DataType": { "Type": "bool", "Spec": { "0": "执行失败", "1": "执行成功" } } } ] } ] }
用户可参考控制台操作指南,在控制台添加上述物模型功能定义(ID可能会有所差异,但不影响)。创建完成后,替换示例代码中的设备四元组信息。
初始化
在使用设备物模型功能之前,首先需要进行初始化,包括 MQTT 客户端的创建和物模型功能的初始化。可参照 devmodelsample.c 中 main 函数的初始化部分代码。
//1. 首先创建 MQTT 客户端,并与云端建立MQTT连接 void *client = IOT_MQTT_Construct(&init_params); if (client != NULL) { LOG_INFO("Cloud Device Construct Success"); } else { LOG_ERROR("Cloud Device Construct Failed"); return FAILURE; } IOT_MQTT_Yield(client, 50); //2. 初始化设备物模型,获取句柄 void *h_dm = IOT_DM_Init(UIOT_MY_PRODUCT_SN, UIOT_MY_DEVICE_SN, client); if (NULL == h_dm) { LOG_ERROR("initialize device model failed"); return FAILURE; } IOT_DM_Yield(h_dm, 50);
设备上报属性
用户可使用API函数 IOTDMProperty_Report 进行属性上报。
如果需要接收上报响应消息,利用 IOTDMRegisterCallback 注册对应的回调函数。
//根据 uiot_export_dm.h 中的声明,定义属性上报的回调函数,获取属性上报的响应。 int property_post_cb(const char *request_id, const int ret_code){ LOG_INFO("property_post_cb; request_id: %s; ret_code: %d", request_id, ret_code) return SUCCESS; } int main(int argc, char **argv) { ... //注册回调函数 IOT_DM_RegisterCallback(PROPERTY_POST , h_dm, property_post_cb); ... for (int i = 0; i < 10; i++) { //属性上报 IOT_DM_Property_Report(h_dm, PROPERTY_POST, i * 2, "{\"volume\": {\"Value\":50}}"); ... IOT_DM_Yield(h_dm, 200); HAL_SleepMs(2000); } ... }
云端下发属性
利用 IOTDMRegisterCallback 注册对应的回调函数,接收云端下发的属性值。
//根据 uiot_export_dm.h 中的声明,定义属性下发的回调函数,获取云端下发的属性值。实际应用中可在该回调函数中处理下发的属性值 int property_set_cb(const char *request_id, const char *property){ LOG_INFO("property_set_cb; request_id: %s; property: %s", request_id, property) return SUCCESS; } int main(int argc, char **argv) { ... //注册回调函数 IOT_DM_RegisterCallback(PROPERTY_SET , h_dm, property_set_cb); ... }
设备上报事件
用户可使用 API 函数 IOTDMTriggerEvent 进行事件上报。如果需要接收上报响应消息,利用 IOTDMRegisterCallback 注册对应的回调函数。
//根据 uiot_export_dm.h 中的声明,定义事件上报的回调函数,获取事件上报的响应。 int event_post_cb(const char *request_id, const int ret_code){ LOG_INFO("event_post_cb; request_id: %s; ret_code: %d", request_id, ret_code) return SUCCESS; } int main(int argc, char **argv) { ... //注册回调函数 IOT_DM_RegisterCallback(EVENT_POST, h_dm, event_post_cb); ... for (int i = 0; i < 10; i++) { //事件上报 IOT_DM_TriggerEvent(h_dm, i * 2 + 1, "low_power_alert", "{\"power\": 5}"); ... IOT_DM_Yield(h_dm, 200); HAL_SleepMs(2000); } ... }
命令下发
利用 IOTDMRegisterCallback 注册对应的回调函数,接收云端下发的命令。
//根据 uiot_export_dm.h 中的声明,定义命令下发的回调函数,获取云端下发的命令。实际应用中可在该回调函数中处理命令的输入输出 int command_cb(const char *request_id, const char *identifier, const char *input, char **output){ LOG_INFO("command_cb; request_id: %s; identifier: %s; input: %s", request_id, identifier, input) *output = (char *)HAL_Malloc(100); HAL_Snprintf(*output, 1000, "{\"result\":%d}", 1); return SUCCESS; } int main(int argc, char **argv) { ... //注册回调函数 IOT_DM_RegisterCallback(COMMAND , h_dm, command_cb); ... }
注意:在命令的回调函数中,需要用 HAL_Malloc 为 *output 申请内存,并且无需释放,由 SDK 负责释放该内存空间。
资源释放
//释放物模型资源 IOT_DM_Destroy(h_dm); //(可选)释放 MQTT Client 资源 IOT_MQTT_Destroy(&client);
API 列表
IOT_DM_RegisterCallback
注册消息回调函数的宏
#define IOT_DM_RegisterCallback(type, handle, cb)
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
type | DM_Type | 输入 | 消息类型,七种DM_Type之一 |
handle | void * | 输入 | IOT_DM_Init 返回的句柄 |
cb | 函数指针 | 输入 | 回调函数指针,函数类型必须与 DECLARE_DM_CALLBACK 声明的类型相同 |
ret | int | 返回值 | <0: 注册消息回调函数失败 =0: 注册消息回调函数成功 |
IOT_DM_Init
初始化设备物模型
void *IOT_DM_Init(const char *product_sn, const char *device_sn, void *ch_signal);
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
product_sn | const char * | 输入 | 指向产品序列号的指针 |
device_sn | const char * | 输入 | 指向设备序列号的指针 |
ch_signal | void * | 输入 | 指定的信号通道,目前为 IOT_MQTT_Construct 返回的句柄 |
ret | void * | 返回值 | 初始化成功,返回句柄;初始化失败,返回 NULL |
IOT_DM_Destroy
释放设备物模型相关的资源
int IOT_DM_Destroy(void *handle);
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
handle | void * | 输入 | IOT_DM_Init 返回的句柄 |
ret | int | 返回值 | <0: 失败 =0: 成功 |
IOT_DM_Property_Report
属性有关的消息上报
int IOT_DM_Property_Report(void *handle, DM_Type type, int request_id, const char *payload);
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
handle | void * | 输入 | IOT_DM_Init 返回的句柄 |
type | DM_Type | 输入 | 消息类型,PROPERTY_RESTORE, PROPERTY_POST, PROPERTY_DESIRED_GET, PROPERTY_DESIRED_DELETE 四种属性相关的消息类型之一 |
request_id | int | 输入 | 消息的 request_id,由用户决定,用于区分每次属性上报 |
payload | const char * | 输入 | 消息体 |
ret | int | 返回值 | <0: 上报失败 =0: 上报成功 |
IOT_DM_TriggerEvent
事件消息上报
int IOT_DM_TriggerEvent(void *handle, int request_id, const char *identifier, const char *payload);
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
handle | void * | 输入 | IOT_DM_Init 返回的句柄 |
request_id | int | 输入 | 消息的 request_id,由用户决定,用于区分不同事件 |
identifier | const char * | 输入 | 事件的 identifier |
payload | const char * | 输入 | 消息体 |
ret | int | 返回值 | <0: 上报失败 =0: 上报成功 |
IOT_DM_Yield
在当前线程为底层 MQTT 客户端让出一定 CPU 执行时间,让其接收网络报文并将消息分发到用户的回调函数中
int IOT_DM_Yield(void *handle, uint32_t timeout_ms);
参数列表
参数 | 数据类型 | 参数类型 | 说明 |
handle | void * | 输入 | IOT_DM_Init 返回的句柄 |
timeout_ms | uint32_t | 输入 | 超时时间,单位:ms |
ret | int | 返回值 | <0: 失败 =0: 成功 |