/**
* @file tuya_sdk_callback.c
* @brief Common process - adapter the flash api
* @version 0.1
* @date 2021-10-22
*
* @copyright Copyright 2020-2021 Tuya Inc. All Rights Reserved.
*
*/
#include "tuya_tools.h"
#include <stdio.h>
#include "tkl_gpio.h"
#include "tkl_uart.h"
#include "tkl_system.h"
#include "tkl_memory.h"
#include "tkl_network_manager.h"

#include "tal_log.h"
#include "tal_gpio.h"
#include "tal_uart.h"
#include "tal_flash.h"
#include "tal_system.h"
#include "tal_nv_flash.h"
#include "tal_sw_timer.h"
#include "tal_zcl_group.h"
#include "tal_zcl_scene.h"
#include "tal_time_sync.h"
#include "tal_heartbeat.h"
#include "tal_data_send.h"
#include "tal_network_mgr.h"
#include "tal_zcl_identify.h"
#include "tal_data_receive.h"
#include "tal_attribute_rw.h"
#include "tal_firmware_cfg.h"
#include "tal_reset_factory.h"
#include "tal_zll_commissioning.h"
#include "tal_endpoint_register.h"

#include "app_common.h"
#include "app_config.h"
#include "app_cluster_on_off.h"
#include "app_cluster_level.h"
#include "app_cluster_color_control.h"
#include "app_light_tools.h"
#include "app_light_control.h"

TIMER_ID etimer_key_scan;
TIMER_ID etimer_blink_sw;
TIMER_ID etimer_countdown;
TIMER_ID etimer_shande_param;
TIMER_ID etimer_shande_rgbcw;
TIMER_ID etimer_join_start_delay;
TIMER_ID etimer_clr_rst_cnt_delay;
TIMER_ID etimer_save_data_delay;
TIMER_ID etimer_mf_blink;
TIMER_ID etimer_power_on_sync;
TIMER_ID etimer_join_end_sync;

#ifdef ENABLE_TAL_LOG
const char *g_net_st_str_test[] = {
    "TAL_ZG_NWK_IDLE",            ///< inner using
    "TAL_ZG_NWK_POWER_ON_LEAVE",  ///< power on and device is not joined network
    "TAL_ZG_NWK_POWER_ON_ONLINE", ///< power on and device is already joined network
    "TAL_ZG_NWK_JOIN_START",      ///< start joining network
    "TAL_ZG_NWK_JOIN_TIMEOUT",    ///< network joining timeout
    "TAL_ZG_NWK_JOIN_OK",         ///< network joined success
    "TAL_ZG_NWK_LOST",            ///< network lost, lost parent
    "TAL_ZG_NWK_REJOIN_OK",       ///< network rejoin ok
    "TAL_ZG_NWK_REMOTE_LEAVE",    ///< remove device by remote device
    "TAL_ZG_NWK_LOCAL_LEAVE",     ///< remove device by local
    "TAL_ZG_NWK_MF_TEST_LEAVE",   ///< remove device by PC test tools
    "TAL_ZG_NWK_ZLL_JOINED",      ///< network joined zll network
    "TAL_ZG_NWK_ZLL_LEAVE",       ///< remove device Zll Reset To Factory New
};
#endif

extern VOID_T app_onoff_count_down_timer_cb(TIMER_ID timer_id, VOID_T *arg);
extern VOID_T app_light_ctrl_blink_timer_cb(TIMER_ID timer_id, VOID_T *arg);
extern VOID_T app_light_ctrl_shade_param(TIMER_ID timer_id, VOID_T *arg);
extern VOID_T app_light_ctrl_shade_rgbcw(TIMER_ID timer_id, VOID_T *arg);

#ifndef GET_ARRAY_LEN
#define GET_ARRAY_LEN(x)    (SIZEOF(x) / SIZEOF(x[0]))
#endif

//power attribute list
#define POWER_ATTR_LIST \
    { 0x0000, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_SINGLETON), 0,   (UINT8_T*)0x0000UL }, /* 10 / Power Configuration / mains voltage*/\
    { 0x0020, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_SINGLETON), 0,   (UINT8_T*)0x00UL  }, /* 11 / Power Configuration / battery voltage*/\
    { 0x0021, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_SINGLETON), 0,   (UINT8_T*)0xC8 } , /* 12 / Power Configuration / battery percentage remaining*/\
    { 0xFFFD, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_SINGLETON), 0,   (UINT8_T*)0x0001  }, /* 13 / Power Configuration / cluster revision*/\

