本文以C Link SDK中的Demo文件./demos/dynregmq_basic_demo.c为例,介绍如何调用Link SDK的API,向物联网平台发起MQTT协议的请求,动态注册设备,获取激活设备所需的认证信息

背景信息

MQTT动态注册的更多信息,请参见概述

步骤一:初始化

  1. 添加头文件。
    #include "aiot_state_api.h"
    #include "aiot_sysdep_api.h"
    #include "aiot_dynregmq_api.h"
  2. 配置底层依赖和日志输出。
        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        aiot_state_set_logcb(demo_state_logcb);
  3. 调用aiot_dynregmq_init,创建dynregmq客户端实例,并初始化默认参数。
        dynregmq_handle = aiot_dynregmq_init();
        if (dynregmq_handle == NULL) {
            printf("aiot_dynregmq_init failed\n");
            return -1;
        }

步骤二:配置功能

调用aiot_http_setopt,配置以下功能。

  1. 配置连接参数
  2. 配置消息回调
  3. 更多功能的配置项,请参见MQTT动态注册配置项
  1. 配置连接参数
    • 示例代码:
      
      
          char *product_key       = "a18wP******";
          char *product_secret    = "CpIlPVCXI7******";
          char *device_name       = "LightSwitch";
          char         *mqtt_host = "iot-06******.mqtt.iothub.aliyuncs.com"; 
          uint8_t skip_pre_regist =1;
      
          ……
      
          /* 配置连接的服务器地址。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_HOST, (void *)host);
          /* 配置连接的服务器端口。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PORT, (void *)&port);
          /* 配置设备ProductKey。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PRODUCT_KEY, (void *)product_key);
          /* 配置设备ProductSecret。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PRODUCT_SECRET, (void *)product_secret);
          /* 配置设备DeviceName */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_DEVICE_NAME, (void *)device_name);
          /* 配置网络连接的安全凭据。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_NETWORK_CRED, (void *)&cred);
          /* 配置是否使用免预注册认证方式。 */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_NO_WHITELIST, (void *)&skip_pre_regist);
          ...
          ...
    • 相关参数:
      参数 示例 说明
      mqtt_host iot-06******.mqtt.iothub.aliyuncs.com 设备的接入域名。
      • 企业版实例和新版公共实例:在实例详情页面的开发配置面板,查看接入域名。
      • 旧版公共实例:接入域名格式为${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com

      新旧版公共实例和企业版实例、以及接入域名的更多信息,请参见实例管理

      skip_pre_regist 1 认证方式是否为免预注册。
      • 0:预注册
      • 1:免预注册
      注意

      关于一型一密预注册和免预注册的更多信息,请参见一型一密

      product_key a18wP******

      在物联网平台创建产品时,保存的产品的ProductKeyProductSecret。更多信息,请参见创建产品

      product_secret CpIlPVCXI7******
      device_name LightSwitch

      设备的名称。

      因设备激活时会校验DeviceName,建议您采用可以直接从设备中读取到的ID,如设备的MAC地址、IMEI或SN码等,作为DeviceName使用。

  2. 配置消息回调
    1. 配置消息回调函数。
      • 示例代码:
         int main(int argc, char *argv[])
        {
            ……
            ……
        
            aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_RECV_HANDLER, (void *)demo_dynregmq_recv_handler);
            aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_USERDATA, (void *)&demo_info);
        
            ……
            ……
        }
      • 相关参数:
        配置项 示例值 说明
        AIOT_DYNREGMQOPT_RECV_HANDLER demo_dynregmq_recv_handler 设置消息回调。当接收消息时,根据该回调函数的设置,执行对应的处理。
        AIOT_DYNREGMQOPT_USERDATA &demo_info 设置上下文。当demo_dynregmq_recv_handler被调用时,该值会被传回。
    2. 定义消息回调函数。
      void demo_dynregmq_recv_handler(void *handle, const aiot_dynregmq_recv_t *packet, void *userdata)
      {
          switch (packet->type) {
              /* TODO: 回调中需保存packet指向的空间内容,回调返回后, 这些空间会被释放。 */
              case AIOT_DYNREGMQRECV_DEVICEINFO_WL: {
                  if (strlen(packet->data.deviceinfo_wl.device_secret) >= sizeof(demo_devinfo_wl.device_secret)) {
                      break;
                  }
      
                  /* 预注册方式认证时, 确保持久保存device_secret。 */
                  memset(&demo_devinfo_wl, 0, sizeof(demo_devinfo_wl_t));
                  memcpy(demo_devinfo_wl.device_secret, packet->data.deviceinfo_wl.device_secret,
                         strlen(packet->data.deviceinfo_wl.device_secret));
              }
              break;
              /* TODO: 回调中需保存packet指向的空间内容,回调返回后, 这些空间会被释放。 */
              case AIOT_DYNREGMQRECV_DEVICEINFO_NWL: {
                  if (strlen(packet->data.deviceinfo_nwl.clientid) >= sizeof(demo_devinfo_nwl.conn_clientid) ||
                      strlen(packet->data.deviceinfo_nwl.username) >= sizeof(demo_devinfo_nwl.conn_username) ||
                      strlen(packet->data.deviceinfo_nwl.password) >= sizeof(demo_devinfo_nwl.conn_password)) {
                      break;
                  }
      
                  /* 免预注册方式认证时, 确保持久化保存clientid, username和password。 */
                  memset(&demo_devinfo_nwl, 0, sizeof(demo_devinfo_nwl_t));
                  memcpy(demo_devinfo_nwl.conn_clientid, packet->data.deviceinfo_nwl.clientid,
                         strlen(packet->data.deviceinfo_nwl.clientid));
                  memcpy(demo_devinfo_nwl.conn_username, packet->data.deviceinfo_nwl.username,
                         strlen(packet->data.deviceinfo_nwl.username));
                  memcpy(demo_devinfo_nwl.conn_password, packet->data.deviceinfo_nwl.password,
                         strlen(packet->data.deviceinfo_nwl.password));
              }
              break;
              default: {
      
              }
              break;
          }
      }

