This article describes how to call the API operations of Link SDK for C to distribute devices. In this example, the ./demos/bootstrap_posix_demo.c sample code file is used.

Background information

  • For more information about device distribution, see Overview.

  • After you obtain the connection information of a device by using the device distribution feature, you can connect the device to IoT Platform. For more information about MQTT connections, see Overview.

Step 1: Initialize a client

  1. Add header files.
    ...
    ...
    
    #include "aiot_bootstrap_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_bootstrap_init operation to create a bootstrap client instance and initialize the default parameters.
        bootstrap_handle =  aiot_bootstrap_init();
        if (bootstrap_handle == NULL) {
            printf("aiot_bootstrap_init failed\n");
            return -1;
        }

Step 2: Configure required features

Call the aiot_bootstrap_setopt operation to configure the following items:

  1. Set connection parameters.
    Notice You must set the TLS connection type to AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA.
    • Sample code
          int32_t res = STATE_SUCCESS;
          void *bootstrap_handle = NULL, *mqtt_handle = NULL;
          aiot_sysdep_network_cred_t cred;
          demo_info_t demo_info;
      
          /* TODO: Replace the values of the following parameters with the ProductKey, DeviceName, and DeviceSecret of your device. */
          char *product_key       = "a18wP******";
          char *device_name       = "LightSwitch";
          char *device_secret     = "uwMTmVAMnGGHaAkqmeDY6cHxxB******";
          ...
          ...
          memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
          cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA;  /* Verify the MQTT broker by using the RSA certificate. */
          cred.max_tls_fragment = 16384; /* The fragment can be up to 16 KB in length. Other optional values include 4 KB, 2 KB, 1 KB, and 0.5 KB. */
          cred.sni_enabled = 1;                               /* The server name indicator that is supported when you establish a TLS connection. */
          cred.x509_server_cert = ali_ca_cert;                 /* The RSA root certificate that is used to verify the MQTT broker. */
          cred.x509_server_cert_len = strlen(ali_ca_crt);     /* The length of the RSA root certificate that is used to verify the MQTT broker. */
          ...
          ...
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_HOST, (void *)host);
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_PORT, (void *)&port);
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_PRODUCT_KEY, (void *)product_key);
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_DEVICE_NAME, (void *)device_name);
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_NETWORK_CRED, (void *)&cred);
      
          ...
          ...
    • Parameters:
      Parameter Example Description
      product_key a18wP******

      The device authentication information. For more information, see Obtain device authentication information.

      In this example, the unique-certificate-per-device authentication method is used.

      The device_secret parameter is required when you establish an MQTT connection by using the obtained endpoint and port number.

      device_name LightSwitch
      device_secret uwMTmVAMnGGHaAkqmeDY6cHxxB******
  2. Configure a message callback.
    • Sample code
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_RECV_HANDLER, (void *)demo_bootstrap_recv_handler); 
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_USERDATA, (void *)&demo_info);
    • Parameters:
      Parameter Example Description
      AIOT_BOOTSTRAPOPT_RECV_HANDLER demo_bootstrap_recv_handler When a device distribution message is received, this callback is called.
      AIOT_BOOTSTRAPOPT_USERDATA demo_info Sets the context. When the demo_bootstrap_recv_handler callback is called, the userdata parameter is returned. You must convert the data type before you use this parameter.
  3. Configure status monitoring.
    1. Define the callback to monitor status.
      void demo_bootstrap_event_handler(void *handle, const aiot_bootstrap_event_t *event, void *userdata)
      {
          switch (event->type) {
              case AIOT_BOOTSTRAPEVT_INVALID_RESPONSE: {
                  printf("AIOT_BOOTSTRAPEVT_INVALID_RESPONSE\n");
              }
              break;
              case AIOT_BOOTSTRAPEVT_INVALID_CMD: {
                  printf("AIOT_BOOTSTRAPEVT_INVALID_CMD\n");
              }
              break;
              default: {
      
              }
              break;
          }
      }
    2. Specify the callbacks to monitor status.
      • Sample code
            aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_EVENT_HANDLER, (void *)demo_bootstrap_event_handler);
      • Parameters:
        Parameter Example Description
        AIOT_BOOTSTRAPOPT_EVENT_HANDLER demo_bootstrap_event_handler When the status of device connection changes, the callback is called to perform the required operations.

