#include "user_mcu.h"
#include "tal_queue.h"
#include "tuya_iot_sdk_api.h"
#include "tuya_uart_com_api.h"
#include <string.h>
#include "uni_log.h"
#include "tkl_thread.h"
#include "tal_uart.h"
#include "dp_process.h"
#define MCU_RX_VER                      0x00             //模块发送帧协议版本号
#define MCU_TX_VER                      0x03             //MCU 发送帧协议版本号(默认)
#define PROTOCOL_HEAD                   0x07             //固定协议头长度
#define FRAME_FIRST                     0x55             //帧头第一字节
#define FRAME_SECOND                    0xaa             //帧头第二字节
#define WIFIR_UART_SEND_BUF_LMT         48              //根据用户DP数据大小量定,必须大于48
#define WIFI_UART_RECV_BUF_LMT          16              //串口数据接收缓存区大小,如MCU的RAM不够,可缩小
#define WIFI_DATA_PROCESS_LMT           24              //串口数据处理缓存区大小,根据用户DP数据大小量定,必须大于24

#define    HEAD_FIRST                   (0)
#define    HEAD_SECOND                  (1)        
#define    PROTOCOL_VERSION             (2)
#define    FRAME_TYPE                   (3)
#define    LENGTH_HIGH                  (4)
#define    LENGTH_LOW                   (5)
#define    DATA_START                   (6)

volatile unsigned char wifi_data_process_buf[PROTOCOL_HEAD + WIFI_DATA_PROCESS_LMT];     //串口数据处理缓存
volatile unsigned char wifi_uart_rx_buf[PROTOCOL_HEAD + WIFI_UART_RECV_BUF_LMT];         //串口接收缓存
volatile unsigned char wifi_uart_tx_buf[PROTOCOL_HEAD + WIFIR_UART_SEND_BUF_LMT + ONE_PACK_LEN];        //串口发送缓存

//---------------------------------------
volatile int           current_temp;//当前温度
volatile unsigned char current_humi;//当前湿度
volatile unsigned char convert_state;
volatile unsigned char mcu_qu_state;

static unsigned char uart_state = 0;

//...
STATIC Attach_Mcu_Update_State attach_mcu_update = Attach_mcu_state_init;

#define         DP_TYPE_RAW                     0x00        //RAW 类型
#define         DP_TYPE_BOOL                    0x01        //bool 类型
#define         DP_TYPE_VALUE                   0x02        //value 类型
#define         DP_TYPE_STRING                  0x03        //string 类型
#define         DP_TYPE_ENUM                    0x04        //enum 类型
#define         DP_TYPE_BITMAP                  0x05        //fault 类型

#define         MCU_HEAT_BEAT_CMD               (0)                              //心跳包,告诉他我还在工作
#define         MCU_DPID_TEMP                   (2)                              //温度
#define         MCU_DPID_HUMI                   (12)
#define         MCU_DPID_TEMP_UNIT_CONVERT      (11)                             //温湿度转换 enum 
#define         MCU_DPID_QU_SWITCH              (101)                            //显示屏开关 bool
#define         STATE_UPLOAD_CMD                (7)                              //状态上报	
#define         MCU_CRG1_WIFI_STATE_DPID        (102)                            //CRG1 wifi 状态

#define         MCU_UPLOAD_VER_CMD              (6)                            //MCU上报版本号VER	
#include        "tal_sleep.h"

typedef struct {
    UINT16_T                    usart_recv_dev_num;
    TKL_THREAD_HANDLE           g_user_uart_thread;
    QUEUE_HANDLE                usart_queue_hdl;
} USART_DEV_T;


STATIC USART_DEV_T usart_dev_head = {
    .usart_recv_dev_num = 0,
    .g_user_uart_thread = NULL,
    .usart_queue_hdl = NULL,
};

unsigned char get_check_sum(unsigned char *pack, unsigned short pack_len)
{
    unsigned short i;
    unsigned char check_sum = 0;
    
    for(i = 0; i < pack_len; i ++) {
        check_sum += *pack ++;
    }
    
    return check_sum;
}