//identify attribute list
#define IDENTIFY_ATTR_LIST                                                                                                     \
    {0x0000, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)0x03},     /* 03 / Identify / ZCL Version*/ \
    {0x0001, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)FIRMWARE_VER},     /* 41 / Identify / Application Version*/\
    {0x0002, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)0x02},     /* 02 / Identify / Stack Version*/\
    {0x0003, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)0x01},     /* 01 / Identify / Hardware Version*/\
    {0x0004, ATTR_CHAR_STRING_ATTRIBUTE_TYPE, 16, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)"_TZ3210_wgz5hl0l"},/*  / Identify / Manufacturer Name*/\
    {0x0005, ATTR_CHAR_STRING_ATTRIBUTE_TYPE, 6, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T *)"TS130F"},/*  / Identify / ModelIdentifier*/\
    {0x0007, ATTR_ENUM8_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST), 0, (UINT8_T*)0x01},          /* 01 / Identify / Power Source*/\
    {0xFFFD, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x01},     /* 01 / Identify / cluster revision*/

//on/off attribute list
#define ON_OFF_LIGHT_ATTR_LIST                                                                                      \
    {0x5000, ATTR_ENUM8_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE),0, (UINT8_T *)0x00},      /* 00 （0：Off, 1：On）/ On/off / backlight(tuya private attribute)*/ \
    {0x8001, ATTR_ENUM8_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE),0, (UINT8_T *)0x00},      /* 00 (0: status indication (relay on, light on), 1: position indication (relay off, light on), 2: Off)/ Indicator status setting (tuya private attribute)*/

//group attribute list
#define GROUP_ATTR_LIST \
    { 0x0000, ATTR_BITMAP8_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x00 }, /* 12 / Groups / name support*/\
    { 0xFFFD, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x0002 }, /* 13 / Groups / cluster revision*/

//scene attribute list
#define SCENE_ATTR_LIST \
    { 0x0000, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x00 }, /* 15 / Scenes / scene count*/\
    { 0x0001, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x00 }, /* 16 / Scenes / current scene*/\
    { 0x0002, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x0000 }, /* 16 / Scenes / current group*/\
    { 0x0003, ATTR_BOOLEAN_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x00 }, /* 17 / Scenes / scene valid*/\
    { 0x0004, ATTR_BITMAP8_ATTRIBUTE_TYPE, 1, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x00 }, /* 18 / Scenes / name support*/\
    { 0xFFFD, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x0002 }, /* 19 / Scenes / cluster revision*/

//curtain private attribute list
    #define CURTAIN_PRIVATE_ATTR_LIST \
    { 0x0065, ATTR_ENUM8_ATTRIBUTE_TYPE, 1,(ATTR_MASK_READABLE|ATTR_MASK_WRITABLE), 0, (UINT8_T*)0x00}, /* 0 / costom control_back / forward*/\

//power attribute
CONST TAL_ATTR_T power_attr_list[] = {
    POWER_ATTR_LIST
};

// identify attribute
CONST TAL_ATTR_T identify_attr_list[] = {
    IDENTIFY_ATTR_LIST
};

//on/off attribute list
const TAL_ATTR_T onoff_attr_list[] = {
    ON_OFF_LIGHT_ATTR_LIST
};

// group attribute
CONST TAL_ATTR_T group_attr_list[] = {
    GROUP_ATTR_LIST
};

// scene attribute
CONST TAL_ATTR_T scene_attr_list[] = {
    SCENE_ATTR_LIST
};

// private attribute
CONST TAL_ATTR_T curtain_private_attr_list[] = {
    CURTAIN_PRIVATE_ATTR_LIST
};

#define DEF_CLUSTER_POWER_CLUSTER_ID(a) \
    { CLUSTER_POWER_CONFIG_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a)) },

#define DEF_CLUSTER_IDENTIFY_CLUSTER_ID(a) \
    {CLUSTER_IDENTIFY_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},

#define DEF_CLUSTER_ON_OFF_CLUSTER_ID(a) \
    {CLUSTER_ON_OFF_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},

