OTA Updates

Last Updated on : 2023-09-22 03:41:43download

This topic describes how to manage firmware versions and implement firmware updates over the air (OTA) for sub-devices.

Description

The following sequence diagram shows how an OTA update for a sub-device works:

AppCloudSDKApplicationSub-deviceUpdate command (MQTT)Update command (MQTT)dev_upgrade callbacktuya_iot_upgrade_devDownload file (HTTPS)Response (HTTPS)GET_FILE_DATA_CBWrite image data to fileDownload process bar report (MQTT)Download process bar report (MQTT)loopSend firmware dataACKtuya_iot_dev_upgd_progress_reptUpdate process bar report (MQTT)Update process bar report (MQTT)loopReport new versiontuya_iot_gw_subdevice_updateUpdate sub-device version (HTTPS)Report OTA result (MQTT)AppCloudSDKApplicationSub-device
  1. The SDK notifies the application of new firmware updates available.
  2. The application calls the SDK’s update download function.
  3. The SDK downloads the updates in multiple packets and sends them to the application for processing.
  4. After the download is completed, the SDK notifies the application of the download result.
    • If the download is successful, the application sends the updates to the sub-device and calls the progress bar updating function.
    • If the download failed, the application calls the SDK’s update status reporting function to report update failure.

Prerequisites

Create firmware key

The firmware key is used to manage the firmware. One firmware key can be associated with multiple firmware versions. Steps to create a firmware key:

  1. On the page of Product Development, find the target product.

  2. Click Develop. The example uses a three-gang switch to show you how to create a firmware key.

    OTA Updates
  3. Click the Hardware Development tab. Choose Add Custom Firmware.

    OTA Updates
  4. Complete the required information and click Generate Firmware Key.

    Field description

    • Firmware Type: Choose Extended Firmware. The protocol type less than 10 is reserved for SDK use. The protocol type greater than or equal to 10 is custom.

    • Update Channel: It matches the input parameter of the protocol type that is bound with the sub-device.

    • Update Timeout: If the sub-device fails to report the new version number, the app will prompt end-users with a message saying update timeout.

      OTA Updates

Create firmware version

This section describes how to upload firmware updates to the platform.

  1. Click New Firmware Version.

    OTA Updates
  2. Enter the Firmware Version, upload the Production Firmware and Firmware Updates, and click Save & Enable.

    In this example, the firmware update file only contains a Hello World string for demonstration.

    OTA Updates
  3. Click Save and Enable.

    OTA Updates

Verify firmware updates

This section describes how to verify the updates by using the allowlist.

  1. Click More > OTA Updates.

    OTA Updates
  2. Select the firmware key and click New Update Deployment.

    OTA Updates
  3. Select the firmware version we created. For Update Method, choose Update Notification. Complete the description and click OK.

    OTA Updates
  4. Click Verify. Enter the virtual ID of the sub-device to add it to the allowlist.

    To find the virtual ID, open the Smart Life app and enter the control panel of the sub-device. Tap in the top right corner and tap Device Information.

    OTA Updates

How to

  • Call tuya_subdev_user_sigle_type_reg to register the device management callback and implement the callback for dev_upgrade.
  • You should implement the callbacks invoked when the gateway downloads the firmware update and notifies the sub-device of update installation.
  • Implement the communication between the gateway and sub-devices.

Data structure

/**
 * @brief sub-device management callback
 */