void int_to_byte(unsigned int number,unsigned char value[4])
{
    value[0] = number >> 24;
    value[1] = number >> 16;
    value[2] = number >> 8;
    value[3] = number & 0xff;
}

/**
 * @brief  bytes 转 int
 * @param  
 * @return 
 * @note   
 */
unsigned long byte_to_int(const unsigned char value[4])
{
    unsigned long nubmer = 0;

    nubmer = (unsigned long)value[0];
    nubmer <<= 8;
    nubmer |= (unsigned long)value[1];
    nubmer <<= 8;
    nubmer |= (unsigned long)value[2];
    nubmer <<= 8;
    nubmer |= (unsigned long)value[3];
    
    return nubmer;
}

/**
 * @brief  crc32计算
 * @param  
 * @return 返回crc值
 * @note   
 */
unsigned int crc32_compute(unsigned char const * p_data, unsigned int size, unsigned int const * p_crc)
{
	unsigned int crc;
    crc = (p_crc == NULL) ? 0xFFFFFFFF : ~(*p_crc);
    for (unsigned int i = 0; i < size; i++)
    {
        crc = crc ^ p_data[i];
        for (unsigned int j = 8; j > 0; j--)
        {
            crc = (crc >> 1) ^ (0xEDB88320U & ((crc & 1) ? 0xFFFFFFFF : 0));
        }
    }
    return ~crc;
}

/**
 * @brief  填充串口一个字节
 * @param  
 * @return 返回长度
 * @note   
 */
unsigned short set_wifi_uart_byte(unsigned short dest, unsigned char byte)
{
    unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest;
    
    *obj = byte;
    dest += 1;
    
    return dest;
}

/**
 * @brief  填充串口buffer
 * @param  
 * @return 返回长度
 * @note   
 */
unsigned short set_wifi_uart_buffer(unsigned short dest, const unsigned char *src, unsigned short len)
{
    unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest;
    
    memcpy(obj,src,len);
    
    dest += len;
    return dest;
}

/**
 * @brief  串口写一数据
 * @param  in 数据  len 长度
 * @return null
 * @note   
 */
void wifi_uart_write_data(unsigned char *in, unsigned short len)
{
    INT_T ret;
    if((NULL == in) || (0 == len)) {
        return;
    }
    if(uart_state==0){
        return;
    }
    ret  = tal_uart_write(TUYA_UART_NUM_0,in,len);
    if(ret < 0){
        PR_DEBUG("tal_uart_write[%d]",ret);
    }
}

/**
 * @brief  CRG1与MCU相连的串口写一帧数据
 * @param  fr_type 类型  fr_ver 版本号 len 长度
 * @return null
 * @note   
 */
void wifi_uart_write_frame(unsigned char fr_type, unsigned char fr_ver, unsigned short len)
{
    unsigned char check_sum = 0;
    
    wifi_uart_tx_buf[HEAD_FIRST] = FRAME_FIRST;
    wifi_uart_tx_buf[HEAD_SECOND] = FRAME_SECOND;
    wifi_uart_tx_buf[PROTOCOL_VERSION] = fr_ver;
    wifi_uart_tx_buf[FRAME_TYPE] = fr_type;
    wifi_uart_tx_buf[LENGTH_HIGH] = len >> 8;
    wifi_uart_tx_buf[LENGTH_LOW] = len & 0xff;
    
    len += PROTOCOL_HEAD;
    check_sum = get_check_sum((unsigned char *)wifi_uart_tx_buf, len - 1);
    wifi_uart_tx_buf[len - 1] = check_sum;
    
    wifi_uart_write_data((unsigned char *)wifi_uart_tx_buf, len);

}