#define DEF_CLUSTER_GROUPS_CLUSTER_ID(a) \
    {CLUSTER_GROUPS_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},

#define DEF_CLUSTER_SCENES_CLUSTER_ID(a) \
    {CLUSTER_SCENES_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},

#define DEF_CLUSTER_WINDOW_COVERING_CLUSTER_ID(a) \
    {CLUSTER_WINDOW_COVERING_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},

#define DEF_CLUSTER_PRIVATE_CLUSTER_ID(a) \
    {CLUSTER_PRIVATE_TUYA_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a))},    

// server cluster list
CONST TAL_CLUSTER_T app_server_cluster_list[] = {
    DEF_CLUSTER_POWER_CLUSTER_ID(power_attr_list)
    DEF_CLUSTER_IDENTIFY_CLUSTER_ID(identify_attr_list)
    DEF_CLUSTER_ON_OFF_CLUSTER_ID(onoff_attr_list)
    DEF_CLUSTER_GROUPS_CLUSTER_ID(group_attr_list)
    DEF_CLUSTER_SCENES_CLUSTER_ID(scene_attr_list)
    DEF_CLUSTER_PRIVATE_CLUSTER_ID(curtain_private_attr_list)
};

#define SERVER_CLUSTER_NUM GET_ARRAY_LEN(app_server_cluster_list)

//endpoint descriptor
TAL_ENDPOINT_T dev_endpoint_desc[] = {
    {1, ZHA_PROFILE_ID, ZG_DEVICE_ID_WINDOW_COVERING_DEVICE, SERVER_CLUSTER_NUM, (TAL_CLUSTER_T *)&app_server_cluster_list[0], 0, NULL},
};
/**
 * @brief 
 * 
 */
STATIC UINT8_T __app_power_on_check_rst_cnt_proc(void)
{
    UINT8_T v_rst_cnt=0;
    UINT8_T v_warm_start=0;
    TAL_KV_STATUS_T v_ret =TAL_KV_SUCC;
    TUYA_RESET_REASON_E v_reason = tal_system_get_reset_reason(NULL);

    TAL_PR_DEBUG("Reset Reason: %d", v_reason);
    if (TUYA_RESET_REASON_HW_WDOG == v_reason)
    {
        return 1;
    }
    v_ret =TAL_KV_SUCC;
    v_ret=tal_kv_flash_read(KV_ID_RST_CNT, 1, &v_rst_cnt);
    if (v_ret !=TAL_KV_SUCC && v_ret !=TAL_KV_KEY_NO_FOUND){
        return 1;
    }
    v_ret =TAL_KV_SUCC;
    v_ret=tal_kv_flash_read(KV_ID_WARM_ST, 1, &v_warm_start);
    if (v_ret !=TAL_KV_SUCC && v_ret !=TAL_KV_KEY_NO_FOUND){
        return 1;
    }

    if (v_warm_start != 0xa5)
    {
        v_warm_start = 0xa5;
        v_rst_cnt = 1;
        v_ret =TAL_KV_SUCC;
        v_ret=tal_kv_flash_write(KV_ID_RST_CNT, 1, &v_rst_cnt);
        if (v_ret !=TAL_KV_SUCC){
                return 1;
            }
        v_ret =TAL_KV_SUCC;
        v_ret=tal_kv_flash_write(KV_ID_WARM_ST, 1, &v_warm_start);
        if (v_ret !=TAL_KV_SUCC){
                return 1;
            }
        return 0;
    }

    v_rst_cnt++;
    if (v_rst_cnt >= 3)
    {
        TAL_PR_DEBUG("join by rst cnt over...");
        tal_sw_timer_start(etimer_join_start_delay, 20, TAL_TIMER_ONCE);

        //5S timeout for clear reset cnt
        tal_sw_timer_start(etimer_clr_rst_cnt_delay, 5000, TAL_TIMER_ONCE);
        return 0;
    }

    v_ret =TAL_KV_SUCC;
    v_ret=tal_kv_flash_write(KV_ID_RST_CNT, 1, &v_rst_cnt);
    if (v_ret !=TAL_KV_SUCC){
            return 1;
        }

    //5S timeout for clear reset cnt
    tal_sw_timer_start(etimer_clr_rst_cnt_delay, 5000, TAL_TIMER_ONCE);

    return 0;
}