typedef struct __ty_gw_subdev_mgr_cbs_s {
    GW_PERMIT_ADD_DEV_CB                dev_add;            // permit joining callback, see GW_PERMIT_ADD_DEV_CB
    GW_DEV_DEL_CB                       dev_del;            // remove callback, see GW_DEV_DEL_CB
    DEV_RESET_IFM_CB                    dev_reset;          // reset callback, see DEV_RESET_IFM_CB
    GW_BIND_DEV_INFORM_CB               dev_bind;           // bind result callback, see GW_BIND_DEV_INFORM_CB

    DEV_OBJ_DP_CMD_CB                   dp_cmd_obj;         // obj DP command, see DEV_OBJ_DP_CMD_CB
    DEV_RAW_DP_CMD_CB                   dp_cmd_raw;         // raw DP command, see DEV_RAW_DP_CMD_CB
    DEV_DP_QUERY_CB                     dp_query;           // DP query, see DEV_DP_QUERY_CB

    DEV_HEARTBEAT_SEND_CB               dev_hb;             // heartbeat query callback, see DEV_HEARTBEAT_SEND_CB
    DEV_UG_INFORM_CB                    dev_upgrade;        // upgrade callback, see DEV_UG_INFORM_CB
    GW_DEV_WAKEUP_CB                    dev_wakeup;         // low power device wakeup callback, see GW_DEV_WAKEUP_CB
    GW_DEV_GRP_INFM_CB                  dev_grp_info;       // group control callback, see GW_DEV_GRP_INFM_CB
    GW_DEV_SCENE_INFM_CB                dev_sce_info;       // scene control callback, see GW_DEV_SCENE_INFM_CB

    GW_DEV_SIGMESH_TOPO_UPDAET_CB       bt_topo_update;     // Bluetooth LE device added callback, see GW_DEV_SIGMESH_TOPO_UPDAET_CB
    GW_DEV_SIGMESH_DEV_CACHE_DEL_CB     bt_cache_del;       // Bluetooth LE device removed callback, see GW_DEV_SIGMESH_DEV_CACHE_DEL_CB
    GW_DEV_SIGMESH_CONN_CB              bt_conn;            // Bluetooth LE device event callback, see GW_DEV_SIGMESH_CONN_CB

    DEV_ONLINE_STAT_SEND_CB             dev_online;         // online state changed callback, see DEV_ONLINE_STAT_SEND_CB
}TY_GW_SUBDEV_MGR_CBS_S;
/**
 * @brief tuya sdk ota firmware info
 */
typedef struct {
    /** firmware type */
    DEV_TYPE_T tp;
    /** upgrade type, see UPGRADE_TYPE_T */
    UPGRADE_TYPE_T type;
    /** firmware download URL */
    CHAR_T fw_url[FW_URL_LEN + 1];
    /** firmware version */
    CHAR_T sw_ver[SW_VER_LEN + 1];
    /** firmware size in BYTE */
    UINT_T file_size;
    /** firmware HMAC */
    CHAR_T fw_hmac[FW_HMAC_LEN + 1];
    /** firmware MD5 */
    CHAR_T fw_md5[FW_MD5_LEN + 1];
    /** is difference OTA or not */
    BOOL_T diff_ota;
} FW_UG_S;

API description

Report the update progress

#define tuya_iot_dev_upgd_progress_rept(percent, devid, tp) \
tuya_iot_dev_upgd_progress_with_remain_time(percent, devid, tp, 0)

Call this function to report the progress of the firmware update.

Report the update result

#define TUS_RD 1                     // ready
#define TUS_UPGRDING 2               // upgrading
#define TUS_UPGRD_FINI 3             // finish
#define TUS_UPGRD_EXEC 4             // error
OPERATE_RET tuya_iot_dev_upgd_result_report(IN CONST CHAR_T *dev_id, IN CONST DEV_TYPE_T type, IN CONST INT_T result);

The application calls this function to report the failure of a firmware update. By default, the change in version number indicates a successful update.

Update the firmware

OPERATE_RET tuya_iot_upgrade_dev_notify(IN CONST CHAR_T *devid,
                                      IN CONST FW_UG_S *fw, \
                                      IN CONST GET_FILE_DATA_CB get_file_cb, \
                                      IN CONST UPGRADE_NOTIFY_CB upgrd_nofity_cb, \
                                      IN CONST PVOID_T pri_data, \
                                      BOOL_T notify, UINT_T download_buf_size);
#define tuya_iot_upgrade_dev(devid, fw, get_file_cb, upgrd_nofity_cb, pri_data) \
  tuya_iot_upgrade_dev_notify(devid, fw, get_file_cb, upgrd_nofity_cb, pri_data, TRUE, 0)