unsigned char mcu_dp_bool_update(unsigned char dpid,unsigned char value){//CRG1模组通过串口回传给MCU的函数1
    memset(wifi_uart_tx_buf,0,sizeof(wifi_uart_tx_buf));
    unsigned short send_len = 0;
    
    send_len = set_wifi_uart_byte(send_len,dpid);
    send_len = set_wifi_uart_byte(send_len,DP_TYPE_BOOL);
    
    send_len = set_wifi_uart_byte(send_len,0);
    send_len = set_wifi_uart_byte(send_len,1);

    if(value == FALSE) {
        send_len = set_wifi_uart_byte(send_len,FALSE);
    }else {
        send_len = set_wifi_uart_byte(send_len,1);
    }
    wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len);
    return 0;
}

/**
 * @brief  CRG1模组通过串口回传给MCU的函数2
 * @param  dpid  dp点  value 
 * @return 0
 * @note   
 */
unsigned char mcu_dp_enum_update(unsigned char dpid,unsigned char value){
    memset(wifi_uart_tx_buf,0,sizeof(wifi_uart_tx_buf));
    unsigned short send_len = 0;
    send_len = set_wifi_uart_byte(send_len,dpid);
    send_len = set_wifi_uart_byte(send_len,DP_TYPE_ENUM);
    send_len = set_wifi_uart_byte(send_len,0);
    send_len = set_wifi_uart_byte(send_len,1);
    send_len = set_wifi_uart_byte(send_len,value);
    wifi_uart_write_frame(STATE_UPLOAD_CMD,MCU_TX_VER,send_len);
    return 0;
}

/**
 * @brief  crg1 向mcu 发送ota 升级指令
 * @param  frame  帧数据
 * @return 0
 * @note   
 */
unsigned char crg1_upgrade_mcu_ota_cmd(USART_FRAME_CMD_T* frame){
    if(frame==NULL)return 1;
    unsigned char* ota_data     = frame->value;
    unsigned char  sub_ota_cmd  = frame->cmd;
    unsigned short len          = frame->size;
    
    memset(wifi_uart_tx_buf,0,sizeof(wifi_uart_tx_buf));
    unsigned short  send_len = 0;
    unsigned int    crc_temp = 0;
    send_len = set_wifi_uart_byte(send_len,sub_ota_cmd);//子ota命令
    if(sub_ota_cmd==UPDATE_TRANS_CMD){
        unsigned char trans_data_len[4];
        unsigned char trans_crc_array[4];
        int_to_byte(len,trans_data_len);
        crc_temp = crc32_compute(ota_data,len,&crc_temp);
        int_to_byte(crc_temp,trans_crc_array);
        send_len = set_wifi_uart_buffer(send_len,trans_data_len,4);//增加发送的数目
        send_len = set_wifi_uart_buffer(send_len,trans_crc_array,4);//增加发送的数目
        //PR_DEBUG("ota_send_len[0x%x],crc[0x%x]",len,crc_temp);
    }
    send_len = set_wifi_uart_buffer(send_len,ota_data,len);//实际发送的数据
    wifi_uart_write_frame(STATE_UPDATE_CMD,MCU_TX_VER,send_len);
    return 0;
}

/**
 * @brief  crg1 请求得到mcu的版本号
 * @param  Null
 * @return Null
 * @note   
 */
unsigned char crg1_request_get_mcu_ver_cmd(void){
    unsigned short send_len = 0;
    send_len = set_wifi_uart_byte(send_len,MCU_UPLOAD_VER_CMD);
    wifi_uart_write_frame(MCU_UPLOAD_VER_CMD,MCU_TX_VER,send_len);
    return 0;
}

/**
 * @brief  wifi串口数据处理服务
 * @param  Null
 * @return Null
 * @note   在MCU主函数while循环中调用该函数
 */
