Device OTA development

更新时间:
复制 MD 格式

Alibaba Cloud IoT Platform provides over-the-air (OTA) update and management services for devices. This topic describes how a device can complete a remote upgrade using the IoT Platform.

Prerequisites

Procedure

The following time series chart illustrates the device upgrade process. The procedure is described using the device application ./demos/ota_basic_demo.c as an example.

image

Step 1: Initialize the device

  1. Create a device handle and establish a connection for the device.

    static void* demo_device_init(char *product_key, char *device_name, char *device_secret, char *host, uint16_t port)
    {
        int32_t res = STATE_SUCCESS;
        /* Create a device. */
        void *device = aiot_device_create(product_key, device_name);
        if (device == NULL) {
            printf("device create failed\n");
            return NULL;
        }
        /* Set the device secret. */
        aiot_device_set_device_secret(device, device_secret);
    
        /* Initialize the connection configuration parameters. */
        aiot_linkconfig_t* config = aiot_linkconfig_init(protocol);
        /* Set the host and port of the server. */
        aiot_linkconfig_host(config, host, port);
    
        /* Set the device connection parameters. */
        aiot_device_set_linkconfig(device, config);
        
        /* Establish a connection for the device. */
        res = aiot_device_connect(device);
        if (res < STATE_SUCCESS) {
            /* If the connection fails, destroy the MQTT instance and revoke resources. */
            aiot_linkconfig_deinit(&config);
            aiot_device_delete(&device);
            printf("aiot_device_connect failed: -0x%04X\n\r\n", -res);
            return NULL;
        }
    
        /* If the connection is successful, return the device object. */
        aiot_linkconfig_deinit(&config);
        return device;
    }
  2. Set the OTA message callback.

    memset(&ota_task, 0, sizeof(ota_task));
        ota_task.device = device;
        ota_task.ota_process_flag = 0;
        ota_task.filename = "fireware.bin";
        /* Set the OTA callback function. */
        aiot_device_ota_set_callback(device, demo_ota_msg_callback, &ota_task);

Step 2: Report the device version number

The IoT Platform determines whether to push an upgrade based on the reported device version number.

  /* Report the device version number. */
    aiot_device_ota_report_version(device, NULL, "4.0.0");

Step 3: Request firmware information

After the IoT Platform deploys the upgrade firmware, it pushes an upgrade message. If an upgrade task is available, the device can actively request the upgrade information.

  /* The device actively requests the upgrade package. If an upgrade task exists, the package is sent. */
    aiot_device_ota_request_firmware(device, NULL);

Step 4: Process the firmware information

The OTA message callback is set in Step 1. This callback function is executed when a message is received. Because the callback function cannot be blocked for a long time, you must create a new thread to handle the firmware download and upgrade actions.

static void demo_ota_msg_callback(void *device, const aiot_ota_msg_t *ota_msg, void *userdata)
{
    int32_t res = STATE_SUCCESS;
    pthread_t ota_process_thread;
    demo_ota_task_t *task = (demo_ota_task_t *)userdata;
    if(ota_msg != NULL && ota_msg->http_url != NULL) {
        /* Check if the device is already upgrading to avoid repeated upgrades. */
        if(task->ota_process_flag != 0) {
            return;
        }

        /* The callback cannot be blocked for a long time. Copy the message for asynchronous processing. The copied object must be deleted. */
        task->ota_msg = aiot_ota_msg_clone(ota_msg);
        res = pthread_create(&ota_process_thread, NULL, demo_ota_process_thread, task);
        if (res < 0) {
            aiot_ota_msg_free(task->ota_msg);
            task->ota_msg = NULL;
            printf("pthread_create demo_ota_process_thread failed: %d\n", res);
            return;
        } else {
            /* Set the thread to the detached state for automatic resource revocation. */
            pthread_detach(ota_process_thread);
        }
    } else {
        printf("ota invalid message \r\n");
    }
}

Step 5: Download the firmware

The firmware download process stops when the download is complete. You can also set a timeout period for the download. The process also stops if the download times out.

    /* Download the file. */
    res = core_http_download_request(task->ota_msg->http_url, params, task->filename, save_file, NULL);

Step 6: Validate the firmware

You must validate the firmware to ensure that it is complete. This example uses MD5 validation. If the validation fails, do not perform the upgrade. Instead, report the failure status and stop the upgrade process.

 res = file_md5_check(task->filename, task->ota_msg->expect_digest);
    if(STATE_SUCCESS != res ) {
        /* If firmware validation fails, report the status. */
        aiot_device_ota_report_state(task->device, NULL, -3);
    }

Step 7: Report the upgrade status

Report the upgrade status to indicate the progress of the upgrade. For example, the following code reports a progress of 100% after the firmware download is complete. You can define the upgrade progress as needed.

/* After the file is successfully written to the file system or flash, report the upgrade progress. */
    aiot_device_ota_report_state(task->device, NULL, 100);

Step 8: Report the new version number

The IoT Platform considers the upgrade complete only when the reported version number matches the new firmware version number. Report the version number after the device restarts.

 /* Reporting the new version number indicates that the upgrade is complete. Report the version after a restart. */
    /*
    aiot_device_ota_report_version(task->device, NULL, ota_msg->version);
    */

Step 9: Deinitialize the device

  /* Disconnect the device and revoke its resources. */
    demo_device_deinit(device_client);