本文将介绍如何实现设备端通过MQTT通讯协议对物联网平台的设备标签数据进行操作。
API列表

如上图流程所示, 使用C-SDK中的devinfo功能, 可将Key-Value形式组织的设备标签上报到云端, 或者从云端删除某个标签。
以下是完整的devinfo部分API列表及简要说明 (详见components/devinfo/aiot_devinfo_api.h
)。
接口名 | 说明 |
---|---|
aiot_devinfo_init | 初始化devinfo实例并设置默认参数。 |
aiot_devinfo_setopt | 配置devinfo实例, 详见devinfo选项配置说明。 |
aiot_devinfo_deinit | 释放devinfo实例句柄的资源。 |
aiot_devinfo_send | 向MQTT服务器发送devinfo的标签更新请求。 |
API使用概述
Devinfo模块用于向阿里云物联网平台更新或删除设备的标签, API的使用流程如下:
- 首先参考
aiot_mqtt_api.h
的说明, 保证成功建立与物联网平台的MQTT
连接。 - 调用
aiot_devinfo_init
初始化devinfo会话, 获取会话句柄。 - 调用
aiot_devinfo_setopt
配置devinfo会话的参数, 常用配置项见aiot_devinfo_setopt
的说明。 - 调用
aiot_devinfo_send
发送标签变更的请求, 比如更新或删除。 - 收到的应答经SDK处理后会调用由
aiot_devinfo_setopt
配置的AIOT_DEVINFOOPT_RECV_HANDLER
回调函数, 通知用户云端的应答。
例程讲解
现对照demos/devinfo_posix_demo.c
例程, 分步骤讲解如何使用API。

