使用指南

ali-iotkit 软件包封装了 HTTP、MQTT、CoAP 和 OTA 等应用层协议,方便了用户设备接入云平台,这里摘取部分做简要介绍。

MQTT 连接

目前阿里云支持 MQTT 标准协议接入,兼容 3.1.1 和 3.1 版本协议,具体的协议请参考 MQTT 3.1.1MQTT 3.1 协议文档。

特征

  • 支持 MQTT 的 PUB、SUB、PING、PONG、CONNECT、DISCONNECT 和 UNSUB 等报文
  • 支持 cleanSession
  • 不支持 will、retain msg
  • 不支持 QOS2
  • 基于原生的 MQTT topic 上支持 RRPC 同步模式,服务器可以同步调用设备并获取设备回执结果

    安全等级

支持 TLSV1、 TLSV1.1 和 TLSV1.2 版本的协议建立安全连接。

  • TCP 通道基础+芯片级加密(ID2硬件集成): 安全级别高
  • TCP 通道基础+对称加密(使用设备私钥做对称加密):安全级别中
  • TCP 方式(数据不加密): 安全级别低

    连接域名

  • 华东2节点:productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883

  • 美西节点:productKey.iot-as-mqtt.us-west-1.aliyuncs.com:1883
  • 新加坡节点:productKey.iot-as-mqtt.ap-southeast-1.aliyuncs.com:1883

    Topic 规范

默认情况下创建一个产品后,产品下的所有设备都拥有以下 Topic 类的权限:

  • /productKey/deviceName/update pub
  • /productKey/deviceName/update/error pub
  • /productKey/deviceName/get sub
  • /sys/productKey/deviceName/thing/# pub&sub
  • /sys/productKey/deviceName/rrpc/# pub&sub
  • /broadcast/productKey/# pub&sub
    每个 Topic 规则称为 topic 类,topic 类实行设备维度隔离。每个设备发送消息时,将 deviceName 替换为自己设备的 deviceName ,防止 topic 被跨设备越权,topic 说明如下:

  • pub:表示数据上报到 topic 的权限

  • sub:表示订阅 topic 的权限
  • /productKey/deviceName/xxx 类型的 topic 类:可以在物联网平台的控制台扩展和自定义
  • /sys 开头的 topic 类:属于系统约定的应用协议通信标准,不允许用户自定义的,约定的 topic 需要符合阿里云 ALink 数据标准
  • /sys/productKey/deviceName/thing/xxx 类型的 topic 类:网关主子设备使用的 topic 类,用于网关场景
  • /broadcast 开头的 topic 类:广播类特定 topic
  • /sys/productKey/deviceName/rrpc/request/${messageId}:用于同步请求,服务器会对消息 Id 动态生成 topic, 设备端可以订阅通配符
  • /sys/productKey/deviceName/rrpc/request/+:收到消息后,发送 pub 消息到 /sys/productKey/deviceName/rrpc/response/${messageId},服务器可以在发送请求时,同步收到结果

    建立 MQTT 连接

使用 IOT_MQTT_Construct 接口与云端建立 MQTT 连接。

如果要实现设备长期在线,需要程序代码中去掉 IOT_MQTT_Unregister 和 IOT_MQTT_Destroy 部分,使用 while 保持长连接状态。

示例代码如下:

  1. while(1)
  2. {
  3. IOT_MQTT_Yield(pclient, 200);
  4. HAL_SleepMs(100);
  5. }

订阅 Topic 主题

使用 IOT_MQTT_Subscribe 接口订阅某个 Topic。

代码如下:

  1. /* Subscribe the specific topic */
  2. rc = IOT_MQTT_Subscribe(pclient, TOPIC_DATA, IOTX_MQTT_QOS1,
  3. _demo_message_arrive, NULL);
  4. if (rc < 0) {
  5. IOT_MQTT_Destroy(&pclient);
  6. EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc);
  7. rc = -1;
  8. goto do_exit;
  9. }

发布消息

使用 IOT_MQTT_Publish 接口发布信息到云端。

代码如下:

  1. /* Initialize topic information */
  2. memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
  3. strcpy(msg_pub, "message: hello! start!");
  4. topic_msg.qos = IOTX_MQTT_QOS1;
  5. topic_msg.retain = 0;
  6. topic_msg.dup = 0;
  7. topic_msg.payload = (void *)msg_pub;
  8. topic_msg.payload_len = strlen(msg_pub);
  9. rc = IOT_MQTT_Publish(pclient, TOPIC_DATA, &topic_msg);
  10. EXAMPLE_TRACE("rc = IOT_MQTT_Publish() = %d", rc);

取消订阅

使用 IOT_MQTT_Unsubscribe 接口取消订阅云端消息