/**
 * @note join start delay timer hander, join now
 * @param[in]  none
 * @param[out] none
 * @return none
 */
STATIC VOID_T __app_network_join_start_delay_cb(TIMER_ID timer_id, VOID_T *arg)
{
    tal_zg_join_start(ZIGBEE_JOIN_MAX_TIMEOUT);
}
/**
 * @brief 
 * 
 * @param timer_id 
 * @param arg 
 * @return STATIC 
 */
STATIC VOID_T __app_clr_rst_cnt_delay_cb(TIMER_ID timer_id, VOID_T *arg)
{
    UINT8_T v_rst_cnt =0;
    TAL_KV_STATUS_T v_ret =TAL_KV_SUCC;
    v_ret=tal_kv_flash_write(KV_ID_RST_CNT, 1, &v_rst_cnt);
    if (v_ret !=TAL_KV_SUCC){
            TAL_PR_DEBUG("clear reset cnt failed.");
            return;
        }
}
/**
 * @brief zigbee node init
 * 
 * @return VOID_T 
 */
STATIC VOID_T __app_router_node_init(VOID_T)
{
    TAL_ZG_NODE_CFG_T node_config = {
        .node_type = ZG_ROUTER,
        .tx_power = 11,
        .scan_interval = 0,
        .scan_duration = ZG_SCAN_DURATION_3,
    };
    tal_zg_node_config(&node_config);
}
/**
 * @brief Generally used for peripheral initialization
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET tuya_init_first(VOID_T)
{
    TAL_UART_CFG_T uart_cfg = {
        .rx_buffer_size = 256,
        .open_mode = 0,
        {
            .baudrate = 115200,
            .parity = TUYA_UART_PARITY_TYPE_NONE,
            .databits = TUYA_UART_DATA_LEN_8BIT,
            .stopbits = TUYA_UART_STOP_LEN_1BIT,
            .flowctrl = TUYA_UART_FLOWCTRL_NONE,
        }
    };
    tal_uart_init(USER_UART0, &uart_cfg);

    app_button_init();

#if (ENABLE_TAL_LOG == 1)
    tal_log_create_manage_and_init(TAL_LOG_LEVEL_DEBUG, 128, dev_uart_output);
#endif

    TAL_PR_DEBUG("/*********first init*********/");
    return OPRT_OK;
}
/**
 * @brief Generally used for register zigbee device
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET tuya_init_second(VOID_T)
{
    //initialize firmware infomation
    TAL_PR_DEBUG("Application version:%d", FIRMWARE_VER);

    //creat software timer

    tal_sw_timer_create(app_button_scan_cb, NULL, &etimer_key_scan);
    tal_sw_timer_create(app_light_ctrl_shade_param, NULL, &etimer_shande_param);
    tal_sw_timer_create(app_light_ctrl_shade_rgbcw, NULL, &etimer_shande_rgbcw);
    tal_sw_timer_create(app_light_ctrl_blink_timer_cb, NULL, &etimer_blink_sw);
    tal_sw_timer_create(app_onoff_count_down_timer_cb, NULL, &etimer_countdown);
    tal_sw_timer_create(__app_network_join_start_delay_cb, NULL, &etimer_join_start_delay);
    tal_sw_timer_create(__app_clr_rst_cnt_delay_cb, NULL, &etimer_clr_rst_cnt_delay);
    tal_sw_timer_create(app_light_ctrl_save_data_delay_cb, NULL, &etimer_save_data_delay);
    tal_sw_timer_create(app_light_ctrl_power_on_sync_cb, NULL, &etimer_power_on_sync);
    tal_sw_timer_create(app_light_ctrl_join_end_sync_cb, NULL, &etimer_join_end_sync);

    //register zigbee endpoint
    tal_zg_endpoint_register(dev_endpoint_desc, GET_ARRAY_LEN(dev_endpoint_desc));
    TAL_PR_DEBUG("identify init ret:%d", tal_zg_identify_init());
    tal_zll_target_touchlink_init();
    tal_zll_target_rssi_threshold_set(-90);


    //zigbee node configuration
    __app_router_node_init();

    //zigbee joining network configuration
    TAL_ZG_JOIN_CFG_T join_config = {
        .auto_join_power_on_flag = TRUE,
        .auto_join_remote_leave_flag = TRUE,
        .join_timeout = 20000,
    };
    tal_zg_join_config(&join_config);

    tal_time_sync_period_set(60 * 1000);

    __app_power_on_check_rst_cnt_proc();
    
    TAL_PR_DEBUG("/*********1.0.0 second init*********/");
    return OPRT_OK;
}
/**
 * @brief Generally used for initialization before manufacturing test
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET tuya_init_third(VOID_T)
{
    TAL_PR_DEBUG("/*********third init*********/");

    OPERATE_RET ret;

    ret = app_light_init();
    if (ret != OPRT_OK)
    {
        TAL_PR_DEBUG("light init ERROR");
    }
    return OPRT_OK;
}
/**
 * @brief Generally used for initialization after manufacturing test
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET tuya_init_last(VOID_T)
{
    UINT8_T version;
    
    tal_uart_deinit(USER_UART0);
    TAL_UART_CFG_T uart_cfg = {
        .rx_buffer_size = 256,
        .open_mode = 0,
        {
            .baudrate = 115200,
            .parity = TUYA_UART_PARITY_TYPE_NONE,
            .databits = TUYA_UART_DATA_LEN_8BIT,
            .stopbits = TUYA_UART_STOP_LEN_1BIT,
            .flowctrl = TUYA_UART_FLOWCTRL_NONE,
        }
    };
    tal_uart_init(USER_UART0, &uart_cfg);

    tal_zg_read_attribute(TUYA_PRIMARY_ENDPOINT,
                          CLUSTER_BASIC_CLUSTER_ID,
                          ATTR_APPLICATION_VERSION_ATTRIBUTE_ID,
                          (VOID_T *)&version,
                          sizeof(version));

	// tal_heartbeat_period_set(30*000);
    // tal_heartbeat_type_set(HEARTBEAT_APP_VERSION);
    TAL_PR_DEBUG("/*********last init %d*********/", version);
    return OPRT_OK;
}
/**
 * @brief user-defined callback interface in main loop.do not block!!!
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET tuya_main_loop(VOID_T)
{
    return OPRT_OK;
}
/**
 * @brief heartbeat report callback
 * NOTE: you can rewrite this API in application layer
 * 
 * @param[in]   status: heartbeat report status
 *
 * @return none
 */
