#include <unistd.h>
#include "update_suport.h"
#include "define_base.h"
#include "update_file.h"
#include "toolkit.h"
#include "os_inf.h"
#include "bmser_log.h"
#include "bmser_dev.h"
#include "transfer_ext_server.h"
#include "exchange_with_mqtt.h"

#define UPDATE_STATUS_LEN 64
static const char *g_Upgrade_status[] = {
    "Upgrade_open_file_failed",
    "Upgrade_crc_check_failed",
    "Upgrade_failed",
    "Upgrade_doing",
    "Upgrade_finish"
};

typedef struct {
    char status[UPDATE_STATUS_LEN];
    int percent;
} OTA_DEV_STATUS_INFO_S;

static OTA_DEV_STATUS_INFO_S g_UPStatusInfo = {0};

typedef struct
{
    uint8_t bmuId;
    uint8_t bcuId;
    uint8_t bauId;
    uint8_t devType;                /*设备类型*/
    uint8_t level;                  /*设备层级*/
    uint8_t cmdCode;                /*操作指令*/
    uint8_t workId;                 /*处理事务类型*/
    uint8_t isHierMode;             /*CANID 或者消息流中 是否分层管理方式*/
}OTA_Dev_CAN_Infor_t;

typedef struct
{
    Std_Bool_Enum isUpdating;               /*是否正在升级*/
    uint8_t cluster_num;
    uint8_t destId;                         ////<根据当前的输入OTA信息获取当前的 ID

    uint32_t error_code;
    uint32_t fileOffset;                    /*当前传输的文件的偏移量*/
    uint32_t fileSize;                      /*文件长度*/
    void* loadingFile;                      /*当前加载的文件*/
    uint8_t frame[ONCE_PACKED_FRAME_SIZE];  /*维护的数据*/
    OTA_Dev_CAN_Infor_t s_devInfor;
}UPSP_Infor_Stru;
UPSP_Infor_Stru *g_pUPSPInfor = NULL;

#define WAIT_RECV_FRAM_TIMEOUT          1500     /*UNIT:10MS*/
#define WAIT_PROCESSED_FRAM_TIMEOUT     300     /*UNIT:10MS*/
#define WAIT_RECV_VER_TIMEOUT           2000    /*获取版本号等待时间*/
#define WAIT_SEND_TRY_TIMES             3       /*UNIT:次数*/
#define WAIT_SEND_VER_TRY_TIMES         5       /*发送show_version次数*/
#define MAX_TRY_RESET_TIMES             5       /*发送reset次数*/
#define MAX_NODE_NUM                    64
#define RESET_BEGIAN_WAIT_TIME          3       /*升级前复位等待时间，单位：s*/
typedef struct
{
    uint16_t waitTime;
    uint16_t tryTimes;
    Std_Base_Type realLen;
    Std_Bool_Enum frameAck;                     /*是否收到ACK信号*/
    Std_Bool_Enum processedAck;                 /*是否收到ACK信号*/
    Download_Step_Enum downStep;
    uint8_t recvd_node[MAX_NODE_NUM];           /*升级响应接收标志*/
    uint8_t recvd_node_debug[MAX_NODE_NUM];     /*Debug响应接收标志*/
    uint32_t fileCrc;
    uint8_t frame[ONCE_PACKED_FRAME_SIZE];
}UPSP_Send_Frame_Infor;

UPSP_Send_Frame_Infor g_UPFrameInfor = {0};

#define DEBUG_SIMULATE_QT    ////<模拟QT调试
/*-----------------------------------------------------------------------------------------
 Discription:  升级维护初始化
 Author:       DFS
 Date:         2019-08-27
 Param:        无
 Return:       Std_Ret_Ok:成功
               Std_Ret_Err:失败
 Modify:
*-----------------------------------------------------------------------------------------*/
Std_Ret_Type UpdateSup_Init(void)
{
    // Std_Base_Type i = 0;
    if(g_pUPSPInfor == NULL)
    {
        g_pUPSPInfor = (UPSP_Infor_Stru *)OS_Malloc(sizeof(UPSP_Infor_Stru));
        DEBUG_ASSERT((g_pUPSPInfor == NULL), "upsp init err1 \n");
    }
    {
        memset(g_pUPSPInfor, 0x00, sizeof(UPSP_Infor_Stru));
        g_pUPSPInfor->fileOffset = 0;
        g_pUPSPInfor->isUpdating = Std_False;
    }
#if 0
#ifdef DEBUG_SIMULATE_QT
        {
            update_simulate_start_newjob();
        }
#endif
#endif

    return Std_Ret_OK;
}