下行数据接收

使用 IOT_MQTT_Yield 数据接收函数接收来自云端的消息。

请在任何需要接收数据的地方调用这个 API。如果系统允许,请起一个单独的线程,执行该接口。

代码如下:

  1. /* handle the MQTT packet received from TCP or SSL connection */
  2. IOT_MQTT_Yield(pclient, 200);

销毁 MQTT 连接

使用 IOT_MQTT_Destroy 接口销毁 MQTT 连接,释放内存。

代码如下:

  1. IOT_MQTT_Destroy(&pclient);

检查连接状态

使用 IOT_MQTT_CheckStateNormal 接口查看当前的连接状态。

该接口用于查询MQTT的连接状态。但是,该接口并不能立刻检测到设备断网,只会在有数据发送或是 keepalive 时才能侦测到 disconnect。

MQTT 保持连接

设备端在 keepalive_interval_ms 时间间隔内,至少需要发送一次报文,包括 ping 请求。

如果服务端在 keepalive_interval_ms 时间内无法收到任何报文,物联网平台会断开连接,设备端需要进行重连。

在 IOT_MQTT_Construct 函数可以设置 keepalive_interval_ms 的取值,物联网平台通过该取值作为心跳间隔时间。keepalive_interval_ms 的取值范围是60000~300000。

示例代码:

  1. iotx_mqtt_param_t mqtt_params;
  2.  
  3. memset(&mqtt_params, 0x0, sizeof(mqtt_params));
  4. mqtt_params.keepalive_interval_ms = 60000;
  5. mqtt_params.request_timeout_ms = 2000;
  6.  
  7. /* Construct a MQTT client with specify parameter */
  8. pclient = IOT_MQTT_Construct(&mqtt_params);

CoAP 连接

  • 支持 RFC 7252 Constrained Application Protocol协议,具体请参考:RFC 7252
  • 使用 DTLS v1.2 保证通道安全,具体请参考:DTLS v1.2
  • 服务器地址 endpoint = productKey.iot-as-coap.cn-shanghai.aliyuncs.com:5684
    其中 productKey 请替换为您申请的产品 Key

CoAP 约定

  • 不支持?号形式传参数
  • 暂时不支持资源发现
  • 仅支持 UDP 协议,并且目前必须通过 DTLS
  • URI 规范,CoAP 的 URI 资源和 MQTT TOPIC 保持一致,参考 MQTT规范

    应用场景

CoAP 协议适用在资源受限的低功耗设备上,尤其是 NB-IoT 的设备使用,基于 CoAP 协议将 NB-IoT 设备接入物联网平台的流程如下图所示:

CoAP 应用场景

建立连接

使用 IOT_CoAP_Init 和 IOT_CoAP_DeviceNameAuth 接口与云端建立 CoAP 认证连接。

示例代码:

  1. iotx_coap_context_t *p_ctx = NULL;
  2. p_ctx = IOT_CoAP_Init(&config);
  3. if (NULL != p_ctx) {
  4. IOT_CoAP_DeviceNameAuth(p_ctx);
  5. do {
  6. count ++;
  7. if (count == 11) {
  8. count = 1;
  9. }
  10. IOT_CoAP_Yield(p_ctx);
  11. } while (m_coap_client_running);
  12. IOT_CoAP_Deinit(&p_ctx);
  13. } else {
  14. HAL_Printf("IoTx CoAP init failed\r\n");
  15. }

收发数据

SDK 使用接口 IOT_CoAP_SendMessage 发送数据,使用 IOT_CoAP_GetMessagePayload 和IOT_CoAP_GetMessageCode 接收数据。

示例代码:

  1. /* send data */
  2. static void iotx_post_data_to_server(void *param)
  3. {
  4. char path[IOTX_URI_MAX_LEN + 1] = {0};
  5. iotx_message_t message;
  6. iotx_deviceinfo_t devinfo;
  7. message.p_payload = (unsigned char *)"{\"name\":\"hello world\"}";
  8. message.payload_len = strlen("{\"name\":\"hello world\"}");
  9. message.resp_callback = iotx_response_handler;
  10. message.msg_type = IOTX_MESSAGE_CON;
  11. message.content_type = IOTX_CONTENT_TYPE_JSON;
  12. iotx_coap_context_t *p_ctx = (iotx_coap_context_t *)param;
  13. iotx_set_devinfo(&devinfo);
  14. snprintf(path, IOTX_URI_MAX_LEN, "/topic/%s/%s/update/",
  15. (char *)devinfo.product_key,
  16. (char *)devinfo.device_name);
  17. IOT_CoAP_SendMessage(p_ctx, path, &message);
  18. }
  19.  
  20. /* receive data */
  21. static void iotx_response_handler(void *arg, void *p_response)
  22. {
  23. int len = 0;
  24. unsigned char *p_payload = NULL;
  25. iotx_coap_resp_code_t resp_code;
  26. IOT_CoAP_GetMessageCode(p_response, &resp_code);
  27. IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
  28. HAL_Printf("[APPL]: Message response code: 0x%x\r\n", resp_code);
  29. HAL_Printf("[APPL]: Len: %d, Payload: %s, \r\n", len, p_payload);
  30. }