VOID_T tal_heartbeat_report_callback(TAL_HEARTBEAT_TYPE_E type)
{
    TAL_PR_DEBUG("heartbeat: %d", type);
}
/**
 * @brief general message receive callback
 * 
 * @param msg 
 * @return TAL_MSG_RET_E 
 */
TAL_MSG_RET_E tal_zcl_general_msg_recv_callback(TAL_ZCL_MSG_T *msg)
{
    //TAL_PR_DEBUG("app gen msg cb: cluster 0x%02x, cmd %d", msg->cluster, msg->command);

    return ZCL_MSG_RET_SUCCESS;
}
/**
 * @brief specific message receive callback
 * 
 * @param msg 
 * @return TAL_MSG_RET_E 
 */
TAL_MSG_RET_E tal_zcl_specific_msg_recv_callback(TAL_ZCL_MSG_T *msg)
{

    switch (msg->cluster)
    {
        case CLUSTER_WINDOW_COVERING_CLUSTER_ID: {     
            curtain_cluster_server_command_handler(msg);
            break;
        }

        case CLUSTER_PRIVATE_TUYA_CLUSTER_ID:
        {
            curtain_cluster_costom_command_handler(msg);
            break;
        }

        default:
            break;
    }

    return ZCL_MSG_RET_SUCCESS;
}
/**
 * @brief pre-save scene callback
 * 
 * @param ep_id 
 * @param scene_id 
 * @param group_id 
 * @return VOID_T 
 */
VOID_T tal_zg_scene_pre_save_callback(UINT8_T ep_id, UINT8_T scene_id, UINT16_T group_id)
{
    TAL_PR_DEBUG("scene pre save: ep %d, sce %d, gp 0x%02x", ep_id, scene_id, group_id);
}
/**
 * @brief save scene callback(add scene and store scene)
 * 
 * @param ep_id 
 * @param scene_id 
 * @param group_id 
 * @param data 
 * @return VOID_T 
 */