/*开启新的下载任务*/
Std_Ret_Type update_init_new_download_job(OTA_Exchange_Stru *pOTAData, uint32_t size)
{
    uint16_t level = pOTAData->dstLevel;
    // Std_Ret_Type ret = Std_Ret_ERR;
    memset(g_pUPSPInfor, 0x00, sizeof(UPSP_Infor_Stru));
    memset(&g_UPFrameInfor, 0x00, sizeof(g_UPFrameInfor));

    /*全局量*/
    g_pUPSPInfor->fileOffset = 0;
    g_pUPSPInfor->fileSize = size;
    g_UPFrameInfor.downStep = Download_Step_Send_Reset_Begin;
    g_pUPSPInfor->s_devInfor.isHierMode  = Std_False;
    g_pUPSPInfor->s_devInfor.bmuId = pOTAData->bmuId;
    g_pUPSPInfor->s_devInfor.bcuId = pOTAData->bcuId;
    g_pUPSPInfor->s_devInfor.bauId = pOTAData->bauId;
    g_pUPSPInfor->s_devInfor.level = pOTAData->dstLevel;
    g_pUPSPInfor->cluster_num = pOTAData->rackNum;

    if(level == BMS_HW_LEVEL_1){
        if(pOTAData->bmuId == CANRBUS_CANID_FLOW_BMUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_1_SLAVE;
        g_pUPSPInfor->destId = pOTAData->bmuId;
    }
    if(level == BMS_HW_LEVEL_2){
        if(pOTAData->bcuId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_2_IBU;
        g_pUPSPInfor->destId = pOTAData->bcuId;
    }
    if(level == BMS_HW_LEVEL_3){
        if(pOTAData->bauId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.bcuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_3_HUB;
        g_pUPSPInfor->destId = pOTAData->bauId;
    }
    g_pUPSPInfor->isUpdating = Std_True;
    return Std_True;
}

/*!
 * @brief       计算地址信息
 *
 * @param[in]   flow
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-7-28     dfs      Create             \n
 *
 */
uint16_t Update_Cal_Addr(UPSP_Infor_Stru *p_upinfor)
{
    uint16_t addr = 0;
    TRANSFER_DEVADDR_STRU *devAddr = (TRANSFER_DEVADDR_STRU *)&addr;
    TRANSFER_DEVADDR_BRO_STRU *broAddr = (TRANSFER_DEVADDR_BRO_STRU *)&addr;
    OTA_Dev_CAN_Infor_t *pOTAInfor = &p_upinfor->s_devInfor;

    if(p_upinfor->s_devInfor.isHierMode == Std_False){
        devAddr->bro = 0;
        devAddr->level3 = pOTAInfor->bauId;
        devAddr->level2 = pOTAInfor->bcuId;
        devAddr->level1 = pOTAInfor->bmuId;
    }
    else{
        broAddr->bro = 1;
        broAddr->broBAU = pOTAInfor->bauId;
        broAddr->broBCU = pOTAInfor->bcuId;
        broAddr->broLevel = pOTAInfor->level;
        broAddr->broType = pOTAInfor->devType;
    }
    return addr;
}


/*!
 * @brief     计算当前的消息类型
 *
 * @param[in]   p_upinfor
 * @param[in]   type
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-8-25     dfs      Create             \n
 *
 */
uint8_t Update_Cal_MsgType(UPSP_Infor_Stru *p_upinfor, uint8_t type)
{
    uint8_t msg_type;
    TRANSFER_MSG_TYPE_STRU *pMsgType = (TRANSFER_MSG_TYPE_STRU *)&msg_type;
    pMsgType->isCorretResp = 1;
    pMsgType->isHier = (p_upinfor->s_devInfor.isHierMode > 0)?1:0;
    pMsgType->isResp = 0;
    pMsgType->isTunnel = 1;
    pMsgType->cmdType = type & TRANSFER_TYPE_CMDTYPE_MASK;
    return msg_type;
}

/*
    按照最新4.1打包协议
    */
Std_Ret_Type packTransferFrame(uint32_t msgType, uint8_t *frame, uint32_t len)
{
    uint16_t crc, addr;
    TRANSFER_FRAMEWORK_STRU *pHeader = (TRANSFER_FRAMEWORK_STRU *)frame;
    pHeader->version = TRANSFER_PROTOCOL_VERSION;
    pHeader->destDevAddr = 0x0000;
    pHeader->version = TRANSFER_PROTOCOL_VERSION;
    addr =  Update_Cal_Addr(g_pUPSPInfor);
    pHeader->destDevAddr = HOST_TO_LITTLE_ENDIAN_16(addr);
    pHeader->msgType = Update_Cal_MsgType(g_pUPSPInfor, msgType);

    pHeader->msgLength = len;
    pHeader->msgType = msgType;
    crc = BmsMsg_Crc16(frame, len + sizeof(TRANSFER_FRAMEWORK_STRU));
    crc = HOST_TO_LITTLE_ENDIAN_16(crc);
    memcpy(&frame[sizeof(TRANSFER_FRAMEWORK_STRU)+len], &crc, sizeof(crc));

    return Std_Ret_OK ;
}


/*    读取复位命令    */
Std_Bool_Enum UpdateSup_ReadResetCmd(void* buff, Std_Base_Type maxlen, Std_Base_Type* realLen)
{
    uint16_t dev_addr = 0;
    TRANSFER_DEVADDR_STRU *p_dev_addr = (TRANSFER_DEVADDR_STRU *)&dev_addr;
    TRANSFER_DEVADDR_BRO_STRU *p_dev_bro = (TRANSFER_DEVADDR_BRO_STRU *)&dev_addr;
    OTA_Dev_CAN_Infor_t *p_dev_infor = &g_pUPSPInfor->s_devInfor;

    if(p_dev_infor->isHierMode == Std_True){
        p_dev_bro->bro = 1;
        p_dev_bro->broLevel = p_dev_infor->level;
        p_dev_bro->broType = p_dev_infor->devType;
        p_dev_bro->broBAU = p_dev_infor->bauId;
        p_dev_bro->broBCU = p_dev_infor->bcuId;
    }
    else{
        p_dev_addr->bro = 0;
        p_dev_addr->level1 = p_dev_infor->bmuId;
        p_dev_addr->level2 = p_dev_infor->bcuId;
        p_dev_addr->level3 = p_dev_infor->bauId;
    }
    *realLen = sprintf(buff,"0x%x reset",dev_addr);
    return Std_True;
}

/*    成功升级    */
void downloadSucceed(void)
{
    UPFile_CloseFile();
    g_pUPSPInfor->isUpdating = Std_False;
    memset(g_UPStatusInfo.status, 0, sizeof(g_UPStatusInfo.status));
    snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[4]);
    exchange_with_mqtt_send_upgrade_status(g_UPStatusInfo.status, strlen(g_UPStatusInfo.status), g_UPStatusInfo.percent);
}

/*    升级失败  */
void downloadFailed(void)
{
    UPFile_CloseFile();
    g_pUPSPInfor->isUpdating = Std_False;
    exchange_with_mqtt_send_upgrade_status(g_UPStatusInfo.status, strlen(g_UPStatusInfo.status), g_UPStatusInfo.percent);
}


typedef struct{
    uint8_t bmuId;
    uint8_t bcuId;
    uint8_t bauId;
    uint8_t devType;                /*设备类型*/
    uint8_t level;                  /*设备层级*/
    uint8_t cmdCode;                /*操作指令*/
    uint8_t workId;                 /*处理事务类型*/
    uint8_t isHierMode;             /*CANID 或者消息流中 是否分层管理方式*/
    uint16_t len;
    uint8_t *buf;
}Update_Exchange_XNCan_Load_t;

Std_Bool_Enum Update_IS_XNCan_CanInfor_Match(Update_Exchange_XNCan_Load_t *p_frame, UPSP_Infor_Stru *p_update_infor)
{
    Std_Bool_Enum is_match = Std_False;
    uint8_t level = p_update_infor->s_devInfor.level;
    do{
        if((p_frame->isHierMode) != p_update_infor->s_devInfor.isHierMode){
            break;
        }
        if((p_frame->cmdCode) != CANRBUS_DEBUG_RESP){
            break;
        }
        if(p_update_infor->s_devInfor.isHierMode){
            if(level == BMS_HW_LEVEL_1){
                if(p_frame->bmuId ==  CANRBUS_CANID_FLOW_BMUID_INVALD){
                    break;
                }
                if(p_frame->bcuId ==  CANRBUS_CANID_FLOW_BCUID_INVALD){
                    break;
                }
            }
            if(level == BMS_HW_LEVEL_2){
                if(p_frame->bcuId ==  CANRBUS_CANID_FLOW_BCUID_INVALD){
                    break;
                }
            }
            if(level == BMS_HW_LEVEL_3){
                if(p_frame->bauId ==  CANRBUS_CANID_FLOW_BAUID_INVALD){
                    break;
                }
            }
        }
        else{
            if(level == BMS_HW_LEVEL_1){
                if(p_frame->bmuId !=  p_update_infor->s_devInfor.bmuId){
                    break;
                }
                if(p_frame->bcuId !=  p_update_infor->s_devInfor.bcuId){
                    break;
                }
            }
            if(level == BMS_HW_LEVEL_2){
                if(p_frame->bcuId !=  p_update_infor->s_devInfor.bcuId){
                    break;
                }
            }
            if(level == BMS_HW_LEVEL_3){
                if(p_frame->bauId !=  p_update_infor->s_devInfor.bauId){
                    break;
                }
            }
        }
        is_match = Std_True;
    }
    while(0);
    return is_match;
}

Std_Bool_Enum Update_IS_XNCan_Content_Match(Update_Exchange_XNCan_Load_t *p_frame, UPSP_Infor_Stru *p_update_infor)
{
    uint8_t msg_type = 0;
    Std_Bool_Enum is_match = Std_False;
    // TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)p_frame->buf;

    do{
        TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)p_frame->buf;
        uint16_t addr = LITTLE_ENDIAN_TO_HOST_16(p_recv_header->destDevAddr);
        uint16_t crc = 0;
        if(p_recv_header->version != TRANSFER_PROTOCOL_VERSION){
            break;
        }
        msg_type = p_recv_header->msgType;
        if(TRANSFER_TYPE_IS_CORRECT_RESP(msg_type) == 0){
            break;
        }
        if (p_frame->len < 2)
            break;
        /*发送的长度中没有包含 CRC长度*/
        crc = BmsMsg_Crc16(p_frame->buf, p_frame->len);
        if(crc != 0){
            break;
        }
        {
            /*回复的消息中没有广播*/
            TRANSFER_DEVADDR_BRO_STRU *pBroLevel =  (TRANSFER_DEVADDR_BRO_STRU *)&addr;
            if(pBroLevel->bro > 0)
                break;
        }

        is_match = Std_True;
    }while(0);
    return is_match;
}

#pragma pack(1)
typedef struct{
    uint8_t id;
    uint32_t offset;
}Update_Transfer_Content_t;
#pragma pack()

void Update_Recv_OneNode_Response(uint8_t id, uint8_t recvd_no[MAX_NODE_NUM])
{
    if ((id < MAX_NODE_NUM) && (id > 0)) {
        recvd_no[id - 1] = 1;
    }
}

Std_Bool_Enum Update_IS_All_Node_Recvd(UPSP_Infor_Stru *p_update_infor, uint8_t recvd_no[MAX_NODE_NUM])
{
    uint32_t i = 0;
    OTA_Dev_CAN_Infor_t *p_otain = &p_update_infor->s_devInfor;

    if (p_otain->isHierMode) {
        if (p_update_infor->cluster_num < 1) {
            return Std_False;
        } else if ((1 == p_update_infor->cluster_num) && (BMS_HW_LEVEL_1 == p_otain->level)) {
            //只有一簇,且为广播升级这一簇的所有从控
            if (1 == recvd_no[g_pUPSPInfor->s_devInfor.bcuId - 1]) {
                return Std_True;
            }
        }

        for (i = 0; i < p_update_infor->cluster_num; i++) {
            if (recvd_no[i] == 0){
                return Std_False;
            }
        }
    } else {
        if (recvd_no[p_update_infor->destId - 1] == 0) {
            return Std_False;
        }
    }
    return Std_True;;

}

uint8_t Update_Select_VD_Id(OTA_Dev_CAN_Infor_t *p_otain, TRANSFER_DEVADDR_STRU *p_addr)
{
    uint8_t select_valid_id = 0;
    uint8_t bmu_id = 0, bcu_id = 0, bau_id = 0;
    bau_id = p_addr->level3;
    bcu_id = p_addr->level2;
    bmu_id = p_addr->level1;
    if(p_otain->isHierMode){
        if((p_otain->level == BMS_HW_LEVEL_1)|| (p_otain->level == BMS_HW_LEVEL_2)){
            select_valid_id = bcu_id;
        }
        if(p_otain->level == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    else{
        if(p_otain->level == BMS_HW_LEVEL_1){
            select_valid_id = bmu_id;
        }
        if(p_otain->level == BMS_HW_LEVEL_2){
            select_valid_id = bcu_id;
        }
        if(p_otain->level == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    return select_valid_id;
}


void Update_Translate_Msg(Update_Exchange_XNCan_Load_t *p_content, canrbus_xncan_header_t *p_payload, uint16_t len)
{
    if((NULL == p_content)||(NULL == p_payload)){
        return;
    }
    p_content->bauId = p_payload->msgFlowBauId;
    p_content->bcuId = p_payload->msgFlowBcuId;
    p_content->bmuId = p_payload->msgFlowBmuId;

    p_content->buf = p_payload->data;
    p_content->cmdCode = p_payload->func;
    p_content->isHierMode = p_payload->msgFlowUpdateType;
    p_content->level = p_payload->layer;
    p_content->workId = p_payload->msgFlowWorkId;
    if(len > sizeof(canrbus_xncan_header_t))
        p_content->len = len - sizeof(canrbus_xncan_header_t) - 2; /*单独减去CRC*/
    else
        p_content->len = 0;

    return ;
}

void Update_Parse_XNCan_PayLoad(Update_Exchange_XNCan_Load_t *p_frame, UPSP_Infor_Stru *p_update_infor, UPSP_Send_Frame_Infor *p_sent_frame)
{
    uint8_t msg_type = 0;
    uint8_t in_id = 0;
    TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)p_frame->buf;
    uint16_t addr = LITTLE_ENDIAN_TO_HOST_16(p_recv_header->destDevAddr);
    TRANSFER_DEVADDR_STRU *p_addr =  (TRANSFER_DEVADDR_STRU *)&addr;

    msg_type = TRANSFER_GET_MSGTYPE(p_recv_header->msgType);
    in_id = Update_Select_VD_Id(&p_update_infor->s_devInfor, p_addr);

    switch(msg_type){
        case  TRANSFER_TYPE_UPDATE:         /*升级*/
        {
            uint32_t offset = 0;
            Update_Transfer_Content_t *p_update_frame = (Update_Transfer_Content_t *)\
                                (p_frame->buf+sizeof(TRANSFER_FRAMEWORK_STRU));
            offset = LITTLE_ENDIAN_TO_HOST_32(p_update_frame->offset);
            if(offset == p_update_infor->fileOffset + p_sent_frame->realLen){
                Update_Recv_OneNode_Response(in_id, g_UPFrameInfor.recvd_node);
            }
            else if((offset == 0)&&(p_update_infor->fileOffset > 0)){
                 p_sent_frame->downStep = Download_Step_Check_Crc_Success;
                 dy_syslog(LOG_DEBUG,"bms file crc ok finished!\n");
            }
            else if(offset == 0xffffffff){
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[1]);
                p_sent_frame->downStep = Download_Step_Check_Crc_Failed;
                dy_syslog(LOG_ERR,"bms file crc error %u !  \n",p_update_infor->fileOffset);
            }
            else
            {
                dy_syslog(LOG_ERR,"offset  error  %u \n",p_update_infor->fileOffset);
            }
            break;
        }
        case  TRANSFER_TYPE_RECORD:         /*记录*/
            break;
        case  TRANSFER_TYPE_RWDB:           /*读写db*/
            break;
        case  TRANSFER_TYPE_DEBUG:           /*debug消息*/
        {
            //升级流程中的Debug(读版本号)消息，用于判断设备是否复位完成
            Update_Recv_OneNode_Response(in_id, g_UPFrameInfor.recvd_node_debug);
            break;
        }
        case  TRANSFER_TYPE_HMI_CONFIG:     /*HMI配置消息*/
            break;
        default:
            break;
    }
}



/*!
 * @brief       本设备固定在  BAU - BCU can
 *
 * @param[in]   p_pay_load
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-8-25     dfs      Create             \n
 *
 */
int32_t Update_Recv_XNCan_PayLoad(uint8_t *buf, uint32_t len, void *param, bool *isUpgrading)
{
    UPSP_Infor_Stru *p_update_infor = g_pUPSPInfor;
    UPSP_Send_Frame_Infor *p_sent_frame = &g_UPFrameInfor;

    Update_Exchange_XNCan_Load_t rec_frame = {0};

    if(p_update_infor == NULL){
        return Std_Ret_ERR;
    }
    *isUpgrading = p_update_infor->isUpdating;
    if(p_update_infor->isUpdating == Std_False){
        return Std_Ret_ERR;
    }

    Update_Translate_Msg(&rec_frame, (canrbus_xncan_header_t *)buf, len);

    ////<匹配任务是否为当前任务
    if(Std_False ==  Update_IS_XNCan_CanInfor_Match( &rec_frame, p_update_infor)){
        return Std_Ret_ERR;
    }

    if(Std_False ==  Update_IS_XNCan_Content_Match( &rec_frame, p_update_infor)){
        return Std_Ret_ERR;
    }

    /*根据当前的广播层级  查看数据是否接收完成*/
    Update_Parse_XNCan_PayLoad(&rec_frame, p_update_infor ,p_sent_frame);
    return Std_Ret_OK;
}

/*下发复位指令，仅用于升级流程*/
static void update_send_reset_begin()
{
    #define DEBUG_CMD_INDEX 5
    int len = 0;
    uint8_t buf[256]= "";
    UpdateSup_ReadResetCmd(buf + DEBUG_CMD_INDEX, ONCE_UP_FILE_SIZE, &len);
    packTransferFrame(TRANSFER_TYPE_DEBUG, buf, len);
    update_send_msg_to_mqtt(update_work_id_debug_msg,buf, len + TRANSFER_FRAMEWORK_LENGTH , NULL);
}

/*下发获取版本号指令，仅用于升级流程*/
static void update_send_show_version_begin()
{
    #define DEBUG_CMD_INDEX 5
    uint16_t len = 0;
    uint8_t buf[256]= "";
    uint8_t ver[]= "0x2080 ShowVersion";
    len = sizeof(ver);
    memcpy(buf + DEBUG_CMD_INDEX, ver, len);
    packTransferFrame(TRANSFER_TYPE_DEBUG, buf, len + sizeof(uint32_t));
    len += TRANSFER_FRAMEWORK_LENGTH + sizeof(uint32_t);
    update_send_msg_to_mqtt(update_work_id_debug_msg,  buf, len, NULL);
}

/*!
 * @brief      升级过程维护
               包括重传、文件读取偏移
               (10ms运行1次)
 * @param[in]   void
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-8-25     dfs      Create             \n
 * 2023-11-17    qzy      升级前增加复位流程+读取版本号判断目标就绪   \n
 */
void UpdateSup_Maintaince(void)
{
    #define UPSP_RUN_ONCE_TIME  2 /*运行一次时间*/
    #define FRAME_CONTENT_INDEX 9   /*HEAD 5 + OFFSET 4*/
    #define DEBUG_CMD_INDEX     5   /*发送命令的内容*/
    File_Op_Ret_Enum  Opret ;
    switch(g_UPFrameInfor.downStep)
    {
        case Download_Step_Send_Reset_Begin:
        {
            // 开始升级先下发复位指令
            update_send_reset_begin();
            g_UPFrameInfor.downStep = Download_Step_Send_Show_Version;
            sleep(RESET_BEGIAN_WAIT_TIME);
            g_UPFrameInfor.tryTimes = 0;
            break;
        }
        case Download_Step_Send_Show_Version:
        {
            //下发读版本号指令，来判断目标设备是否就绪
            g_UPFrameInfor.waitTime = 0;
            update_send_show_version_begin();
            g_UPFrameInfor.downStep = Download_Step_Check_Dev_Ready;
            break;
        }
        case Download_Step_Check_Dev_Ready:
        {
            //判断所有目标设备是否就绪
            if(Update_IS_All_Node_Recvd(g_pUPSPInfor, g_UPFrameInfor.recvd_node_debug) == Std_True)
            {
                g_UPFrameInfor.downStep = Download_Step_Read;
                g_UPFrameInfor.waitTime = 0;
            }
            g_UPFrameInfor.waitTime += UPSP_RUN_ONCE_TIME;
            //超时
            if(g_UPFrameInfor.waitTime > WAIT_RECV_VER_TIMEOUT)
            {
                g_UPFrameInfor.downStep =  Download_Step_Send_Show_Version;
                ++g_UPFrameInfor.tryTimes;
                if(g_UPFrameInfor.tryTimes > WAIT_SEND_VER_TRY_TIMES)
                {
                    g_UPFrameInfor.downStep =  Download_Step_Err;
                }
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[2]);
                dy_syslog(LOG_ERR, "Check_Dev_Ready timeout \n");
            }
            break;
        }
        case Download_Step_Read:
            Opret = UPFile_ReadFile(g_UPFrameInfor.frame + FRAME_CONTENT_INDEX, ONCE_UP_FILE_SIZE, &g_UPFrameInfor.realLen);
            if(Opret != File_Opr_Ok){
                //故障需要终止
                g_UPFrameInfor.downStep = Download_Step_Err;
                break;
            }
            {
                uint32_t offsettemp = HOST_TO_LITTLE_ENDIAN_32(g_pUPSPInfor->fileOffset);
                memcpy(&g_UPFrameInfor.frame[sizeof(TRANSFER_FRAMEWORK_STRU)], &offsettemp, sizeof(offsettemp));
            }
            if(packTransferFrame(TRANSFER_TYPE_UPDATE, g_UPFrameInfor.frame, g_UPFrameInfor.realLen + sizeof(uint32_t)) != Std_Ret_OK)
            {
                //出现故障
                g_UPFrameInfor.downStep = Download_Step_Err;
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[0]);
                break;
            }
            g_UPFrameInfor.fileCrc ^= CalculateXorCrc(g_UPFrameInfor.frame + FRAME_CONTENT_INDEX, g_UPFrameInfor.realLen);
            memset(g_UPFrameInfor.recvd_node, 0, sizeof(g_UPFrameInfor.recvd_node));
            g_UPFrameInfor.frameAck = Std_False;
            g_UPFrameInfor.processedAck = Std_False;
            g_UPFrameInfor.downStep = Download_Step_Send;
            g_UPFrameInfor.tryTimes = 0;
            break;
        case Download_Step_Send:
            g_UPFrameInfor.waitTime = 0;
            update_send_msg_to_mqtt(update_work_id_upgrade,g_UPFrameInfor.frame, \
                                    g_UPFrameInfor.realLen + TRANSFER_FRAMEWORK_LENGTH +sizeof(uint32_t), NULL);
            g_UPFrameInfor.downStep = Download_Step_Recvd_Ack;
            //dy_syslog(LOG_DEBUG,"send  offset = %u \n", g_pUPSPInfor->fileOffset);
            break;
        case Download_Step_Recvd_Ack:
            if(Update_IS_All_Node_Recvd( g_pUPSPInfor, g_UPFrameInfor.recvd_node) == Std_True)
            {
                g_UPFrameInfor.processedAck = Std_True;
                g_UPFrameInfor.downStep = Download_Step_Process_Ack;
                g_UPFrameInfor.waitTime = 0;
                //dy_syslog(LOG_DEBUG, "update percent = %%%u \n", 100 * g_pUPSPInfor->fileOffset / g_pUPSPInfor->fileSize);
            }
            g_UPFrameInfor.waitTime += UPSP_RUN_ONCE_TIME;
            if(g_UPFrameInfor.waitTime > WAIT_RECV_FRAM_TIMEOUT)
            {
                g_UPFrameInfor.downStep =  Download_Step_Send;
                ++g_UPFrameInfor.tryTimes;
                if(g_UPFrameInfor.tryTimes > WAIT_SEND_TRY_TIMES)
                {
                    g_UPFrameInfor.downStep =  Download_Step_Err;
                    g_pUPSPInfor->error_code |= (1<<OTA_Error_Retry_Err);
                }
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[2]);
                dy_syslog(LOG_ERR, "update wait recv timeout \n");
            }
            break;
        case Download_Step_Process_Ack:
            if(Std_True == g_UPFrameInfor.processedAck)
            {
                if((g_pUPSPInfor->fileOffset + g_UPFrameInfor.realLen) == g_pUPSPInfor->fileSize) {
                    g_UPFrameInfor.downStep = Download_Step_Send_Crc;
                }
                else  {
                    g_UPFrameInfor.downStep = Download_Step_Ok;
                }
                g_UPFrameInfor.waitTime = 0;
            }
            g_UPFrameInfor.waitTime += UPSP_RUN_ONCE_TIME;
            if(g_UPFrameInfor.waitTime > WAIT_PROCESSED_FRAM_TIMEOUT)
            {
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[2]);
                g_UPFrameInfor.downStep =  Download_Step_Err;
                g_pUPSPInfor->error_code |= (1<<OTA_Error_Retry_Err);
            }
            break;
        case Download_Step_Send_Crc:
            {
                uint32_t temp = 0xffffffff;
                /*此处累加因此后面再判断OK时直接为超出文件范围 升级成功*/
                g_pUPSPInfor->fileOffset +=  g_UPFrameInfor.realLen;
                memcpy(&g_UPFrameInfor.frame[sizeof(TRANSFER_FRAMEWORK_STRU)], &temp, 4);
                /*4Byte len  4Bytes crc*/
                g_UPFrameInfor.realLen = 8;
                temp = HOST_TO_LITTLE_ENDIAN_32(g_pUPSPInfor->fileSize);
                memcpy(&g_UPFrameInfor.frame[sizeof(TRANSFER_FRAMEWORK_STRU)+4], &temp, 4);
                temp = HOST_TO_LITTLE_ENDIAN_32(g_UPFrameInfor.fileCrc);
                memcpy(&g_UPFrameInfor.frame[sizeof(TRANSFER_FRAMEWORK_STRU)+8], &temp, 4);
                packTransferFrame(TRANSFER_TYPE_UPDATE, g_UPFrameInfor.frame, g_UPFrameInfor.realLen + 4);

                g_UPFrameInfor.frameAck = Std_False;
                g_UPFrameInfor.processedAck = Std_False;
                g_UPFrameInfor.downStep = Download_Step_Send;
                g_UPFrameInfor.tryTimes = 0;
            }
            break;
        case Download_Step_Err:
            {
                downloadFailed();
                g_UPFrameInfor.downStep =  Download_Step_Send_Reset_Begin;
            }
            break;
        case Download_Step_Ok:
            {
                g_pUPSPInfor->fileOffset +=  g_UPFrameInfor.realLen;
                /*判断升级是否结束*/
                if(g_pUPSPInfor->fileOffset >= g_pUPSPInfor->fileSize){
                    //g_UPFrameInfor.downStep =  Download_Step_Read_Reset;
                }
                else {
                    g_UPFrameInfor.downStep =  Download_Step_Read;
                }
            }
            break;
        case Download_Step_Check_Crc_Failed:
            {
                downloadFailed();
                g_UPFrameInfor.downStep =  Download_Step_Send_Reset_Begin;
            }
            break;
        case Download_Step_Check_Crc_Success:
            g_UPFrameInfor.downStep =  Download_Step_Read_Reset;
            break;
        case Download_Step_Read_Reset:
            UpdateSup_ReadResetCmd(g_UPFrameInfor.frame + DEBUG_CMD_INDEX, ONCE_UP_FILE_SIZE, &g_UPFrameInfor.realLen);
            packTransferFrame(TRANSFER_TYPE_DEBUG, g_UPFrameInfor.frame, g_UPFrameInfor.realLen);
            g_UPFrameInfor.waitTime = 0;
            g_UPFrameInfor.tryTimes = 0;
            g_UPFrameInfor.downStep = Download_Step_Send_Reset;
            break;
        case Download_Step_Send_Reset:{
                g_UPFrameInfor.waitTime += UPSP_RUN_ONCE_TIME;
                if(g_UPFrameInfor.waitTime > WAIT_RECV_FRAM_TIMEOUT)
                {
                    update_send_msg_to_mqtt(update_work_id_debug_msg,g_UPFrameInfor.frame, \
                                            g_UPFrameInfor.realLen + TRANSFER_FRAMEWORK_LENGTH , NULL);
                    g_UPFrameInfor.waitTime = 0;
                    ++g_UPFrameInfor.tryTimes;
                    if(g_UPFrameInfor.tryTimes > MAX_TRY_RESET_TIMES)
                    {
                        downloadSucceed();
                    }
                }
                break;
            }
        default:
            break;
    }

    if (Download_Step_Process_Ack == g_UPFrameInfor.downStep) {
        memset(&g_UPStatusInfo.status, 0, sizeof(g_UPStatusInfo.status));
        snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[3]);
        g_UPStatusInfo.percent = 100 * g_pUPSPInfor->fileOffset / g_pUPSPInfor->fileSize;
    }
}


