全部產品
Search
文件中心

:MQTT動態註冊使用樣本

更新時間:Jun 30, 2024

本文以C Link SDK中的Demo檔案./demos/dynregmq_basic_demo.c為例,介紹如何調用Link SDK的API,向物聯網平台發起MQTT協議的請求,動態註冊裝置,擷取啟用裝置所需的認證資訊

背景資訊

定製SDK時,在SDK定製頁面的裝置認證方案地區,需選中動態註冊。使用本樣本前,請確保您已閱讀並瞭解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_dynregmq_setopt,配置以下功能。

  1. 配置串連參數

  2. 配置訊息回調

  3. 更多功能的配置項,請參見MQTT動態註冊配置項

  4. 配置串連參數

    • 範例程式碼:

          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******

      在物聯網平台建立產品時,儲存的產品的ProductKey和ProductSecret。更多資訊,請參見建立產品

      product_secret

      CpIlPVCXI7******

      device_name

      LightSwitch

      裝置的名稱。

      因裝置啟用時會校正DeviceName,建議您採用可以直接從裝置中讀取到的ID,如裝置的MAC地址、IMEI或SN碼等,作為DeviceName使用。

  5. 配置訊息回調

    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

    更多資訊,請參見編譯與運行

  • 關於運行結果的詳細說明,請參見MQTT動態註冊作業記錄

  • 一型一密免預註冊下發的密鑰不是DeviceSecret,而是ClientIdUserNamePassword

    您可以在mqtt_basic_demo.c中通過AIOT_MQTTOPT_USERNAME, AIOT_MQTTOPT_PASSWORD, AIOT_MQTTOPT_CLIENTID這幾個配置項設定上述密鑰,調用aiot_mqtt_connect連雲,參考代碼如下。

     char *user_name  = "demo_user_name";
     char *password = "demo_passwd";
     char *client_id = "demo_client_id";
     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_USERNAME, user_name);
     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PASSWORD, password);
     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_CLIENTID, client_id);
     res = aiot_mqtt_connect(mqtt_handle);