OTA Update

Last Updated on : 2023-09-06 10:40:14download

An over-the-air (OTA) update is the wireless delivery of new software, firmware, or other data to connected IoT devices. TuyaOS Gateway Development Framework provides APIs to help you integrate the OTA update feature into your product easily.

This topic describes how to implement the OTA update feature with TuyaOS Gateway Development Framework.

Background

TuyaOS allows you to update both the gateway firmware and the subordinate firmware via OTA.

The subordinate firmware refers to the firmware on the external hardware integrated with the gateway, such as MCU, Zigbee module, and Bluetooth module.

Gateway firmware and subordinate firmware adopt the same OTA update process. The update channel is used to identify the type of firmware update.

The update channel for gateway firmware is fixed to 0. The update channels 1 to 9 are reserved for Tuya and not editable. If your gateway is integrated with a third-party module, set a value from [10, 19] as the update channel for the subordinate firmware. TuyaOS natively provides the OTA update feature for Tuya’s modules, so if you use an external module from Tuya, OTA-related development is not necessary.

Prerequisites

Get acquainted with Firmware Management and Firmware Update, which are necessary steps to deploy an OTA update to end devices using the Tuya IoT Development Platform.

How to

  • Register the update notification callback TY_GW_APP_CBS_S gw_upgrade_cb through tuya_iot_reg_gw_app_cb. In the callback, call tuya_iot_upgrade_gw to download the update.
  • In tuya_iot_upgrade_gw, you need to implement GET_FILE_DATA_CB and UPGRADE_NOTIFY_CB.
    • In the callback GET_FILE_DATA_CB, write data blocks to the file.
    • In the callback UPGRADE_NOTIFY_CB, perform the firmware update. If the firmware update is downloaded and verified successfully, the update is installed according to the firmware type indicated by FW_UG_S->tp. FW_UG_S->tp corresponds to the update channel specified on the Tuya IoT Development Platform.
  • The gateway reports the latest version number after a successful update and restart.

Process of OTA firmware update

CloudSDKApplicationOTA NotificationTY_GW_APP_CBS_S.gw_upgrade_cbtuya_iot_upgrade_gwStart a Thread to Download OTA FileOTA File Data Block RequestOTA File Data Block ResponseGET_FILE_DATA_CBloop[Break when the download is finished]OTA File Data ValidationUPGRADE_NOTIFY_CBUpdate and RebootInitialize with New VersionVersions ReportCloudSDKApplication

Example

/**
 * @brief OTA file block callback.
 * @note In the callback, save data to the OTA file. This callback is invoked multiple times until the file download is done.
 */
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)
{
    INT_T fd = 0;
    ssize_t w_len = 0;

    PR_DEBUG("OTA File Data, total len: %d, len: %d, offset: %d", total_len, len, offset);

    if (pri_data == NULL) {
        PR_ERR("pri_data is null");
        return OPRT_INVALID_PARM;
    }

    fd = *(INT_T *)pri_data;

    // Write data to file.
    w_len = write(fd, data, len);
    if (w_len <= 0) {
        close(fd);
        *remain_len = 0;
        return OPRT_COM_ERROR;
    }

    return OPRT_OK;
}

/**
 * @brief The notification callback for the result of OTA file download.
 * @note In the callback, determine the result of file download. If the result is a success, install the update according to the firmware type.
    */
STATIC OPERATE_RET __dev_ota_notify(IN CONST FW_UG_S *fw, IN CONST INT_T download_result, IN PVOID_T pri_data)
{
    INT_T fd = 0;

    if (pri_data == NULL) {
        PR_ERR("pri_data is null");
        return OPRT_INVALID_PARM;
    }

    fd = *(INT_T *)pri_data;
    close(fd);

    // Determine the result of the firmware update download.
    if (download_result == OPRT_OK) {
        PR_DEBUG("OTA File Download Successfully");
        if (fw->tp == DEV_NM_ATH_SNGL) {
            // The main firmware. Update the main firmware.
        } else {
            // The subordinate firmware. Update the firmware according to the firmware type.
        }
    } else {
        PR_WARN("OTA File Download Failure");
    }

    return OPRT_OK;
}

/**
 * @brief Firmware update notification callback.
 * @note In the callback, download the firmware update.
 */
STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw)
{
    STATIC INT_T fd = 0;
    OPERATE_RET op_ret = OPRT_OK;

    PR_DEBUG("upgrade callback");
    PR_DEBUG("        tp: %d", fw->tp);
    PR_DEBUG("    fw_url: %s", fw->fw_url);
    PR_DEBUG("    sw_ver: %s", fw->sw_ver);
    PR_DEBUG("   fw_hmac: %s", fw->fw_hmac);
    PR_DEBUG(" file_size: %u", fw->file_size);

    // Remove the OTA file.
    remove(MY_FW_FILE);

    // Create the OTA file.
    fd = open(MY_FW_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0755);
    if (fd < 0) {
        PR_ERR("open error");
        return OPRT_COM_ERROR;
    }

    op_ret = tuya_iot_upgrade_gw(fw, __dev_ota_data, __dev_ota_notify, (VOID *)&fd);
    if (op_ret != OPRT_OK) {
        PR_ERR("tuya_iot_upgrade_dev err: %d", op_ret);
    }

    return;
}

STATIC VOID ota_demo(VOID)
{
    TY_GW_APP_CBS_S gw_app_cbs = {
        .gw_upgrade_cb     = __gw_upgrade_cb,
    };

    // Register the update notification callback.
    tuya_iot_reg_gw_app_cb(&gw_app_cbs);

    // Update the main firmware. The new firmware version number should be passed in after the update is installed.
    // tuya_iot_wr_wf_sdk_init

    // Update the subordinate firmware. The new firmware version number should be reported after the update is installed.
    // tuya_user_ncp_ver_upload_reg
}