/*!
 * @brief
 *
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-8-25     dfs      Create             \n
 *
 */
void update_start_new_otajob(OTA_Exchange_Stru *pOTAData)
{
    DEBUG_ASSERT((g_pUPSPInfor == NULL), "upsp insert err\r\n");
    // uint16_t dstLevel = pOTAData->dstLevel;
    uint32_t size = 0;

    if(g_pUPSPInfor->isUpdating == Std_True){
        return;
    }
    g_pUPSPInfor->error_code = 0;

    if(pOTAData->dstLevel < MAX_UPSP_FILE_LEVEL){
        if(File_Opr_Ok == UPFile_OpenFile((void *)pOTAData->fileName, &size)){
            if(UPFile_ISCRCCorrect(NULL) == Std_True)
            {
                update_init_new_download_job(pOTAData, size);
            }
            else{
                g_pUPSPInfor->error_code |= (1<<OTA_Error_FileCrc);
                dy_syslog(LOG_ERR, "file  crc err \n");
                memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
                snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[1]);
                exchange_with_mqtt_send_upgrade_status(g_UPStatusInfo.status, strlen(g_UPStatusInfo.status), g_UPStatusInfo.percent);
            }
        }
        else{
            g_pUPSPInfor->error_code |= (1<<OTA_Error_ReadFile);
            dy_syslog(LOG_ERR, "read file err \n");
            memset(&g_UPStatusInfo, 0, sizeof(g_UPStatusInfo));
            snprintf(g_UPStatusInfo.status, sizeof(g_UPStatusInfo.status), "%s", g_Upgrade_status[0]);
            exchange_with_mqtt_send_upgrade_status(g_UPStatusInfo.status, strlen(g_UPStatusInfo.status), g_UPStatusInfo.percent);
        }
    }
}