步骤三:发送请求

调用aiot_dynregmq_send_request,根据配置连接的参数,向服务器发起动态注册请求。

     res = aiot_dynregmq_send_request(dynregmq_handle);
    if (res < STATE_SUCCESS) {
        printf("aiot_dynregmq_send_request failed: -0x%04X\n", -res);
        return -1;
    }        

步骤四:接收应答

注册请求消息发送后,物联网平台返回应答报文。设备端调用aiot_dynregmq_recv,接收应答消息,根据消息回调函数,执行对应处理。

    res = aiot_dynregmq_recv(dynregmq_handle);
    if (res < STATE_SUCCESS) {
        printf("aiot_dynregmq_recv failed: -0x%04X\n", -res);
        return -1;
    }         

例程仅做打印操作,但在实际业务环境中,您还需编写代码,将返回的设备身份认证信息,保存至本地。每当设备登录时,通过该认证信息建立与物联网平台的连接。

    if (skip_pre_regist == 0) {
        printf("device secret: %s\n", demo_devinfo_wl.device_secret);
    } else {
        printf("clientid: %s\n", demo_devinfo_nwl.conn_clientid);
        printf("username: %s\n", demo_devinfo_nwl.conn_username);
        printf("password: %s\n", demo_devinfo_nwl.conn_password);
    }

步骤五:退出程序

调用aiot_dynregmq_deinit,销毁dynregmq客户端实例,释放资源。

    res = aiot_dynregmq_deinit(&dynregmq_handle);            

后续步骤

  • 例程文件配置完成后,需进行编译,生成可执行文件./output/dynregmq-basic-demo

    更多信息,请参见编译与运行

  • 关于运行结果的详细说明,请参见运行日志