VOID_T tal_zg_scene_save_callback(UINT8_T ep_id, UINT8_T scene_id, UINT16_T group_id, TAL_SCENE_DATA_T *data)
{
    TAL_PR_DEBUG("scene save: ep %d, sce %d, gp 0x%02x, type %d", ep_id, scene_id, group_id, data->type);

    UINT8_T onoff;
    LIGHT_MODE_E mode;
    UINT16_T bright;
    UINT16_T temper;

    app_light_ctrl_data_switch_get((UINT8_T *)&onoff);
    app_light_ctrl_data_mode_get((LIGHT_MODE_E *)&mode);
    app_light_ctrl_data_bright_get(&bright);
    app_light_ctrl_data_temper_get(&temper);

    data->pdata[0] = onoff;
    data->pdata[1] = mode;

    data->pdata[2] = 0;
    data->pdata[3] = 0;

    data->pdata[4] = 0;
    data->pdata[5] = 0;

    data->pdata[6] = 0;
    data->pdata[7] = 0;

    data->pdata[8] = bright >> 8;
    data->pdata[9] = bright;

    data->pdata[10] = temper >> 8;
    data->pdata[11] = temper;

    data->len = 12;

    TAL_PR_DEBUG("ADD SCENE DATA LEN = 0x%x", data->len);
    TAL_PR_DEBUG("ADD SCENE DATA : ");
}
/**
 * @brief recall scene callback
 *
 * @param[in]   ep_id:     endpoint id
 * @param[in]   scene_id:  scene id
 * @param[in]   group_id:  group id
 * @param[in]   time100ms: scene transition time(bat:100ms)
 * @param[in]   data:      point to scene data
 * @return  VOID_T
 */
VOID_T tal_zg_scene_recall_callback(UINT8_T ep_id, UINT8_T scene_id, UINT16_T group_id, UINT_T time100ms, TAL_SCENE_DATA_T *data)
{
    TAL_PR_DEBUG("scene recall: ep %d, sce %d, gp 0x%02x, type %d", ep_id, scene_id, group_id, data->type);
    UINT8_T onoff;
    LIGHT_MODE_E mode;
    UINT8_T proc_flag = TRUE;

    UINT16_T app_bright;
    UINT16_T app_temper;

    OPERATE_RET ret = 0;

    UINT8_T pre_onoff;

    TAL_PR_DEBUG("RECALL SCENE DATA LEN = %d", data->len);
    onoff = data->pdata[0];
    mode = (LIGHT_MODE_E)(data->pdata[1]);
    app_bright = (data->pdata[8] << 8) | data->pdata[9];
    app_temper = (data->pdata[10] << 8) | data->pdata[11];

    app_light_ctrl_data_switch_get((UINT8_T *)&pre_onoff);
    ret = app_light_ctrl_data_switch_set(onoff);

    if (pre_onoff != onoff)
    {
        //onoff state has been changed, stop the count down timer, and report onoff
        app_onoff_set_count_down_report_flag_time(TRUE, 1000);
        app_onoff_data_count_down_set(0);
    }
    if (ret == OPRT_OK)
    {
        proc_flag = TRUE;
    }
    ret = app_light_ctrl_data_mode_set((LIGHT_MODE_E)mode);
    if (ret == OPRT_OK)
    {
        proc_flag = TRUE;
    }
    if (mode == WHITE_MODE)
    {
        ret = app_light_ctrl_data_bright_set(app_bright, 0);
        if (ret == OPRT_OK)
        {
            proc_flag = TRUE;
        }
        ret = app_light_ctrl_data_temp_set(app_temper, 0);
        if (ret == OPRT_OK)
        {
            proc_flag = TRUE;
        }
    }
    else
    {
        // do nothing
    }
    if (proc_flag)
    {
        app_light_ctrl_proc();
        app_onoff_report_value(QOS_0, 0, onoff);
        app_color_report_ty_temperature_value(QOS_0, 500, app_temper);
        app_level_report_ty_bright_value(QOS_0, 800, app_bright);
    }
}
/**
 * @brief add group callback
 *
 * @param[in]   ep_id:    endpoint id
 * @param[in]   group_id: group id
 * @return  VOID_T
 */