void wifi_uart_service(unsigned short recv_count){
    static unsigned short rx_in = 0;
    unsigned short rx_value_len = 0;
    rx_in = recv_count;
    if(rx_in < PROTOCOL_HEAD)
        return;

    unsigned short ok = 0;
    
    if(wifi_data_process_buf[HEAD_FIRST] == FRAME_FIRST) {
        ok ++;
    }
    if(wifi_data_process_buf[HEAD_SECOND] == FRAME_SECOND) {
        ok ++;
    }  
    if(wifi_data_process_buf[PROTOCOL_VERSION] == MCU_TX_VER) {
        ok ++;
    }      
    rx_value_len = wifi_data_process_buf[LENGTH_HIGH] * 0x100;
    rx_value_len += (wifi_data_process_buf[LENGTH_LOW] + PROTOCOL_HEAD);
    if(recv_count == (rx_value_len)){
        ok ++;
    }
    //数据接收完成
    if(get_check_sum((unsigned char *)wifi_data_process_buf,rx_value_len - 1)%0x100 == wifi_data_process_buf[rx_value_len - 1]) {
        ok ++;
    }
    #if 0
    PR_DEBUG("wifi_uart_service_ok[%d],rx_value_len[%d]",ok,rx_value_len);
    for (size_t i = 0; i < rx_value_len; i++)
    {
        PR_DEBUG("[0x%x]  ",wifi_data_process_buf[i]);
    }
    PR_DEBUG("\r\n");
    #endif
    data_handle(rx_value_len);
}

/**
 * @brief  接收MCU发过来的串口信息处理
 * @param  rx_value_len   接收到的字符长度
 * @return Null
 * @note    
 */
void data_handle(unsigned char rx_value_len)
{
    extern OPERATE_RET attach_set_mcu_info(unsigned char *ver,unsigned char len);
    //unsigned char ret;
    unsigned char cmd_type = wifi_data_process_buf[FRAME_TYPE];
    uint8_t get_dpid;
    uint8_t data_type;
    //uint8_t data_len;
    uint8_t value_data[4];
    switch(cmd_type)
    {
        case MCU_HEAT_BEAT_CMD:
            PR_DEBUG("MCU_HEAT_BEAT_CMD");
            break;
        case MCU_UPLOAD_VER_CMD:
            PR_DEBUG("MCU_UPLOAD_VER_CMD");
            #if 1
            PR_DEBUG("value len:[0x%x][0x%x]",wifi_data_process_buf[LENGTH_HIGH] << 8 ,wifi_data_process_buf[LENGTH_LOW]);
            //PR_DEBUG("value: [0x%x][0x%x]",wifi_data_process_buf[DATA_START],wifi_data_process_buf[DATA_START+1]);
            //PR_DEBUG("value2:[0x%x][0x%x][0x%x]",wifi_data_process_buf[DATA_START+2],wifi_data_process_buf[DATA_START+3],wifi_data_process_buf[DATA_START+4]); 
            #endif 
            attach_set_mcu_info(&wifi_data_process_buf[DATA_START],(wifi_data_process_buf[LENGTH_HIGH] << 8) + (wifi_data_process_buf[LENGTH_LOW]));
            break;
        case STATE_UPLOAD_CMD:
            get_dpid = wifi_data_process_buf[DATA_START];
            switch (get_dpid)
            {
            case MCU_DPID_TEMP:
                data_type = wifi_data_process_buf[DATA_START+1];
                if(data_type == DP_TYPE_VALUE){
                    memset(value_data,0,sizeof(value_data));
                    value_data[0] = wifi_data_process_buf[DATA_START+4];
                    value_data[1] = wifi_data_process_buf[DATA_START+5];
                    value_data[2] = wifi_data_process_buf[DATA_START+6];
                    value_data[3] = wifi_data_process_buf[DATA_START+7];
                    unsigned long r_va = byte_to_int(value_data);
                    upload_device_temp_value((signed int)r_va);
                    PR_DEBUG("dpid[%d],value: %ld",MCU_DPID_TEMP,r_va);
                }
                break;
            case MCU_DPID_HUMI:
                data_type = wifi_data_process_buf[DATA_START+1];
                if(data_type == DP_TYPE_VALUE){
                    memset(value_data,0,sizeof(value_data));
                    value_data[0] = wifi_data_process_buf[DATA_START+4];
                    value_data[1] = wifi_data_process_buf[DATA_START+5];
                    value_data[2] = wifi_data_process_buf[DATA_START+6];
                    value_data[3] = wifi_data_process_buf[DATA_START+7];
                    unsigned long r_va = byte_to_int(value_data);
                    upload_device_humi_value((unsigned int)r_va);
                    PR_DEBUG("dpid[%d],value: %ld",MCU_DPID_HUMI,r_va);
                }
                break;
            case MCU_DPID_TEMP_UNIT_CONVERT:
                data_type = wifi_data_process_buf[DATA_START+1];
                if(data_type == DP_TYPE_ENUM){
                    uint8_t  temp_unit =  wifi_data_process_buf[DATA_START+4];
                    upload_device_convert_status(temp_unit);
                    PR_DEBUG("dpid[%d],value: %d",MCU_DPID_TEMP_UNIT_CONVERT,temp_unit);
                }
                break;
            case MCU_DPID_QU_SWITCH:
                data_type = wifi_data_process_buf[DATA_START+1];
                if(data_type == DP_TYPE_BOOL){
                    uint8_t  qu_switch = wifi_data_process_buf[DATA_START+4];
                    upload_device_switch_status(qu_switch);
                    PR_DEBUG("dpid[%d],value: %d",MCU_DPID_QU_SWITCH,qu_switch);
                }
                break;
            default:
                break;
            }
            break;
        default:break;
    }
}