这个例程适用于Linux
这类支持pthread的POSIX设备, 它演示了用SDK配置MQTT参数并建立连接, 之后创建2个线程。
- 一个线程用于保活长连接。
- 一个线程用于接收消息, 并在有消息到达时进入默认的数据回调, 在连接状态变化时进入事件回调。
接着在MQTT连接上发送设备标签更新或删除请求, 如果云平台的回应报文到达, 从接收线程会调用devinfo消息处理的回调函数, 把上报结果打印出来。
需要用户关注或修改的部分, 已经用 TODO
在注释中标明。
- 设置设备证书
例程使用的设备证书是公用的, 所以应用于实际业务时, 请替换如下的
TODO
部分, 传入用户自己真实的设备证书。/* TODO: 替换为自己设备的设备证书 */ char *product_key = "a13FNXXXXXX"; char *device_name = "devinfo_basic_demo"; char *device_secret = "r8gHQiRkFnVUjJEWm0LvOCS7lEXXXXXX";
- 进入程序入口, 给SDK配置全局的底层依赖和日志回调
底层依赖描述了硬件平台的资源使用方式, 比如怎样获取时钟, 分配内存等, 日志回调是用户的函数, SDK有log输出的时候会进入这个函数。
int main(int argc, char *argv[]) { ... ... /* 配置SDK的底层依赖 */ aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); /* 配置SDK的日志输出 */ aiot_state_set_logcb(demo_state_logcb);
- 给MQTT会话配置参数并建立连接
这些连接参数包括如何建立TLS连接, 服务器地址在哪, 连接后的数据及事件回调函数是什么等等, 然后用
aiot_mqtt_connect()
建立连接。int32_t demo_mqtt_start(void **handle) { ... ... /* 创建1个MQTT客户端实例并内部初始化默认参数 */ mqtt_handle = aiot_mqtt_init(); ... /* 与服务器建立MQTT连接 */ res = aiot_mqtt_connect(mqtt_handle);
以下代码创建1个子线程, 专门用于保活设备与云平台之间的长连接。
/* 创建一个单独的线程, 专用于执行aiot_mqtt_process, 它会自动发送心跳保活, 以及重发QoS1的未应答报文 */ g_mqtt_process_thread_running = 1; res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle);
以下代码创建1个子线程, 专门用于接收从云平台推送下来的MQTT消息。
/* 创建一个单独的线程用于执行aiot_mqtt_recv, 它会循环收取服务器下发的MQTT消息, 并在断线时自动重连 */ g_mqtt_recv_thread_running = 1; res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle);
- 创建devinfo会话实例并设置回应消息处理回调
devinfo服务的请求和应答是在MQTT长连接上进行的, 以下代码设置了请求发送后, 如果设备收到了云平台的devinfo回应消息进入哪个用户回调函数。
/* 配置devinfo会话, 把它和MQTT会话的句柄关联起来 */ res = aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_MQTT_HANDLE, mqtt_handle); ... /* TODO: DEVINFO消息回应从云端到达设备时, 会进入此处设置的回调函数 */ res = aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_RECV_HANDLER, (void *)demo_devinfo_recv_handler); ... res = aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_EVENT_HANDLER, (void *)demo_devinfo_event_handler);
- 向服务器发送标签更新请求
使用
aiot_devinfo_send()
接口, 以上面设置的参数, 向服务器发起标签更新请求。/* 示例: 发送update请求给云平台 */ /* TODO: 替换示例JSON中的 testKey 部分, 效果就会变成更新其他Key标识的设备标签 */ /* TODO: 替换示例JSON中的 testValue 部分, 效果就会变成更新其他Value到设备标签 */ /* { aiot_devinfo_msg_t devinfo_update; char *update = "[{\"attrKey\":\"testKey\",\"attrValue\":\"testValue\"}]"; memset(&devinfo_update, 0, sizeof(aiot_devinfo_msg_t)); devinfo_update.product_key = product_key; devinfo_update.device_name = device_name; devinfo_update.type = AIOT_DEVINFO_MSG_UPDATE; devinfo_update.data.update.params = update; res = aiot_devinfo_send(devinfo_handle, &devinfo_update); if (res < STATE_SUCCESS) { aiot_devinfo_deinit(&devinfo_handle); demo_mqtt_stop(&mqtt_handle); return -1; } printf("aiot_devinfo_send update msg id: %d\n", res); } */
如果打开注释, 重新编译, 以下日志就对应运行例程时被发送的标签更新请求。
[1583155953.211][LK-0309] pub: /sys/a13FNXXXXXX/devinfo_basic_demo/thing/deviceinfo/update [LK-030A] > 7B 22 69 64 22 3A 22 30 22 2C 22 76 65 72 73 69 | {"id":"0","versi [LK-030A] > 6F 6E 22 3A 22 31 2E 30 22 2C 22 70 61 72 61 6D | on":"1.0","param [LK-030A] > 73 22 3A 5B 7B 22 61 74 74 72 4B 65 79 22 3A 22 | s":[{"attrKey":" [LK-030A] > 74 65 73 74 4B 65 79 22 2C 22 61 74 74 72 56 61 | testKey","attrVa [LK-030A] > 6C 75 65 22 3A 22 74 65 73 74 56 61 6C 75 65 22 | lue":"testValue" [LK-030A] > 7D 5D 7D | }]}
- 从接收线程得到服务应答
在
demo_mqtt_start()
中, 已开启了1个专门的接收消息线程demo_mqtt_recv_thread
, 它会永无休止的调用aiot_mqtt_recv()
来收取消息。如果得到devinfo的服务应答, 那么会根据上面
AIOT_DEVINFOOPT_RECV_HANDLER
选项的设置, 进入用户侧的回调函数(以下只是把云端应答打印出来)。/* TODO: 数据处理回调, 当SDK从网络上收到devinfo消息时被调用 */ void demo_devinfo_recv_handler(void *handle, const aiot_devinfo_recv_t *packet, void *userdata) { switch (packet->type) { /* 这是云端对devinfo消息的应答报文 */ case AIOT_DEVINFORECV_GENERIC_REPLY: { printf("pk: %s, dn: %s, code: %d, msg id: %d\n", packet->product_key, packet->device_name, packet->data.generic_reply.code, packet->data.generic_reply.msg_id); ... ...
以下日志对应的是被成功接收到的服务应答和例程的解析打印。
[1583155953.266][LK-0309] pub: /sys/a13FNXXXXXX/devinfo_basic_demo/thing/deviceinfo/update_reply [LK-030A] < 7B 22 63 6F 64 65 22 3A 32 30 30 2C 22 64 61 74 | {"code":200,"dat [LK-030A] < 61 22 3A 7B 7D 2C 22 69 64 22 3A 22 30 22 2C 22 | a":{},"id":"0"," [LK-030A] < 6D 65 73 73 61 67 65 22 3A 22 73 75 63 63 65 73 | message":"succes [LK-030A] < 73 22 2C 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 | s","method":"thi [LK-030A] < 6E 67 2E 64 65 76 69 63 65 69 6E 66 6F 2E 75 70 | ng.deviceinfo.up [LK-030A] < 64 61 74 65 22 2C 22 76 65 72 73 69 6F 6E 22 3A | date","version": [LK-030A] < 22 31 2E 30 22 7D | "1.0"} pk: a13FNXXXXXX, dn: devinfo_basic_demo, code: 200, msg id: 0
code
的值是200
, 代表云端已经接受了刚才发送的标签更新请求, 此时登录控制台刷新网页可看到标签的值已经发生变化。
在文档使用中是否遇到以下问题
更多建议
匿名提交