The application calls this function to get the sub-device firmware update after receiving the callback for dev_upgrade.

  • get_file_cb is invoked when the gateway downloads the firmware update.
  • upgrd_nofity_cb is invoked when the gateway notifies the sub-device of the update installation.

Example

STATIC CHAR_T upg_dev[DEV_ID_LEN] = {0};

/**
 * @brief device OTA callback
 * @param[in]     fw          : OTA firmware information
 * @param[in]     total_len   : total length of OTA image
 * @param[in]     offset      : OTA image offset
 * @param[in]     data        : payload of OTA image
 * @param[in]     len         : length of data
 * @param[out]    remain_len  : tell SDK remain length
 * @param[in]     pri_data    : pri_data is passed as the argument of tuya_iot_upgrade_dev()
 */
STATIC OPERATE_RET __dev_ota_data(IN CONST FW_UG_S *fw,
                                  IN CONST UINT_T total_len,
                                  IN CONST UINT_T offset,
                                  IN CONST BYTE_T *data,
                                  IN CONST UINT_T len,
                                  OUT UINT_T *remain_len,
                                  IN PVOID_T pri_data)
{

    /**
     * TODO:
     *      Receiving OTA image data callback. Maybe should write to file
     */

     /**
      * Here we have an example showing what should do in this callback
      *     a) print OTA image data (maybe you should write to file )
      *     b) report to the cloud.
      */

    for (INT_T i = 0; i < len; i++) {
        PR_DEBUG_RAW("%02x ", data[i]);
    }
    PR_DEBUG_RAW("\n");

    UINT_T percent = 0;
    percent = ((offset * 100) / (total_len+1));
    if (percent >= 99) {
        percent = 98;
    }
    tuya_iot_dev_upgd_progress_rept(percent, upg_dev, fw->tp);

    return OPRT_OK;
}

/**
 * @brief device OTA notify callback
 * @param[in]     fw                : OTA firmware information
 * @param[in]     download_result   : result of download OTA image
 * @param[in]     pri_data          : pri_data is passed as the argument of tuya_iot_upgrade_dev()
*/
STATIC VOID __dev_ota_notify(IN CONST FW_UG_S *fw,
                             IN CONST INT_T download_result,
                             IN PVOID_T pri_data)
{

    /**
     * TODO:
     * download_result == OPRT_OK , download success , send notify to sub-device and transform it
     * download_result != OPRT_OK , download failed, report result
     */

    /**
     * Here we have an example :
     *      a) if download succeeded, report new software version
     *      b) if download failed, report result:
     *                  #define TUS_RD 1            // ready
     *                  #define TUS_UPGRDING 2      // upgrading
     *                  #define TUS_UPGRD_FINI 3    // finish
     *                  #define TUS_UPGRD_EXEC 4    // error
     */
    if (download_result == OPRT_OK) {
        tuya_iot_gw_subdevice_update(upg_dev, fw->sw_ver);
    } else {
        tuya_iot_dev_upgd_result_report(upg_dev, fw->tp, 4);
    }
}

/**
 * @brief SDK receives upgrade cmd callback
 * @param[in]     dev_id            : device's ID
 * @param[in]     fw                : OTA firmware information
*/
STATIC VOID __dev_upgrade_cb(CONST CHAR_T *dev_id, CONST FW_UG_S *fw)
{

    /**
      * TODO:
      * call tuya_iot_upgrade_dev() to download sub-device's new image and do something
      */

    strncpy(upg_dev, dev_id, SIZEOF(upg_dev));
    tuya_iot_upgrade_dev(dev_id, fw, __dev_ota_data, __dev_ota_notify, NULL);
}

TY_GW_SUBDEV_MGR_CBS_S dev_mgr_cbs = {
    .dev_upgrade   = __dev_upgrade_cb,
};

tuya_subdev_user_sigle_type_reg( &dev_mgr_cbs , DEV_ATTACH_MOD_1 );