VOID_T tal_zg_add_group_callback(UINT8_T ep_id, UINT16_T group_id)
{
    TAL_PR_DEBUG("ep id: %d,group id: %d", ep_id, group_id);
}
/**
 * @brief view group callback
 *
 * @param[in]   ep_id:    endpoint id
 * @param[in]   group_id: group id
 * @return  VOID_T
 */
VOID_T tal_zg_view_group_callback(UINT8_T ep_id, UINT16_T group_id)
{
    TAL_PR_DEBUG("ep id: %d,group id: %d", ep_id, group_id);
}
/**
 * @brief remove group callback
 *
 * @param[in]   ep_id:    endpoint id
 * @param[in]   group_id: group id
 * @return  VOID_T
 */
VOID_T tal_zg_remove_group_callback(UINT8_T ep_id, UINT16_T group_id)
{
    TAL_PR_DEBUG("ep id: %d,group id: %d", ep_id, group_id);
}
/**
 * @brief zigbee network network change callback(user can rewrite this API)
 * 
 * @param[in]   status: network status
 * @return VOID_T
 */
VOID_T tal_zg_nwk_status_changed_callback(TAL_ZG_NWK_STATUS_E status)
{
    switch (status)
    {
    case TAL_ZG_NWK_POWER_ON_LEAVE:
    {
        TAL_PR_DEBUG("power_on_leave---");
        break;
    }
    case TAL_ZG_NWK_POWER_ON_ONLINE:
    {
        TAL_PR_DEBUG("power_on_online---");
        break;
    }
    case TAL_ZG_NWK_JOIN_START:
    {
        TAL_PR_DEBUG("nwk_join_start---");
        //light blink when steering
        app_light_ctrl_blink_start(1000);
        break;
    }
    case TAL_ZG_NWK_JOIN_OK:
    {
        TAL_PR_DEBUG("nwk_join_ok---");
        app_light_ctrl_blink_stop();
        break;
    }
    case TAL_ZG_NWK_REJOIN_OK:
    {
        TAL_PR_DEBUG("nwk_rejoin_ok---");
        break;
    }
    case TAL_ZG_NWK_JOIN_TIMEOUT:
    {
        TAL_PR_DEBUG("nwk_join_timeout---");
        app_light_ctrl_blink_stop();
        break;
    }
    case TAL_ZG_NWK_LOST:
    {
        TAL_PR_DEBUG("nwk_lost---");
        break;
    }
    case TAL_ZG_NWK_REMOTE_LEAVE:
    {
        TAL_PR_DEBUG("nwk_remote_leave---");
        app_light_ctrl_data_switch_set(TRUE);
        app_light_ctrl_data_mode_set(WHITE_MODE);
        app_light_ctrl_data_bright_set(1000, 0);
        app_light_ctrl_data_temp_set(1000, 0);
        app_light_ctrl_proc();
        break;
    }
    case TAL_ZG_NWK_LOCAL_LEAVE:
    {
        TAL_PR_DEBUG("nwk_local_leave---");
        break;
    }
    case TAL_ZG_NWK_MF_TEST_LEAVE:
    {
        TAL_PR_DEBUG("nwk_mf_test_leave---");
        break;
    }
    default:
    {
        break;
    }
    }
}
VOID_T tal_beacon_mf_test_callback(VOID_T)
{
    TAL_PR_DEBUG("enter beacon test\n");
    tal_sw_timer_create(app_light_ctrl_mf_blink_cb, NULL, &etimer_mf_blink);
    tal_sw_timer_start(etimer_mf_blink, 250, TAL_TIMER_ONCE);
}

/**
 * @brief reset factory default callback
 *
 * @param[in]   type: reset factory type
 * @return  VOID_T
 */
VOID_T tal_zg_reset_factory_default_callback(TAL_RESET_TYPE_T type)
{
    TAL_PR_DEBUG("receive reset to factory default cmd %d", type);
}

VOID_T tal_zll_target_commissioning_complete_callback(TAL_ZLL_TARGET_STATUS_E status)
{
    TAL_PR_DEBUG("zll target status %d",status);
}



VOID_T tal_time_sync_complete_callback(BOOL_T status, UINT_T time_sec)
{
 }