/*-----------------------------------------------------------------------------------------
 Discription:  终止当前升级
               复位操作
 Author:       DFS
 Date:         2019-08-27
 Param:        无
 Return:       无
 Modify:
*-----------------------------------------------------------------------------------------*/
void UpdateSup_AbortUpdating(void)
{
    g_pUPSPInfor->fileOffset = 0;
    g_pUPSPInfor->isUpdating = Std_False;
    return;
}


/*-----------------------------------------------------------------------------------------
 Discription:  升级维护实时运行模块
               1、获取目录树；
               2、获取升级文件；
               3、升级维护；
               4、复位读取版本；

               目前读取采取阻塞式，因此该runnable需要单独运行
 Author:       DFS
 Date:         2019-08-27
 Param:        无
 Return:       Std_Ret_Ok:成功
               Std_Ret_Err:失败
 Modify:
*-----------------------------------------------------------------------------------------*/
void UpdateSup_Runnable(void)
{
    DEBUG_ASSERT((g_pUPSPInfor == NULL), "upsp err\r\n");

    /*运行当前升级流程*/
    if(g_pUPSPInfor->isUpdating == Std_True)
    {
         UpdateSup_Maintaince();
         // TODO:对外update
         {
            if (Download_Step_Process_Ack == g_UPFrameInfor.downStep) {
                exchange_with_mqtt_send_upgrade_status(g_UPStatusInfo.status, strlen(g_UPStatusInfo.status), g_UPStatusInfo.percent);
            }
         }
        OS_Delay_MS(2);
    }
    else
    {
        OS_Delay_MS(100);
    }
    return ;
}