/**
 * @brief  串口初始化
 * @param  
 * @return Null
 * @note    
 */
void mcu_uart_hw_init(void){
    tal_uart_deinit(TUYA_UART_NUM_0);
    OPERATE_RET ret = OPRT_OK;
    TAL_UART_CFG_T cfg = {0};
    cfg.base_cfg.baudrate = 115200;
    cfg.base_cfg.databits = TUYA_UART_DATA_LEN_8BIT;
    cfg.base_cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
    cfg.base_cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
    cfg.rx_buffer_size = 1024;
    
    ret = tal_uart_init(TUYA_UART_NUM_0, &cfg);
    uart_state = 1;
    //PR_DEBUG("mcu_uart_hw_init [%d]",ret);
}

/**
 * @brief  将数据发送给uart线程的队列
 * @param  sub_ota_cmd (ota指令) ota_data (数据)  Len  (长度)
 * @return Null
 * @note    
 */
unsigned char post_data_usart_queue(unsigned char sub_ota_cmd,unsigned char* ota_data,unsigned short len){
    OPERATE_RET op_ret = OPRT_OK;
    unsigned int crc_temp = 0;
    USART_FRAME_CMD_T *frame = (USART_FRAME_CMD_T *)malloc(sizeof(USART_FRAME_CMD_T));
    if(frame==NULL)return 1;
    if(len == 0)return 2;
    if(ota_data==NULL)return 3;
    frame->value = (unsigned char*)malloc(len*sizeof(unsigned char));
    if(frame->value==NULL)return 4;
    memcpy(frame->value,ota_data,len);
    frame->size = len;
    frame->cmd  = sub_ota_cmd;
    frame->crc  = crc32_compute(ota_data,len,&crc_temp);
    op_ret      = tal_queue_post(usart_dev_head.usart_queue_hdl, &frame, 500);
    PR_DEBUG("post_data_usart[%d],frame->crc[0x%x]", op_ret,frame->crc);
    if (OPRT_OK != op_ret) {
        PR_DEBUG("post queue error, %d", op_ret);
    }
    return 0;
}

/**
 * @brief  crg1与mcu串口主线程处理
 * @param  
 * @return Null
 * @note    
 */
