All Products
Search
Document Center

IoT Platform:Sample code

Last Updated:Feb 08, 2023

This article describes how to call the API operations of Link SDK for C to upload device files to IoT Platform over MQTT. This reduces the overhead of hardware resources and development costs. In this example, the ./demos/mqtt_upload_basic_demo.c sample code file is used.

Context

  • For more information about the file uploading feature, see Overview.

  • You must use the MQTT protocol to upload files.

Step 1: Initialize a client

  1. Add header files.

    ……
    ……
    #include "aiot_mqtt_api.h"
    #include "aiot_mqtt_upload_api.h"
    #include "core_crc64.h"
    ……
  2. Add the underlying dependency and configure the log output feature.

    /* The collection of system-related functions that are stored in the portfiles/aiot_port folder. */
    extern aiot_sysdep_portfile_t g_aiot_sysdep_portfile;
    /* The server certificate located in external/ali_ca_cert.c. * /
    extern const char *ali_ca_cert;
    /* The callback to print logs of the SDK. */
    static int32_t demo_state_logcb(int32_t code, char *message)
    {
        printf("%s", message);
        return 0;
    }
  3. Call the aiot_mqtt_upload_init operation to create a client instance and initialize the default parameters.

        mqtt_handle = aiot_mqtt_upload_init();

Step 2: Configure required features

Call the aiot_mqtt_upload_setopt operation to configure the following items.

  1. Associate with an MQTT connection handle.

    Important

    Before you set file uploading-specific parameters, make sure that device authentication information is specified.

    You must establish an MQTT connection. The following sample code is used to associate with the MQTT connection handle:

        void *up_handle = aiot_mqtt_upload_init();
        aiot_mqtt_upload_setopt(up_handle, AIOT_MQTT_UPLOADOPT_MQTT_HANDLE, mqtt_handle);
  2. (Optional)

    Set the file uploading-specific parameters.

    • Sample code

          uint32_t rsp_timeout = 2000;
          aiot_mqtt_upload_setopt(up_handle, AIOT_MQTT_UPLOADOPT_RSP_TIMEOUT_MS, &rsp_timeout);
          uint32_t rety_count = 5;
          aiot_mqtt_upload_setopt(up_handle, AIOT_MQTT_UPLOADOPT_RETRY_COUNT, &rety_count);
          uint32_t block_size = 1024;
          aiot_mqtt_upload_setopt(up_handle, AIOT_MQTT_UPLOADOPT_DEFAULT_BLOCK_SIZE, &block_size);
    • Parameters:

      Parameter

      Description

      rsp_timeout

      Specifies the retransmission timeout period of each data packet, in milliseconds.

      If you do not specify this parameter or set this parameter to 0, the timeout period is 5 seconds.

      In this example, the value is set to 2000.

      AIOT_MQTT_UPLOADOPT_RSP_TIMEOUT_MS

      Calls the aiot_mqtt_upload_setopt operation to set the retransmission timeout period of each data packet.

      rety_count

      Specifies the number of retries if timeout errors occur.

      Default value: 10.

      In this example, the value is set to 5.

      AIOT_MQTT_UPLOADOPT_RETRY_COUNT

      Calls the aiot_mqtt_upload_setopt operation to set the number of retries if timeout errors occur.

      block_size

      Specifies the maximum size of each data packet, in bytes.

      Valid values: 256 to 131072. Default value: 2048.

      In this example, the value is set to 1024.

      AIOT_MQTT_UPLOADOPT_DEFAULT_BLOCK_SIZE

      Calls the aiot_mqtt_upload_setopt operation to set the maximum size of each data packet.

(Optional) Step 3: Calculate the CRC64 checksum of a file

When you upload a file, the CRC16 algorithm is used to calculate the file checksum by default. You can specify the CRC64 algorithm based on your business needs. By default, the SDK provides the CRC64-specific C library.

In this example, the CRC64 algorithm is used.

    uint64_t crc = mqtt_upload_get_file_crc64(MQTT_UPLOAD_FILE_NAME);