uint8_t file_path[]="SeMaster_Infor14-80-1-1.bin";
void update_revert_msg_to_xncan(canrbus_xncan_header_t *p_src, Update_Exchange_XNCan_Load_t *p_payload)
{
    if((NULL == p_src)||(NULL == p_payload)){
        return;
    }
    p_payload->bauId = p_src->msgFlowBauId;
    p_payload->bcuId = p_src->msgFlowBcuId;
    p_payload->bmuId = p_src->msgFlowBmuId;

    p_payload->buf = p_src->data;
    p_payload->cmdCode = p_src->func;
    p_payload->isHierMode = p_src->msgFlowUpdateType;
    p_payload->level = p_src->layer;
    p_payload->workId = p_src->msgFlowWorkId;
    return ;
}


void update_send_msg_to_mqtt(uint8_t work_id, uint8_t* buf, uint32_t len, void* param)
{
    uint8_t send_buf[MAX_CMD_LINE*2] = {0};
    canrbus_xncan_header_t *p_payload = (canrbus_xncan_header_t *)send_buf;
    OTA_Dev_CAN_Infor_t *p_dev = &g_pUPSPInfor->s_devInfor;

    p_payload->msgFlowBauId = p_dev->bauId;
    p_payload->msgFlowBcuId = p_dev->bcuId;
    p_payload->msgFlowBmuId = p_dev->bmuId;
    p_payload->func = CANRBUS_DEBUG;

    p_payload->msgFlowUpdateType = p_dev->isHierMode;
    p_payload->layer = p_dev->level;
    p_payload->msgFlowWorkId = work_id;
    memcpy(p_payload->data, buf, len);
    len += sizeof(canrbus_xncan_header_t);

    exchange_with_mqtt_send_package(send_buf, len, NULL);
}