STATIC void __user_uart_main_cb(void *arg){
    OPERATE_RET         op_ret = OPRT_OK;
    USART_FRAME_CMD_T   *usart_frame = NULL;

    mcu_uart_hw_init();//mcu串口初始化
    if (NULL == usart_dev_head.usart_queue_hdl) {
        op_ret = tal_queue_create_init(&usart_dev_head.usart_queue_hdl, 320, 1);
        //PR_DEBUG("tal_queue_create_init, %d", op_ret);
    }
    while(1)
    {
        op_ret = tal_queue_fetch(usart_dev_head.usart_queue_hdl, &usart_frame, 1000);
        if (OPRT_OK != op_ret) {
            //TAL_PR_ERR("wait semaphore error, %d", op_ret);
        }else{
            if(usart_frame != NULL){
                //PR_DEBUG("tal_queue_fetch_cout[%d]",usart_frame->size);
                crg1_upgrade_mcu_ota_cmd(usart_frame);
                if(usart_frame->value != NULL){
                    free(usart_frame->value);
                    usart_frame->value  = NULL;
                }
                free(usart_frame);
                usart_frame = NULL;
            }
        }
        
        UINT32_T recv_cout = tal_uart_get_rx_data_size(TUYA_UART_NUM_0); //读取到mcu串口的消息数
        if(recv_cout > 0){
            //PR_DEBUG("user_uart_main,recv_cout[%d]",recv_cout);
            tal_uart_read(TUYA_UART_NUM_0, wifi_data_process_buf, recv_cout);
            wifi_uart_service(recv_cout);//mcu串口处理
            memset(wifi_data_process_buf,0,sizeof(wifi_data_process_buf));//处理完清理一下
            recv_cout = 0;
        }
        
    }
    if (NULL != usart_dev_head.usart_queue_hdl) {
        tal_queue_free(usart_dev_head.usart_queue_hdl);
        usart_dev_head.usart_queue_hdl = NULL;
    }
    if(NULL != usart_dev_head.g_user_uart_thread){
        tkl_thread_release(usart_dev_head.g_user_uart_thread);
        usart_dev_head.g_user_uart_thread = NULL;
    }
}

/**
 * @brief  crg1与mcu串口主线 入口
 * @param  
 * @return Null
 * @note    
 */
void user_uart_mcu_main(void){
    tkl_thread_create(&usart_dev_head.g_user_uart_thread, "user_uart_main", 4096, 4, __user_uart_main_cb, NULL);
}


/**
 * @brief  crg1同步wifi的状态值
 * @param  
 * @return Null
 * @note    
 */
void CRG1_wifi_status_sync(SDK_WIFI_NW_STAT_T stat){
    if(SDK_STAT_UNPROVISION==stat){
        upload_device_temp_value(260);//上传一个默认值
        upload_device_humi_value(680);//上传一个默认值
    }
    mcu_dp_enum_update(MCU_CRG1_WIFI_STATE_DPID,stat);//将状态传给mcu
}

/**
 * @brief  crg1同步wifi网络状态
 * @param  
 * @return Null
 * @note    
 */
void crg1_wifi_network_status_sync(SDK_NW_STAT_T stat){
    mcu_dp_enum_update(MCU_CRG1_WIFI_STATE_DPID,stat);
}

/**
 * @brief  上电立即检测网络状态
 * @param  
 * @return Null
 * @note    
 */
void first_power_on_check_network_status(void){
    static unsigned short time = 0;
    if(time >= 0 && time < 200){
        time++;
    }
    if(time==200){
        GW_NW_STAT_T nw_stat = GNS_UNVALID;
        tuya_user_iot_get_gw_nw_stat(&nw_stat);
        if (nw_stat == GNS_WAN_VALID) {
            mcu_dp_enum_update(MCU_CRG1_WIFI_STATE_DPID,nw_stat);
        }
        time = 300;
    }
}

/**
 * @brief  打印接收到的ota 数据
 * @param  data len
 * @return  
 * @note    
 */