Step 3: Send a request

Notice Before you send a device distribution request, make sure that the device is distributed in IoT Platform. Otherwise, the current endpoint and port number of the device is returned.

Call the aiot_bootstrap_send_request operation to send an HTTPS request to the server. For more information about the parameters in the request, see the previous step.

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

Step 4: Receive a response

  1. After the message is sent, IoT Platform returns a response message. The device calls the aiot_bootstrap_recv operation to receive the response data and process the data by using the message callback.
        res = aiot_bootstrap_recv(bootstrap_handle);
        if (res < STATE_SUCCESS) {
            printf("aiot_bootstrap_recv failed, res: -0x%04X\n", -res);
            return -1;
        }
  2. Specify the processing logic of the callback.
    When you specify the processing logic of the callback, take note of the following items:
    Message type Description
    AIOT_BOOTSTRAPRECV_STATUS_CODE The HTTP status code that is returned by IoT Platform. For more information, see HTTP status codes.

    In this example, the logic to process received status codes is not specified. You can specify the logic based on your business needs.

    AIOT_BOOTSTRAPRECV_CONNECTION_INFO The response message that is returned by IoT Platform.

    aiot_bootstrap_recv_t indicates the message type. You must save the host and port parameters on premises.

    In this example, the response message is printed.

    AIOT_BOOTSTRAPRECV_NOTIFY The device distribution message that is sent by IoT Platform.

    After a device is distributed in IoT Platform, IoT Platform sends a message to the device.

    In this example, the message is printed. You must specify the logic to disconnect the device and re-initiate a device distribution request.

    void demo_bootstrap_recv_handler(void *handle, const aiot_bootstrap_recv_t *packet, void *userdata)
    {
        demo_info_t *demo_info = (demo_info_t *)userdata;
    
        switch (packet->type) {
            case AIOT_BOOTSTRAPRECV_STATUS_CODE: {
                demo_info->code = packet->data.status_code.code;
            }
            break;
            case AIOT_BOOTSTRAPRECV_CONNECTION_INFO: {
                demo_info->host = malloc(strlen(packet->data.connection_info.host) + 1);
                if (demo_info->host != NULL) {
                    memset(demo_info->host, 0, strlen(packet->data.connection_info.host) + 1);
                    /* TODO: Store the device distribution message to a specified location and release the memory space. */
                    memcpy(demo_info->host, packet->data.connection_info.host, strlen(packet->data.connection_info.host));
                    demo_info->port = packet->data.connection_info.port;
                }
            }
            break;
            case AIOT_BOOTSTRAPRECV_NOTIFY: {
                printf("AIOT_BOOTSTRAPRECV_NOTIFY, cmd: %d\n", packet->data.notify.cmd);
    
            }
            default: {
    
            }
            break;
        }
    }

(Optional) Step 5: Establish an MQTT connection

After you obtain the required endpoint and port number, connect the device with IoT Platform over MQTT. For more information about MQTT connections, see Overview.

After an MQTT connection is established, perform the following steps to distribute the device.

  1. Associate with an MQTT connection handle. by calling the aiot_bootstrap_setopt operation.
    • Sample code
          aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_MQTT_HANDLE, (void *)mqtt_handle);
    • Parameters:
      Parameter Example Description
      AIOT_BOOTSTRAPOPT_MQTT_HANDLE mqtt_handle When the device receives the distribution message sent by IoT Platform, this callback is called.
  2. Log on to the IoT Platform console and distribute the device.
  3. After the device receives the message, the device goes offline. Re-perform Step 1 to Step 4 to obtain the endpoint and re-connect the device to IoT Platform.

Step 6: Exit the program

Call the aiot_bootstrap_deinit operation to destroy the bootstrap client instance and release resources.

    res = aiot_bootstrap_deinit(&bootstrap_handle);
    if (res < 0) {
        printf("demo_start_stop failed\n");
        return -1;
    }

What to do next

  • After you configure the sample code file, compile the file to generate an executable file In this example, the ./demos/bootstrap-posix-demo executable file is generated.

    For more information, see Compilation and running.

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