void update_simulate_start_newjob(void)
{
    OTA_Exchange_Stru  OTAData = {0};
    OTAData.bauId = 1;
    OTAData.bcuId = 0;
    OTAData.bmuId = 0;
    OTAData.dstLevel = 3;
    memcpy(OTAData.fileName, file_path, sizeof(file_path));
    update_start_new_otajob(&OTAData);
}

Std_Ret_Type update_send_dev_reset(OTA_Exchange_Stru *pOTAData)
{
    if (NULL == pOTAData) {
        return Std_Ret_ERR;
    }

    if (g_pUPSPInfor->isUpdating == Std_True) {
        return Std_Ret_ERR;
    }

    g_pUPSPInfor->s_devInfor.isHierMode = Std_False;
    g_pUPSPInfor->s_devInfor.bmuId = pOTAData->bmuId;
    g_pUPSPInfor->s_devInfor.bcuId = pOTAData->bcuId;
    g_pUPSPInfor->s_devInfor.bauId = pOTAData->bauId;
    g_pUPSPInfor->s_devInfor.level = pOTAData->dstLevel;

    if (pOTAData->dstLevel == BMS_HW_LEVEL_1) {
        if (pOTAData->bmuId == CANRBUS_CANID_FLOW_BMUID_BRO) {
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_1_SLAVE;
        g_pUPSPInfor->destId = pOTAData->bmuId;
    }

    if (pOTAData->dstLevel == BMS_HW_LEVEL_2) {
        if(pOTAData->bcuId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_2_IBU;
        g_pUPSPInfor->destId = pOTAData->bcuId;
    }

    if (pOTAData->dstLevel == BMS_HW_LEVEL_3) {
        if(pOTAData->bauId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.bcuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_3_HUB;
        g_pUPSPInfor->destId = pOTAData->bauId;
    }

    UpdateSup_ReadResetCmd(g_UPFrameInfor.frame + DEBUG_CMD_INDEX, ONCE_UP_FILE_SIZE, &g_UPFrameInfor.realLen);
    packTransferFrame(TRANSFER_TYPE_DEBUG, g_UPFrameInfor.frame, g_UPFrameInfor.realLen);
    update_send_msg_to_mqtt(update_work_id_debug_msg, g_UPFrameInfor.frame, g_UPFrameInfor.realLen + TRANSFER_FRAMEWORK_LENGTH , NULL);

    return Std_Ret_OK;
}

void update_send_test_show_version(OTA_Exchange_Stru *pOTAData)
{
    #define DEBUG_CMD_INDEX 5
    uint16_t len = 0;
    uint8_t buf[256]= "";
    uint8_t ver[]= "0x2080 ShowVersion";
    len = sizeof(ver);

    //仅非升级时查询版本号
    if (g_pUPSPInfor->isUpdating == Std_True) {
        return;
    }

    g_pUPSPInfor->s_devInfor.isHierMode  = Std_False;
    g_pUPSPInfor->s_devInfor.bmuId = pOTAData->bmuId;
    g_pUPSPInfor->s_devInfor.bcuId = pOTAData->bcuId;
    g_pUPSPInfor->s_devInfor.bauId = pOTAData->bauId;
    g_pUPSPInfor->s_devInfor.level = pOTAData->dstLevel;

    if (pOTAData->dstLevel == BMS_HW_LEVEL_1) {
        if (pOTAData->bmuId == CANRBUS_CANID_FLOW_BMUID_BRO) {
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_1_SLAVE;
        g_pUPSPInfor->destId = pOTAData->bmuId;
    }

    if (pOTAData->dstLevel == BMS_HW_LEVEL_2) {
        if(pOTAData->bcuId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_2_IBU;
        g_pUPSPInfor->destId = pOTAData->bcuId;
    }

    if (pOTAData->dstLevel == BMS_HW_LEVEL_3) {
        if(pOTAData->bauId == CANRBUS_CANID_FLOW_BCUID_BRO){
            g_pUPSPInfor->s_devInfor.isHierMode = Std_True;
        }
        g_pUPSPInfor->s_devInfor.bmuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.bcuId = CANRBUS_CANID_FLOW_BMUID_INVALD;
        g_pUPSPInfor->s_devInfor.devType = BROADCAST_LEVEL_3_HUB;
        g_pUPSPInfor->destId = pOTAData->bauId;
    }

    memcpy(buf + DEBUG_CMD_INDEX, ver, len);
    packTransferFrame(TRANSFER_TYPE_DEBUG, buf, len + sizeof(uint32_t));
    len += TRANSFER_FRAMEWORK_LENGTH + sizeof(uint32_t);
    update_send_msg_to_mqtt(update_work_id_debug_msg,  buf, len, NULL);
}




