网关故障替换

更新时间:2024-04-18 09:10:39下载pdf

本文将介绍如何使用网关开发框架开发支持故障替换功能的网关产品。

背景信息

网关故障替换功能是终端用户使用的网关出现硬件故障后,使用新的网关替换原来的故障网关,故障网关下的子设备和场景联动等数据自动迁移到新的网关。终端用户无需重新添加子设备和配置场景联动,从而提升用户体验。

工作原理

网关故障替换的本质是数据备份和恢复,网关开启故障替换功能后,定期把本地数据备份到云端,当网关出现硬件故障时,用新的网关代替故障网关,云端通知新的网关进行数据恢复,新的网关拉取故障网关最后一次的备份数据进行恢复。

IoT 网关支持各种 IoT 协议,通常是主控搭配模组的硬件架构,所以除了恢复业务层的数据以外,可能还涉及恢复模组的数据,如恢复故障网关的无线网络等,取决于具体的 IoT 协议或者模组,如果不是使用涂鸦模组,需要确保第三方模组支持故障提供功能。

使用方法

  • tuya_iot_sdk_pre_init 之前调用 tuya_gw_replacement_enable 来开启故障替换功能。
  • 若网关搭配了涂鸦网关 Zigbee 模组,需要在 SDK 初始化接口 tuya_iot_wired_wf_sdk_init 之后调用 tuya_gw_replacement_zigbee_init 接口初始化 Zigbee 网关故障替换业务,无需关心数据的备份和恢复。
  • 若网关使用第三方模组,或者需要备份和恢复私有的数据,则可以通过注册回调来实现。调用 tuya_gw_replacement_register_cb 接口注册故障替换回调处理。在备份回调中使用 tuya_gw_flt_rpl_put_cfg_file 接口推送要备份的文件,在恢复回调中使用 tuya_gw_flt_rpl_get_cfg_file 接口提取要恢复的文件。

回调函数

备份通知

/**
 * @brief Apply fault replacement package notification
 *
 * @param app_ver Application version
 *
 * @return OPERATE_RET OPRT_OK is success
 */
typedef OPERATE_RET(*GW_FLT_RPL_BACK_UP_CB)(OUT USHORT_T *app_ver);

备份结果通过

/**
 * @brief Notification of the end of file backup, and the application can clear the cache file at this time
 *
 * @param result Backup result
 *
 * @return OPERATE_RET OPRT_OK is success
 */
typedef OPERATE_RET(*GW_FLT_RPL_BACK_UP_DONE_NOTIFY_CB)(IN INT_T result);

被恢复通知

/**
 * @brief Gateway failure replacement recovery notification application callback
 *
 * @param app_ver Application version
 * @param errcode Recovery result, 0 means success.
 *
 * @return OPERATE_RET OPRT_OK is success
 */
typedef OPERATE_RET(*GW_FLT_RPL_RESTORE_NOTIFY_CB)(IN USHORT_T app_ver,OUT INT_T *errcode);

被恢复 2 阶段通知

/**
 * @brief Gateway failure replacement recovery step 2
 *
 * @return OPERATE_RET OPRT_OK is success
 */
typedef OPERATE_RET(*GW_FLT_RPL_RESTORE_STAGE2_CB)(VOID);

被恢复结果通知

/**
 * @brief Notification of end of recovery process
 *
 * @param errcode Recovery result, 0 means success.
 *
 * @return OPERATE_RET OPRT_OK is success
 */
typedef OPERATE_RET(*GW_FLT_RPL_RESTORE_DONE_NOTIFY_CB)(IN INT_T result);

API 说明

故障替换使能

/**
 * @brief Enable gateway replacement feature, which is disabled by default.
 * @note This API should be called before `tuya_iot_init`.
 */
VOID tuya_gw_replacement_enable(VOID);

故障替换初始化

/**
 * @brief Initiate Zigbee NCP replacement when Tuya's Zigbee module is used.
 * @note If you use Tuya's Zigbee module, SDK will backup and restore data for Zigbee NCP, you only
 *       need to call this API to initiate it with an NCP version.
 *
 * @param[in] version minimum NCP version that supports replacement feature.
 *
 * @return OPRT_OK on success. For others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tuya_gw_replacement_zigbee_init(CHAR_T *version);
#define tuya_gw_user_fault_replace_init tuya_gw_replacement_zigbee_init

获取替换文件

/**
 * @brief Extract the required files from the backup package
 *
 * @param filename Compressed package name
 * @param dir file name to extract
 * @return OPERATE_RET OPRT_OK is success
 */
OPERATE_RET tuya_gw_flt_rpl_get_cfg_file(IN CONST CHAR_T *filename, IN CONST CHAR_T *dir);

推送替换文件

/**
 * @brief Fill the files that need to be backed up into the package
 *
 * @param filename Compressed package name
 * @param dir File name to be packaged
 * @return OPERATE_RET OPRT_OK is success
 */
OPERATE_RET tuya_gw_flt_rpl_put_cfg_file(IN CONST CHAR_T *filename, IN CONST CHAR_T *dir);

故障替换处理注册

/**
 * @brief Register gateway replacement callback, which is used for custom module.
 * @note This API should be called after `tuya_iot_init`.
 *
 * @param[in] handler callback function.
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tuya_gw_replacement_register_cb(GW_FLT_RPL_CBS_S *handler);

使用示例

STATIC OPERATE_RET __fr_backup_cb(OUT USHORT_T *app_ver)
{
    PR_DEBUG("fr backup");

    /* 推送文件 */
    tuya_gw_flt_rpl_put_cfg_file("shadow", "/etc/");
    tuya_gw_flt_rpl_put_cfg_file("passwd", "/etc/");

    return OPRT_OK;
}

STATIC OPERATE_RET __fr_backup_done_cb(IN INT_T result)
{
    PR_DEBUG("fr backup done");

    return OPRT_OK;
}

STATIC OPERATE_RET __fr_restore_stage1_cb(IN USHORT_T app_ver,OUT INT_T *errcode)
{
    PR_DEBUG("fr restore stage1");

    *errcode = 0;

    tuya_gw_flt_rpl_get_cfg_file("shadow", "/etc/");
    tuya_gw_flt_rpl_get_cfg_file("passwd", "/etc/");

    return OPRT_OK;
}

STATIC OPERATE_RET __fr_restore_stage2_cb(VOID)
{
    PR_DEBUG("fr restore stage2");

    return OPRT_OK;
}

STATIC OPERATE_RET __fr_restore_done_cb(IN INT_T result)
{
    PR_DEBUG("fr restore done");

    if (result) {
        PR_ERR("restore failed");
    } else {
        PR_DEBUG("restore success");
    }

    return OPRT_OK;
}

VOID test_gw_fault_replacement(VOID)
{
    GW_FLT_RPL_CBS_S __gw_rf_cbs = {
        .gw_flt_rpl_back_cb                = __fr_backup_cb,
        .gw_flt_rpl_back_up_done_notify_cb = __fr_backup_done_cb,
        .gw_flt_rpl_restore_notify_cb      = __fr_restore_stage1_cb,
        .gw_flt_rpl_restore_stage2_cb      = __fr_restore_stage2_cb,
        .gw_flt_rpl_restore_done_notify_cb = __fr_restore_done_cb,
    };

    tuya_gw_replacement_register_cb( &__gw_rf_cbs );
}