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
Add header files.
…… …… #include "aiot_mqtt_api.h" #include "aiot_mqtt_upload_api.h" #include "core_crc64.h" ……
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; }
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.
Associate with an MQTT connection handle.
ImportantBefore 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);
(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
Call the aiot_mqtt_upload_open_stream operation to initiate a file uploading request to IoT Platform.
ImportantIf 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
andmqttuploadfile002.txt
.ImportantTake 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 theuserdata
parameter is specified.The
mqttuploadfile002.txt
has no CRC64 checksum and theuserdata
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.
NoteIoT 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.
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 thedata
parameter.ImportantDuring 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; }
(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.