下行数据接收

使用 IOT_CoAP_Yield 接口接收来自云端的下行数据。

请在任何需要接收数据的地方调用这个API,如果系统允许,请起一个单独的线程,执行该接口。

销毁 CoAP 连接

使用 IOT_CoAP_Deinit 接口销毁 CoAP 连接并释放内存。

OTA 升级

固件升级 Topic

  • 设备端上报固件版本给云端
/ota/device/inform/productKey/deviceName
  • 设备端订阅该topic接收云端固件升级通知
/ota/device/upgrade/productKey/deviceName
  • 设备端上报固件升级进度
/ota/device/progress/productKey/deviceName
  • 设备端请求是否固件升级
/ota/device/request/productKey/deviceName

固件升级说明

  • 设备固件版本号只需要在系统启动过程中上报一次即可,不需要周期循环上报
  • 根据版本号来判断设备端OTA是否升级成功
  • 从OTA服务端控制台发起批量升级,设备升级操作记录状态是待升级

实际升级以OTA系统接收到设备上报的升级进度开始,设备升级操作记录状态是升级中。

  • 设备离线时,接收不到服务端推送的升级消息

当设备上线后,主动通知服务端上线消息,OTA 服务端收到设备上线消息,验证该设备是否需要升级,如果需要,再次推送升级消息给设备, 否则,不推送消息。

OTA 代码说明

初始化

OTA 模块的初始化依赖于 MQTT 连接,即先获得的 MQTT 客户端句柄 pclient。

  1. h_ota = IOT_OTA_Init(PRODUCT_KEY, DEVICE_NAME, pclient);
  2. if (NULL == h_ota) {
  3. rc = -1;
  4. printf("initialize OTA failed\n");
  5. }

上报版本号

在 OTA 模块初始化之后,调用 IOT_OTA_ReportVersion 接口上报当前固件的版本号,升级成功后重启运行新固件,并使用该接口上报新固件版本号,云端与 OTA 升级任务的版本号对比成功后,提示 OTA 升级成功。

示例代码如下:

  1. if (0 != IOT_OTA_ReportVersion(h_ota, "version2.0")) {
  2. rc = -1;
  3. printf("report OTA version failed\n");
  4. }

下载固件

MQTT 通道获取到 OTA 固件下载的 URL 后,使用 HTTPS 下载固件,边下载边存储到 Flash OTA 分区。

  • IOT_OTA_IsFetching() 接口:用于判断是否有固件可下载
  • IOT_OTA_FetchYield() 接口:用于下载一个固件块
  • IOT_OTA_IsFetchFinish() 接口:用于判断是否已下载完成
    示例代码:
  1. // 判断是否有固件可下载
  2. if (IOT_OTA_IsFetching(h_ota)) {
  3. unsigned char buf_ota[OTA_BUF_LEN];
  4. uint32_t len, size_downloaded, size_file;
  5. do {
  6. // 循环下载固件
  7. len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1);
  8. if (len > 0) {
  9. // 写入到Flash等存储器中(边下载边存储)
  10. }
  11. } while (!IOT_OTA_IsFetchFinish(h_ota)); // 判断固件是否下载完毕
  12. }

上报下载状态

使用 IOT_OTA_ReportProgress 接口上报固件下载进度。

  1. if (percent - last_percent > 0) {
  2. IOT_OTA_ReportProgress(h_ota, percent, NULL);
  3. }
  4. IOT_MQTT_Yield(pclient, 100);

判断下载固件是否完整

固件下载完成后,使用 IOT_OTA_Ioctl 接口校验固件的完整性。

  1. int32_t firmware_valid;
  2. IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4);
  3. if (0 == firmware_valid) {
  4. printf("The firmware is invalid\n");
  5. } else {
  6. printf("The firmware is valid\n");
  7. }

销毁 OTA 连接

使用 IOT_OTA_Deinit 销毁 OTA 连接并释放内存。

参考

  • 以上内容引自阿里云物联网平台使用文档,详细内容请访问阿里云物联网平台文档中心进行查阅
  • 更多的 API 使用说明请参考 API 使用文档
  • 更多的示例代码请参考示例程序及示例使用说明

原文: https://www.rt-thread.org/document/site/submodules/ali-iotkit/docs/user-guide/