Step 4: Initiate a request to upload files

  1. Call the aiot_mqtt_upload_open_stream operation to initiate a file uploading request to IoT Platform.

    Important
    • If you upload files with the same name, do not call the aiot_mqtt_upload_open_stream operation to initiate multiple requests. After the uploading fails, you can reinitiate a request to upload the file.

    • If you upload files with different names, you can call the aiot_mqtt_upload_open_stream operation to initiate multiple requests. You can also initiate a request to upload multiple files.

    • Sample code

      • Define the file size and file name:

        #define MQTT_UPLOAD_FILE_SIZE       (2 * 1024)
        #define MQTT_UPLOAD_FILE_NAME       ("mqttuploadfile001.txt")
        #define MQTT_UPLOAD_FILE_SIZE2       (1 * 1024 + 127)
        #define MQTT_UPLOAD_FILE_NAME2       ("mqttuploadfile002.txt")
      • Initiate a request to upload files:

         uint32_t test_userdata = 100;
            aiot_mqtt_upload_open_stream(up_handle, MQTT_UPLOAD_FILE_NAME, MQTT_UPLOAD_FILE_SIZE,
                AIOT_MQTT_UPLOAD_FILE_MODE_OVERWRITE, &crc, mqtt_upload_read_data_handler, &test_userdata);
            mqtt_upload_create_upload_file(MQTT_UPLOAD_FILE_NAME2, MQTT_UPLOAD_FILE_SIZE2);
            aiot_mqtt_upload_open_stream(up_handle, MQTT_UPLOAD_FILE_NAME2, MQTT_UPLOAD_FILE_SIZE2,
                AIOT_MQTT_UPLOAD_FILE_MODE_OVERWRITE, NULL, mqtt_upload_read_data_handler, NULL);
    • Sample code description

      • In this example the operation is called to upload the following two files: mqttuploadfile001.txt and mqttuploadfile002.txt.

        Important
        • Take note of the following naming conventions for files:

          • Each file name can contain digits, letters, underscores (_), and periods (.).

          • Each file name must start with a digit or letter.

          • Each file name can be up to 100 bytes in length.

        • The size of a single file can be up to 16 MB.

      • The mqttuploadfile001.txt has a CRC64 checksum and the userdata parameter is specified.

      • The mqttuploadfile002.txt has no CRC64 checksum and the userdata parameter is not specified.

      • In this example, the processing policy is set to overwrite. The following table describes the available processing policies.

        Processing policy (conflictStrategy)

        Description

        overwrite

        This policy is used by default. If you use this policy, IoT Platform deletes the existing file and retains only the newly uploaded file.

        append

        After the device initiates the file uploading request, IoT Platform returns the information about the existing file with the same name. In this case, you can perform the following operations on the device:

        • If the uploading process of the file in IoT Platform is not completed, you can continue to upload the on-premises file.

          Note

          IoT Platform retains the files that are not completely uploaded for only 24 hours.

        • If the uploading process of the file in IoT Platform is completed, you can change the policy or raname the on-premises file. Then, upload the file again.

        reject

        IoT Platform returns an error code indicating that the file already exists and rejects the request to upload the on-premises file.

  2. After IoT Platform receives the request, IoT Platform returns a response to the device. After the device receives the response message, a callback is triggered to read the files.

    The SDK reads the files or the memory data by segment to obtain the data parameter. Then, the CRC16 algorithm is used to calculate the checksum of the data packet indicated by the data parameter.

    Important

    During the transmission of file segments, the maximum size of each data packet cannot exceed the value of the AIOT_MQTT_UPLOADOPT_DEFAULT_BLOCK_SIZE parameter. Each data packet must be at least 256 bytes, except for the last data packet.

    The mqtt_upload_read_data_handler callback is specified in the following sample code:

    int32_t mqtt_upload_read_data_handler(const aiot_mqtt_upload_recv_t *packet, uint8_t *data, uint32_t size, void *userdata) {
        int32_t read_len = 0;
        if (userdata != NULL) {
            uint32_t *test_userdata = (uint32_t *)userdata;
            printf("test_userdata:%d\r\n", *test_userdata);
        }
        if (packet == NULL) {
            return 0;
        }
        if (packet->desc.code == UPLOAD_FILE_OK) {
            if (data != NULL && size != 0) {
                uint32_t read_size = size;
                FILE *fp;
                char* file_name = packet->desc.file_name;
                fp = fopen(file_name, "r");
                uint32_t offset = packet->desc.file_offset;
                fseek(fp, offset, SEEK_SET);
                printf("Open %s read at: %d\r\n", file_name, offset);
                read_len = fread(data, sizeof(uint8_t), read_size, fp);
                printf("Read_len: %d\r\n", read_len);
                fclose(fp);
            }
        } else {
            printf("Error code:%d, message:%s\r\n", packet->desc.code, packet->desc.message);
        }
        return read_len;
    }
  3. (Optional)

    If you want to cancel file uploading, call the aiot_mqtt_upload_cancel_stream operation.

    For more information, see aiot_mqtt_upload_cancel_stream.

Step 5: Check file uploading statuses

You can call the aiot_mqtt_upload_process operation to cyclically detect the file uploading statuses. Sample code:

    while(1) {
        aiot_mqtt_upload_result_t result = aiot_mqtt_upload_process(up_handle);
        if (result.code == STATE_MQTT_UPLOAD_FINISHED) {
            /* The uploading is successful. */
            printf("MQTT Upload file(%s) success\r\n", result.file_name);
            uploaded_file++;
            if (uploaded_file == 2) {
                break;
            }
        } else if (result.code == STATE_MQTT_UPLOAD_FAILED ||
                   result.code == STATE_MQTT_UPLOAD_FAILED_TIMEOUT ||
                   result.code == STATE_MQTT_UPLOAD_CANCEL_FAILED ) {
            /* The uploading fails. */
            printf("MQTT Upload file(%s) failed,res:-0x%.4X\r\n", result.file_name, -result.code);
            /* Destroy the MQTT UPLOAD instance. */
        } else if (result.code == STATE_MQTT_UPLOAD_CANCEL_SUCCESS) {
            printf("MQTT Upload file(%s) cancel success,res:-0x%.4X\r\n", result.file_name, -result.code);
        } else if (result.code == STATE_MQTT_UPLOAD_FAILED_WHOLE_CHECK) {
            printf("MQTT Upload file(%s) whole file md5 failed,res:-0x%.4X\r\n", result.file_name, -result.code);
        }
        sleep(1);
    }

Step 6: Exit the program

Call the aiot_mqtt_upload_deinit operation to destroy the client instance and release resources.

aiot_mqtt_upload_deinit(&up_handle);

What's next

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

For more information, see Compilation and running.