All Products
Search
Document Center

IoT Platform:Example on how to dynamically register a device over MQTT

Last Updated:Jul 03, 2023

This topic describes how to call the API operations of Link SDK for C to send Message Queuing Telemetry Transport (MQTT) requests to IoT Platform, dynamically register a device, and obtain the verification information that is required to activate the device. In this example, a sample code file named ./demos/dynregmq_basic_demo.c is used.

Background information

When you customize an SDK, set Device authentication scheme to Dynamic registration on the SDK customization page. Before you use the sample code file in this topic, make sure that you are familiar with the content of the Overview topic.

Step 1: Initialize the SDK

  1. Add header files.

    #include "aiot_state_api.h"
    #include "aiot_sysdep_api.h"
    #include "aiot_dynregmq_api.h"
  2. Add the underlying dependency and configure the log output feature.

        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        aiot_state_set_logcb(demo_state_logcb);
  3. Call the aiot_dynregmq_init operation to create a client instance named dynregmq and initialize the default parameters.

        dynregmq_handle = aiot_dynregmq_init();
        if (dynregmq_handle == NULL) {
            printf("aiot_dynregmq_init failed\n");
            return -1;
        }

Step 2: Configure the required features

Call the aiot_dynregmq_setopt operation to configure the following items:

  1. Configure connection parameters.

  2. Configure a message callback.

  3. For more information, see MQTT-based dynamic registration.

  4. Configure connection parameters.

    • Sample code:

          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;
          ...
          /* Specify the endpoint of the server.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_HOST, (void *)host);
          /* Specify the port of the server.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PORT, (void *)&port);
          /* Specify the ProductKey of the device.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PRODUCT_KEY, (void *)product_key);
          /* Specify the ProductSecret of the device.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PRODUCT_SECRET, (void *)product_secret);
          /* Specify the DeviceName of the device.
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_DEVICE_NAME, (void *)device_name);
          /* Specify the security credential of the connection.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_NETWORK_CRED, (void *)&cred);
          /* Specify whether to use the preregistration-free verification method.  */
          aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_NO_WHITELIST, (void *)&skip_pre_regist);
          ...
          ...
    • Parameters:

      Parameter

      Examples

      Overview

      mqtt_host

      iot-06******.mqtt.iothub.aliyuncs.com

      The endpoint to which you want to connect the device.

      Format: ${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com.

      skip_pre_regist

      1

      Specifies whether to use the preregistration-free verification method.

      • 0: no

      • 1: yes

      Important

      For more information about pre-registration and preregistration-free unique-certificate-per-product verification methods, see Unique-certificate-per-product verification.

      product_key

      a18wP******

      The ProductKey and ProductSecret that you saved when you created the product in the IoT Platform console. For more information, see Create a product.

      product_secret

      CpIlPVCXI7******

      device_name

      LightSwitch

      The DeviceName of the device.

      IoT Platform checks the DeviceName when a device initiates an activation request. We recommend that you use an identifier that can be obtained from the device as the DeviceName. The identifier can be the MAC address, International Mobile Equipment Identity (IMEI) number, or serial number (SN) of the device.

  5. Configure a message callback.

    1. Specify a message callback function.

      • Sample code:

         int main(int argc, char *argv[])
        {
            ...
            Etc.
            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);
            ...
            Etc.
        }
      • Parameters:

        Parameter

        Example

        Description

        AIOT_DYNREGMQOPT_RECV_HANDLER

        demo_dynregmq_recv_handler

        Configures a message callback. When a message is received, the callback is called to perform the required operations.

        AIOT_DYNREGMQOPT_USERDATA

        &demo_info

        The context. When the demo_dynregmq_recv_handler operation is called, the value obtained from the operation is returned.

    2. Define the message callback function.

      void demo_dynregmq_recv_handler(void *handle, const aiot_dynregmq_recv_t *packet, void *userdata)
      {
          switch (packet->type) {
              /* TODO: You must save the space to which the packet parameter in the callback points. After the callback returns a result, the space is released.  */
              case AIOT_DYNREGMQRECV_DEVICEINFO_WL: {
                  if (strlen(packet->data.deviceinfo_wl.device_secret) >= sizeof(demo_devinfo_wl.device_secret)) {
                      break;
                  }
                  /* If you use the pre-registration verification method, make sure that the device_secret parameter is persisted.  */
                  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: You must save the space to which the packet parameter in the callback points. After the callback returns a result, the space is released.  */
              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;
                  }
                  /* If you use the preregistration-free verification method, make sure that the clientid, username, and password parameters are persisted.  */
                  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;
          }
      }

Step 3: Send a request

Call the aiot_dynregmq_send_request operation to send a dynamic registration request to the server. For information about how to configure the parameters, see Configure connection parameters.

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

Step 4: Receive a response

After the registration request is sent, IoT Platform returns a response. The device calls the aiot_dynregmq_recv operation to receive the response data and process the data by using the message callback.

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

In this example, the response data is printed. You must specify the logic to save the returned device verification information on premises. The verification information is used when the device connects to IoT Platform.

    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);
    }

Step 5: Exit the program

Call the aiot_dynregmq_deinit operation to delete the dynregmq client instance and release the related resources.

    res = aiot_dynregmq_deinit(&dynregmq_handle);            

What to do next

  • After you configure the sample code file, compile the file to generate an executable file. In this example, the ./output/dynregmq-basic-demo executable file is generated.

    For more information, see Prepare a development environment.

  • For more information about the running results, see View logs.

  • If you use the preregistration-free unique-certificate-per-product verification method to verify the device, IoT Platform issues the ClientId, UserName, and Password instead of DeviceSecret to the device after IoT Platform verifies the device.

    You can specify the ClientId, UserName, and Password for the AIOT_MQTTOPT_USERNAME, AIOT_MQTTOPT_PASSWORD, and AIOT_MQTTOPT_CLIENTID parameters in the mqtt_basic_demo.c file and call the aiot_mqtt_connect operation to connect the device to IoT Platform. The following sample code provides an example on how to perform the preceding operations:

     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);