STATIC VOID_T __print_firmware_data(IN CONST BYTE_T *data, IN CONST UINT_T len)
{
    UINT_T i = 0;
    if(NULL == data || 0 == len) {
        return;
    }
    for(i = 0; i < len; i++) {
        TAL_PR_DEBUG_RAW("%02X ", data[i]);
        if(0 == ((i+1)%0x10)) {
            TAL_PR_DEBUG_RAW("\r\n");
        }
    }
    return;
}

/**
 * @brief  更新固件版本
 * @param  tp version
 * @return  
 * @note    
 */
STATIC VOID_T __update_firmware_version(IN CONST GW_PERMIT_DEV_TP_T tp, IN CONST CHAR_T *version)
{
    GW_ATTACH_ATTR_T attr = {0};

    TAL_PR_DEBUG("update tp:%d version:%s", tp, version);

    memset((UCHAR_T *)&attr, 0x00, SIZEOF(GW_ATTACH_ATTR_T));
    attr.tp  = tp;
    strncpy(attr.ver, version, SW_VER_LEN);
    tuya_iot_dev_set_attach_attr(tp, &attr);

    return;
}

STATIC OPERATE_RET __attach_download_result_notify_cb(IN CONST FW_UG_S *fw, IN CONST INT_T download_result, IN PVOID_T pri_data)
{
    PR_DEBUG("download  Finish");
    PR_DEBUG("download_result:%d", download_result);
    unsigned char download_arrary[4];
    int_to_byte((unsigned int)download_result,download_arrary);
    attach_mcu_update = Attach_mcu_state_end;
    //post_data_usart_queue(UPDATE_END_CMD,download_arrary,4);
    return OPRT_OK;
}

/**
 * @brief  附属固件OTA数据的回调
 * @param  
 * @return  
 * @note    
 */
STATIC OPERATE_RET __get_attach_fw_data_cb(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)
{
    OPERATE_RET op_ret = OPRT_OK;
    UINT_T pack_cnt = 0, i = 0, send_len = 0;
    if(attach_mcu_update == Attach_mcu_state_init){
        attach_mcu_update = Attach_mcu_state_start;
        unsigned char total_arrary[4];
        int_to_byte(total_len,total_arrary);
        //op_ret = post_data_usart_queue(UPDATE_START_CMD,total_arrary,4);;
    }
    TAL_PR_DEBUG("Rev File Data,Total_len:%d,Offset:%d Len:%d",total_len,offset, len);
    
    pack_cnt    = len/ONE_PACK_LEN;
    *remain_len = len % ONE_PACK_LEN;
    TAL_PR_DEBUG("pack_cnt:%d ,remain_len:%d", pack_cnt,(*remain_len));
    for (i=0; i<pack_cnt; i++) {
        //__print_firmware_data(&data[send_len], ONE_PACK_LEN);
        //通过Uart传数据给mcu
        //op_ret = post_data_usart_queue(UPDATE_TRANS_CMD,&data[send_len],ONE_PACK_LEN);
        send_len += ONE_PACK_LEN;
        TAL_PR_DEBUG("send_len:%d", send_len);
    }

    // last pack
    if (offset + len == total_len) {
        TAL_PR_DEBUG("the last fw pack");

        if ((*remain_len) > 0) {
            //__print_firmware_data(&data[send_len], (*remain_len));
            //通过Uart传数据给mcu;传最后一帧
            //op_ret = post_data_usart_queue(UPDATE_TRANS_CMD,&data[send_len],(*remain_len));
            send_len += (*remain_len);
            *remain_len = 0;
        }

        //update version
        __update_firmware_version(fw->tp, fw->sw_ver);
    }
    attach_mcu_update = Attach_mcu_state_ing;
    return OPRT_OK;
}

/**
 * @brief  附属固件OTA升级入口
 * @param  
 * @return  
 * @note    
 */
VOID attach_mcu_upgrade(CONST FW_UG_S *fw){
    if (fw->tp == DEV_NM_NOT_ATH_SNGL) {
        tuya_iot_upgrade_gw(fw, __get_attach_fw_data_cb, __attach_download_result_notify_cb, NULL);
    }
}