/*
 * @Author: qianziyang qianzy@bmser.com
 * @Date: 2024-01-26 16:15:44
 * @LastEditors: qianziyang qianzy@bmser.com
 * @LastEditTime: 2024-03-12 10:22:28
 * @FilePath: /rk3568_sdk_1018/bmser_app/libdb_control/src/tools/canrbus/bmser_canrbus.c
 * @Description: 流协议组解包
 */
#include "bmser_canrbus.h"
#include "bms_transfer_V50.h"
#include "bms_transfer.h"
#include "can_rbus.h"
#include "toolkit.h"
#include "bmser_dev.h"
#include "bmser_log.h"
#include "sqlite_api.h"
#include "bmser_error_code.h"

#define CAN_DATA_HEAD_LEN           5   // canrbus默认header长度
#define DEBUG_CMD_MAX_BUFF_SIZE    64   // debug指令最大长度

int32_t packTransferFrame_V41(CanrbusFlow_Infor_t *pCanrInfor, uint32_t in_len, uint8_t *in_frame, \
                                    uint32_t *out_len, uint8_t *out_frame);
int32_t packTransferFrame_V50(CanrbusFlow_Infor_t *pCanrInfor, uint32_t in_len, uint8_t *in_frame, \
                                    uint32_t *out_len, uint8_t *out_frame);

static int32_t packDebugStr_V41(CanrbusFlow_Infor_t *pCanrInfor, uint8_t dbg_cmd, void* buff, int32_t* realLen);
static int32_t packDebugStr_V50(CanrbusFlow_Infor_t *pCanrInfor, uint8_t dbg_cmd, void* buff, int32_t* realLen);

static int32_t isFlowContentMatch_V41(uint8_t *buf, uint16_t len);
static int32_t isFlowContentMatch_V50(uint8_t *buf, uint16_t len);

static uint8_t getCmdCode_V41(uint8_t *buf);
static uint8_t getCmdCode_V50(uint8_t *buf);

static uint8_t selectVDId_V41(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *buf);
static uint8_t selectVDId_V50(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *buf);

/*  默认版本
    bau V4.1
    bcu V4.1
    bmu V4.1
    bdu V5.0
*/
// 版本号实例
static CanrbusFlow_Ver_t* getCanrbusFlowVerInstance(void) 
{
    static CanrbusFlow_Ver_t ver_instance = 
    {
        CANRBUS_FLOW_VER_0x41,
        CANRBUS_FLOW_VER_0x41,
        CANRBUS_FLOW_VER_0x41,
        CANRBUS_FLOW_VER_0x50
     }; 
    return &ver_instance;
}

// 查询并配置安装参数表中配置的流协议版本
static int32_t queryAndSetDeviceVersion(char *dev_name, int *ver, char *log_msg)
{
    int ret = 0;
    sqlResult_t sqlResult = {0};

    ret = sqliteApi_query_custom(CANRBUSFLOW_VER_TABLE, CANRBUSFLOW_VERSION_KEY, \
                                CANRBUSFLOW_DEVNAME_KEY, dev_name, INTEGER, &sqlResult);
    if (ret != 0) {
        dy_syslog(LOG_ERR, "Failed to query %s version from database.\n", log_msg);
    } else {
        if(sqlResult.integer >= CANRBUS_FLOW_VER_0x41 && sqlResult.integer < CANRBUS_FLOW_VER_BUTT) {
            *ver = sqlResult.integer;
        } else {
            dy_syslog(LOG_ERR, "%s ver from table is illeagl, ver = %d.\n", log_msg, sqlResult.integer);
        }
    }

    return ret;
}

/*!
 * @brief       canrbus消息流初始化，确定canrbus消息流版本
 *
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-02-05     qzy      Create             \n
 */
int32_t CanrbusFlowInit(void)
{
    int ret = 0;
    CanrbusFlow_Ver_t* pCanrVer = getCanrbusFlowVerInstance(); // 获取版本号实例指针

    if (pCanrVer == NULL) {
        dy_syslog(LOG_ERR, "Failed to get CanrbusFlow version instance.\n");
        return -1;
    }

    // 查询并设置版本号, 没查询到则使用默认值
    ret |= queryAndSetDeviceVersion(CANRBUSFLOW_DEVNAME_VAL_BAU, &pCanrVer->bau_ver, "BAU");
    ret |= queryAndSetDeviceVersion(CANRBUSFLOW_DEVNAME_VAL_BCU, &pCanrVer->bcu_ver, "BCU");
    ret |= queryAndSetDeviceVersion(CANRBUSFLOW_DEVNAME_VAL_BMU, &pCanrVer->bmu_ver, "BMU");
    ret |= queryAndSetDeviceVersion(CANRBUSFLOW_DEVNAME_VAL_BDU, &pCanrVer->bdu_ver, "BDU");

    dy_syslog(LOG_DEBUG, "lib: bau_ver:%d, bcu_ver:%d, bmu_ver:%d, bdu_ver:%d\n",pCanrVer->bau_ver, \
    pCanrVer->bcu_ver,pCanrVer->bmu_ver,pCanrVer->bdu_ver);

    return ret;
}

/*根据设备层级获取canrbus流协议版本*/
static int32_t CanrbusFlowGetVerByLevel(uint8_t devlevel)
{
    int32_t canrbusVer = 0;
    CanrbusFlow_Ver_t* pCanrVer = getCanrbusFlowVerInstance();
    if (pCanrVer == NULL) {
        dy_syslog(LOG_ERR, "Failed to get CanrbusFlow version instance.\n");
        return -1;
    }
    if(devlevel == BMS_HW_LEVEL_1) {
        canrbusVer = pCanrVer->bmu_ver;
    } else if(devlevel == BMS_HW_LEVEL_2) {
        canrbusVer = pCanrVer->bcu_ver;
    } else if(devlevel == BMS_HW_LEVEL_3) {
        canrbusVer = pCanrVer->bau_ver;
        // todo: bdu
    } else {
        // 取默认版本4.1
        canrbusVer = CANRBUS_FLOW_VER_0x41;
    }
    return canrbusVer;
}

/*!
 * @brief       按照canrbus 流协议打包
 *
 * @param[in]      CanrbusFlow_Infor_t *pCanrInfor
 * @param[in]      uint32_t in_len     有效数据体长度
 * @param[in]      uint8_t *in_data    有效数据体buf
 * @param[out]     uint32_t out_len    组装完成的buf长度
 * @param[out]     uint8_t *out_data   组装完成的buf
 * 
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-29     qzy      Create             \n
 * 2024-02-19     qzy      入参出参修改         \n
 */
int32_t CanrbusFlowPackData(CanrbusFlow_Infor_t *pCanrInfor, uint32_t in_len, uint8_t *in_data,\
                                    uint32_t *out_len, uint8_t *out_data)
{
    if (pCanrInfor == NULL || in_data == NULL || out_len == NULL || out_data == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }
    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(pCanrInfor->devlevel);
    // 根据版本选择打包函数
    if (canrbusVer == CANRBUS_FLOW_VER_0x41) {
        packTransferFrame_V41(pCanrInfor, in_len, in_data, out_len, out_data);
    } else if (canrbusVer == CANRBUS_FLOW_VER_0x50) {
        packTransferFrame_V50(pCanrInfor, in_len, in_data, out_len, out_data);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowPackCanrbusFrame, canrbusVer err.\n");
        return -1;
    }

    return 0;
}

/*!
 * @brief       组装Debug指令字符串(事务3 debug指令)
 *
 * @param[in]   CanrbusFlow_Infor_t *p_upinfor
 * @param[in]   uint8_t dbg_cmd       debug指令类型
 * @param[out]  void    *buff         命令字符串buf
 * @param[out]  int32_t *realLen      命令字符串长度
 * @return      Std_True
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-09     qzy      Create             \n
 */
int32_t CanrbusFlowPackDebugCmdStr(CanrbusFlow_Infor_t *pCanrInfor, uint8_t dbg_cmd, void* buff, int32_t* realLen)
{
    if (pCanrInfor == NULL || buff == NULL || realLen == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }

    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(pCanrInfor->devlevel);
    if(CANRBUS_FLOW_VER_0x41 == canrbusVer) {
        packDebugStr_V41(pCanrInfor, dbg_cmd, buff, realLen);
    } else if(CANRBUS_FLOW_VER_0x50 == canrbusVer) {
        packDebugStr_V50(pCanrInfor, dbg_cmd, buff, realLen);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowPackDebugCmdStr, canrbusVer err.\n");
    }
    return 0;
}

/*!
 * @brief       检查响应包是否合法(升级)
 *
 * @param[in]   uint8_t  devlevel   设备层级(根据层级确定协议版本)
 * @param[in]   uint8_t  *buf       响应包
 * @param[in]   uint16_t  len       响应包长度
 * @return      true: match ; false: not match
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-09     qzy      Create             \n
 */
int32_t CanrbusFlowIsFlowContentMatch(uint8_t devlevel, uint8_t *buf, uint16_t len)
{
    if (buf == NULL || len == 0) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }

    int32_t isMatch = 0;
    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(devlevel);
    if(CANRBUS_FLOW_VER_0x41 == canrbusVer) {
        isMatch = isFlowContentMatch_V41(buf, len);
    } else if(CANRBUS_FLOW_VER_0x50 == canrbusVer) {
        isMatch = isFlowContentMatch_V50(buf, len);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowIsFlowContentMatch, canrbusVer err.\n");
    }
    return isMatch;
}

/*!
 * @brief       获取功能码
 *
 * @param[in]   uint8_t devlevel    设备层级
 * @param[in]   uint8_t *buf        数据包
 * @return      cmd_code            功能码
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
uint8_t CanrbusFlowGetCmdCode(uint8_t devlevel, uint8_t *buf)
{
    if (buf == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }

    uint8_t cmdCode = 0;
    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(devlevel);
    if(CANRBUS_FLOW_VER_0x41 == canrbusVer) {
        cmdCode = getCmdCode_V41(buf);
    } else if(CANRBUS_FLOW_VER_0x50 == canrbusVer) {
        cmdCode = getCmdCode_V50(buf);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowGetCmdCode, canrbusVer err.\n");
    }
    return cmdCode;
}

/*!
 * @brief       获取设备level_id
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @param[in]   uint8_t *buf                  数据包
 * @return      Select_VD_Id                  level_id
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
uint8_t CanrbusFlowSelectVDId(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *buf)
{
    if (pCanrInfor == NULL || buf == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }
    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(pCanrInfor->devlevel);
    uint8_t id = 0;
    if(CANRBUS_FLOW_VER_0x41 == canrbusVer) {
        id = selectVDId_V41(pCanrInfor, buf);
    } else if(CANRBUS_FLOW_VER_0x50 == canrbusVer) {
        id = selectVDId_V50(pCanrInfor, buf);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowSelectVDId, canrbusVer err.\n");
    }
    return id;
}

/*!
 * @brief       获取传输框架长度(不包含CRC)
 *
 * @param[in]   uint8_t devlevel          设备层级
 * @return      length
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-29     qzy      Create             \n
 */
uint8_t CanrbusFlowGetHeaderLen(uint8_t devlevel)
{
    uint8_t length = CAN_DATA_HEAD_LEN;        //默认为canrbus V41协议头长度
    uint8_t canrbusVer = CanrbusFlowGetVerByLevel(devlevel);
    if(CANRBUS_FLOW_VER_0x41 == canrbusVer) {
        length = sizeof(TRANSFER_FRAMEWORK_STRU);
    } else if(CANRBUS_FLOW_VER_0x50 == canrbusVer) {
        length = sizeof(TRANSFER_FRAMEWORK_STRU_V50);
    } else {
        dy_syslog(LOG_ERR, "CanrbusFlowGetHeaderLen, canrbusVer err.\n");
    }
    return length;
}

/******************************************** CANRBUS V41 *************************************************/
/*!
 * @brief       计算地址信息(V41)
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @return
 * @retval      addr
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-26     qzy      Create             \n
 */
static uint16_t calAddr_V41(CanrbusFlow_Infor_t *pCanrInfor)
{
    uint16_t addr = 0;
    TRANSFER_DEVADDR_STRU *devAddr = (TRANSFER_DEVADDR_STRU *)&addr;
    TRANSFER_DEVADDR_BRO_STRU *broAddr = (TRANSFER_DEVADDR_BRO_STRU *)&addr;

    if(pCanrInfor->isHierMode == false){
        devAddr->bro = 0;
        devAddr->level3 = pCanrInfor->bauId;
        devAddr->level2 = pCanrInfor->bcuId;
        devAddr->level1 = pCanrInfor->bmuId;
    }
    else{
        broAddr->bro = 1;
        broAddr->broBAU = pCanrInfor->bauId;
        broAddr->broBCU = pCanrInfor->bcuId;
        broAddr->broLevel = pCanrInfor->devlevel;
        broAddr->broType = pCanrInfor->devType;
    }
    return addr;
}

/*!
 * @brief       解析addr信息(V41)
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @return
 * @retval      addr
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-11-05     tk      Create             \n
 */
static uint16_t ParseAddr_V41(uint16_t addr, CanrbusFlow_Infor_t *pCanrInfor)
{
    TRANSFER_DEVADDR_STRU *devAddr = (TRANSFER_DEVADDR_STRU *)&addr;
    TRANSFER_DEVADDR_BRO_STRU *broAddr = (TRANSFER_DEVADDR_BRO_STRU *)&addr;

    if ((addr & 0x8000) == 0) {
        pCanrInfor->bauId = devAddr->level3;
        pCanrInfor->bcuId = devAddr->level2;
        pCanrInfor->bmuId = devAddr->level1;
    } else {
        pCanrInfor->bauId = broAddr->broBAU;
        pCanrInfor->bcuId = broAddr->broBCU;
        pCanrInfor->devlevel = broAddr->broLevel;
        switch(pCanrInfor->devlevel) {
            case BMS_HW_LEVEL_1: {    //层级1: bmu
                pCanrInfor->bmuId = HWID_LEVEL_1_MASK;
            } break;
            case BMS_HW_LEVEL_2:    //层级2: bcu
            case BMS_HW_LEVEL_3: {   //层级3: bau
                pCanrInfor->bmuId = 0;  //BMU为无效层级(0x00)
            } break;
            default:
                break;
        }
        pCanrInfor->devType = broAddr->broType;
    }

    return 0;
}

/*!
 * @brief     计算当前的消息类型(V41)
 * @param[in]   p_upinfor
 * @param[in]   type
 * @return
 * @retval      msg_type
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-26     qzy      Create             \n
 */
static uint8_t calMsgType_V41(CanrbusFlow_Infor_t *pCanrInfor)
{
    uint8_t msg_type;
    TRANSFER_MSG_TYPE_STRU *pMsgType = (TRANSFER_MSG_TYPE_STRU *)&msg_type;
    pMsgType->isCorretResp = 1;
    pMsgType->isHier = (pCanrInfor->isHierMode > 0)?1:0;
    pMsgType->isResp = 0;
    pMsgType->isTunnel = 1;
    pMsgType->cmdType = pCanrInfor->cmdCode & TRANSFER_TYPE_CMDTYPE_MASK;
    return msg_type;
}

/*!
 * @brief     解析当前的消息类型(V41)
 * @param[in]   p_upinfor
 * @param[in]   type
 * @return
 * @retval      msg_type
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-11-05     tk      Create             \n
 */
static int ParseMsgType_V41(uint8_t msg_type, CanrbusFlow_Infor_t *pCanrInfor)
{
    TRANSFER_MSG_TYPE_STRU *pMsgType = (TRANSFER_MSG_TYPE_STRU *)&msg_type;
    pCanrInfor->isHierMode = (pMsgType->isHier > 0) ? 1 : 0;
    pCanrInfor->cmdCode = pMsgType->cmdType & TRANSFER_TYPE_CMDTYPE_MASK;

    return 0;
}

/*!
 * @brief       按照canrbus V41协议打包binary_flow mqtt
 * @param[in]      CanrbusFlow_Infor_t *pCanrInfor
 * @param[in]      uint32_t data_len    有效数据体长度
 * @param[in]      uint8_t *data_frame  有效数据体buf
 * @param[out]     uint32_t out_len     组装完成的buf长度
 * @param[out]     uint8_t *out_frame   组装完成的buf
 * @return
 * @retval      0
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-26     qzy      Create             \n
 */
int32_t packTransferFrame_V41(CanrbusFlow_Infor_t *pCanrInfor, uint32_t in_len, uint8_t *in_frame, \
                                    uint32_t *out_len, uint8_t *out_frame)
{
    if (pCanrInfor == NULL || in_frame == NULL || out_len == NULL || out_frame == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }
    uint16_t crc, addr;
    memcpy(out_frame + sizeof(TRANSFER_FRAMEWORK_STRU), in_frame, in_len);
    TRANSFER_FRAMEWORK_STRU *pHeader = (TRANSFER_FRAMEWORK_STRU *)out_frame;
    pHeader->version = TRANSFER_PROTOCOL_VERSION;
    pHeader->destDevAddr = 0x0000;
    addr = calAddr_V41(pCanrInfor);
    pHeader->destDevAddr = HOST_TO_LITTLE_ENDIAN_16(addr);
    pHeader->msgType = calMsgType_V41(pCanrInfor);

    pHeader->msgLength = in_len;
    crc = BmsMsg_Crc16(out_frame, in_len + sizeof(TRANSFER_FRAMEWORK_STRU));
    crc = HOST_TO_LITTLE_ENDIAN_16(crc);
    memcpy(&out_frame[sizeof(TRANSFER_FRAMEWORK_STRU)+in_len], &crc, sizeof(crc));
    *out_len = in_len + sizeof(TRANSFER_FRAMEWORK_STRU) + sizeof(crc);
    return 0;
}

static int32_t packDebugStr_V41(CanrbusFlow_Infor_t *pCanrInfor, uint8_t dbg_cmd, void* buff, int32_t* realLen)
{
    uint16_t dev_addr = calAddr_V41(pCanrInfor);

    switch (dbg_cmd) {
        case DEBUG_CMD_RESET:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x reset", dev_addr);
            break;
        case DEBUG_CMD_SHOWVERSION:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x ShowVersion", dev_addr);
            break;
        case DEBUG_CMD_STARTPRG:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x StartPrg", dev_addr);
            break;
        case DEBUG_CMD_ENDPRG:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x EndPrg", dev_addr);
            break;
        case DEBUG_CMD_CANRBUSVERSION:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x CANRBUSVersion", dev_addr);
            break;
        default:
            *realLen = 0;
            break;
    }
    return 0;
}

/*!
 * @brief       检查升级响应包是否match(V41)
 *
 * @param[in]   uint8_t  *buf       响应包
 * @param[in]   uint16_t  len       响应包长度
 * @return      1: match ; 0: not match
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-09     qzy      Create             \n
 */
static int32_t isFlowContentMatch_V41(uint8_t *buf, uint16_t len)
{
    uint8_t msg_type = 0;
    int32_t is_match = 0;

    do{
        TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)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 (len < 2)
            break;
        /*发送的长度中没有包含 CRC长度*/
        crc = BmsMsg_Crc16(buf, len);
        if(crc != 0){
            break;
        }
        {
            /*回复的消息应为单播*/
            TRANSFER_DEVADDR_BRO_STRU *pBroLevel =  (TRANSFER_DEVADDR_BRO_STRU *)&addr;
            if(pBroLevel->bro > 0)
                break;
        }
        is_match = 1;
    }while(0);
    return is_match;
}

/*!
 * @brief       获取功能码(V41)
 *
 * @param[in]   uint8_t *buf  数据包
 * @return      cmd_code    功能码
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
static uint8_t getCmdCode_V41(uint8_t *buf)
{
    uint8_t msg_type = 0;
    TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)buf;
    msg_type = TRANSFER_GET_MSGTYPE(p_recv_header->msgType);
    return msg_type;
}

/*!
 * @brief       获取设备level_id(V41)
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @param[in]   uint8_t *buf                  数据包
 * @return      Select_VD_Id                  level_id
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
static uint8_t selectVDId_V41(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *buf)
{
    uint8_t select_valid_id = 0;
    uint8_t bmu_id = 0, bcu_id = 0, bau_id = 0;
    TRANSFER_FRAMEWORK_STRU *p_recv_header = (TRANSFER_FRAMEWORK_STRU *)buf;
    uint16_t addr = LITTLE_ENDIAN_TO_HOST_16(p_recv_header->destDevAddr);
    TRANSFER_DEVADDR_STRU *p_addr =  (TRANSFER_DEVADDR_STRU *)&addr;
    bau_id = p_addr->level3;
    bcu_id = p_addr->level2;
    bmu_id = p_addr->level1;
    if(pCanrInfor->isHierMode){
        if((pCanrInfor->devlevel == BMS_HW_LEVEL_1) || (pCanrInfor->devlevel == BMS_HW_LEVEL_2)){
            select_valid_id = bcu_id;
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    else{
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_1){
            select_valid_id = bmu_id;
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_2){
            select_valid_id = bcu_id;
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    return select_valid_id;
}

/******************************************** CANRBUS V41 *************************************************/


/******************************************** CANRBUS V50 *************************************************/
/*!
 * @brief       计算目的地址信息(V50)
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @return      uint32_t addr   目的地址
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-01-26     qzy      Create             \n
 */
static uint32_t calAddr_V50(CanrbusFlow_Infor_t *pCanrInfor)
{
    uint32_t addr = 0;
    TRANSFER_DEVADDR_STRU_V50 *dstAddr = (TRANSFER_DEVADDR_STRU_V50 *)&addr;
    dstAddr->res = 0x00;                         //预留
    dstAddr->level3_id = pCanrInfor->bauId;      //BAU仅支持定向，固定为bauid

    switch(pCanrInfor->devlevel)
    {
        case BMS_HW_LEVEL_1:    //层级1: bmu
        {
            dstAddr->level2_id = pCanrInfor->bcuId;  //a:升级某一簇的从控(簇ID); b:升级所有簇的从控(0xFF)
            if(pCanrInfor->isHierMode == Std_False){
                dstAddr->level1_id = pCanrInfor->bmuId;      //定向(暂不支持)
            } else {
                dstAddr->level1_id = TRANSFER_V50_LEVEL_BRO;//广播(0xFF)
            }
            break;
        }
        case BMS_HW_LEVEL_2:    //层级2: bcu
        {
            dstAddr->level1_id = TRANSFER_V50_LEVEL_INVALD;  //BMU为无效层级(0x00)
            if(pCanrInfor->isHierMode == Std_False){
                dstAddr->level2_id = pCanrInfor->bcuId;      //定向
            } else {
                dstAddr->level2_id = TRANSFER_V50_LEVEL_BRO;//广播(0xFF)
            }
            break;
        }
        case BMS_HW_LEVEL_3:    //层级3: bau
        {
            //level3_id固定为bauId，bcu、bmu层级置为无效
            dstAddr->level1_id = TRANSFER_V50_LEVEL_INVALD;
            dstAddr->level2_id = TRANSFER_V50_LEVEL_INVALD;
            break;
        }
        default:
            break;
    }
    return addr;
}

/*!
 * @brief       解析addr信息(V50)
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @return      uint32_t addr   目的地址
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2024-11-05     tk      Create             \n
 */
static uint32_t ParseAddr_V50(uint32_t addr, CanrbusFlow_Infor_t *pCanrInfor)
{
    TRANSFER_DEVADDR_STRU_V50 *srcAddr = (TRANSFER_DEVADDR_STRU_V50 *)&addr;
    pCanrInfor->bauId = srcAddr->level3_id;      //BAU仅支持定向，固定为bauid

    switch(pCanrInfor->devlevel)
    {
        case BMS_HW_LEVEL_1:    //层级1: bmu
        {
            pCanrInfor->bcuId = srcAddr->level2_id;   //a:升级某一簇的从控(簇ID); b:升级所有簇的从控(0xFF)
            if(pCanrInfor->isHierMode == Std_False) {
                pCanrInfor->bmuId = srcAddr->level1_id;
            } else {
                pCanrInfor->bmuId = TRANSFER_V50_LEVEL_BRO;//广播(0xFF)
            }
            break;
        }
        case BMS_HW_LEVEL_2:    //层级2: bcu
        {
            pCanrInfor->bmuId = TRANSFER_V50_LEVEL_INVALD;  //BMU为无效层级(0x00)
            if (pCanrInfor->isHierMode == Std_False) {
                pCanrInfor->bcuId = srcAddr->level2_id;     //定向
            } else {
                pCanrInfor->bcuId = TRANSFER_V50_LEVEL_BRO; //广播(0xFF)
            }
            break;
        }
        case BMS_HW_LEVEL_3:    //层级3: bau
        {
            //level3_id固定为bauId，bcu、bmu层级置为无效
            pCanrInfor->bmuId = TRANSFER_V50_LEVEL_INVALD;
            pCanrInfor->bcuId = TRANSFER_V50_LEVEL_INVALD;
            break;
        }
        default:
            break;
    }
    return 0;
}

/*!
 * @brief     计算数据帧操作方式(V50)
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @return      uint8_t frame_type   数据帧操作方式
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-08     qzy      Create             \n
 *
 */
static uint8_t calFrameType_V50(uint8_t isHierMode)
{
    uint8_t frame_type;
    TRANSFER_FRAME_TYPE_STRU_V50 *pFrameType = (TRANSFER_FRAME_TYPE_STRU_V50 *)&frame_type;
    pFrameType->isBro = (isHierMode > 0 )?1:0;
    pFrameType->isCorretResp = 0;
    pFrameType->isHier = isHierMode;
    pFrameType->isResp = 0;
    pFrameType->res = 0;
    return frame_type;
}

static uint8_t calDevType_V50(uint8_t level)
{
    uint32_t devType = 0;
    switch(level)
    {
        case BMS_HW_LEVEL_1:    //层级1: bmu
        {
            devType = TRANSFER_DEV_BMU_V50;
            break;
        }
        case BMS_HW_LEVEL_2:    //层级2: bcu
        {
            devType = TRANSFER_DEV_BCU_V50;
            break;
        }
        case BMS_HW_LEVEL_3:    //层级3: bau
        {
            devType = TRANSFER_DEV_BAU_V50;
            break;
        }
        default:
            break;
    }
    return devType;
}

static uint8_t calLevel_V50(uint8_t devType)
{
    uint8_t level = 0;
    switch(devType)
    {
        case TRANSFER_DEV_BMU_V50:    //层级1: bmu
        {
            level = BMS_HW_LEVEL_1;
            break;
        }
        case TRANSFER_DEV_BCU_V50:    //层级2: bcu
        {
            level = BMS_HW_LEVEL_2;
            break;
        }
        case TRANSFER_DEV_BAU_V50:    //层级3: bau
        {
            level = BMS_HW_LEVEL_3;
            break;
        }
        default:
            break;
    }

    return level;
}

/*!
 * @brief       按照canrbus 5.0协议打包
 *
 * @param[in]   UPSP_Infor_Stru *pUPSPInfor
 * @param[in]   uint32_t msgType     命令码(cmd_code)
 * @param[out]  uint8_t *frame       组装完成的buf
 * @param[in]   uint32_t len         有效数据长度
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-08     qzy      Create             \n
 */
int32_t packTransferFrame_V50(CanrbusFlow_Infor_t *pCanrInfor, uint32_t in_len, uint8_t *in_frame, \
                                    uint32_t *out_len, uint8_t *out_frame)
{
    if (pCanrInfor == NULL || in_frame == NULL || out_len == NULL || out_frame == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }
    uint16_t crc;
    uint32_t addr;
    memcpy(out_frame + sizeof(TRANSFER_FRAMEWORK_STRU_V50), in_frame, in_len);
    TRANSFER_FRAMEWORK_STRU_V50 *pHeader = (TRANSFER_FRAMEWORK_STRU_V50 *)out_frame;
    pHeader->header = CANRBUS_FLOW_HEADER_V50;                            //起始帧数据(0xD1)
    pHeader->ver = TRANSFER_VERSION_V50;                                  //版本号(0x50)
    pHeader->dev = calDevType_V50(pCanrInfor->devlevel);                  //设备类型
    pHeader->src_id = 0x0000;                                             //源地址(预留,0x00)
    addr =  calAddr_V50(pCanrInfor);                                      //目的地址
    pHeader->dst_id = HOST_TO_LITTLE_ENDIAN_16(addr);
    pHeader->frame_type = calFrameType_V50(pCanrInfor->isHierMode);
    pHeader->cmd_code = pCanrInfor->cmdCode;
    pHeader->reserve = 0x00;
    pHeader->data_len = in_len;

    crc = BmsMsg_Crc16(out_frame, in_len + sizeof(TRANSFER_FRAMEWORK_STRU_V50));
    crc = HOST_TO_LITTLE_ENDIAN_16(crc);
    memcpy(&out_frame[sizeof(TRANSFER_FRAMEWORK_STRU_V50)+in_len], &crc, sizeof(crc));
    *out_len = in_len + sizeof(TRANSFER_FRAMEWORK_STRU_V50) + sizeof(crc);

    return 0;
}

int32_t ParsepackTransferFrame_V41(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *in_frame) {
    if (pCanrInfor == NULL || in_frame == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }

    TRANSFER_FRAMEWORK_STRU *pHeader = (TRANSFER_FRAMEWORK_STRU *)in_frame;
    uint16_t addr = 0;
    ParseMsgType_V41(pHeader->msgType, pCanrInfor);
    addr = LITTLE_ENDIAN_TO_HOST_16(pHeader->destDevAddr);
    ParseAddr_V41(addr, pCanrInfor);

    return 0;
}

int32_t ParsepackTransferFrame_V50(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *in_frame) {
    if (pCanrInfor == NULL || in_frame == NULL) {
        dy_syslog(LOG_ERR, "Invalid input param.\n");
        return -1;
    }

    TRANSFER_FRAMEWORK_STRU_V50 *pHeader = (TRANSFER_FRAMEWORK_STRU_V50 *)in_frame;
    uint32_t addr = 0;
    TRANSFER_FRAME_TYPE_STRU_V50 *pFrameType = (TRANSFER_FRAME_TYPE_STRU_V50 *)&pHeader->frame_type;
    pCanrInfor->devlevel = calLevel_V50(pHeader->dev);
    pCanrInfor->cmdCode = pHeader->cmd_code;
    pCanrInfor->isHierMode = pFrameType->isHier;
    addr = LITTLE_ENDIAN_TO_HOST_16(pHeader->src_id);
    ParseAddr_V50(addr, pCanrInfor);

    return 0;
}

static int32_t packDebugStr_V50(CanrbusFlow_Infor_t *pCanrInfor, uint8_t dbg_cmd, void* buff, int32_t* realLen)
{
    uint16_t dev_addr = (uint16_t)calAddr_V50(pCanrInfor);
    switch (dbg_cmd) {
        case DEBUG_CMD_RESET:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x reset", dev_addr);
            break;
        case DEBUG_CMD_SHOWVERSION:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x ShowVersion", dev_addr);
            break;
        case DEBUG_CMD_STARTPRG:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x StartPrg", dev_addr);
            break;
        case DEBUG_CMD_ENDPRG:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x EndPrg", dev_addr);
            break;
        case DEBUG_CMD_CANRBUSVERSION:
            *realLen = snprintf(buff, DEBUG_CMD_MAX_BUFF_SIZE, "0x%x CANRBUSVersion", dev_addr);
            break;
        default:
            *realLen = 0;
            break;
    }
    return 0;
}

/*!
 * @brief       检查升级响应包是否match(V50)
 *
 * @param[in]   uint8_t  *buf       响应包
 * @param[in]   uint16_t  len       响应包长度
 * @return      1: match ; 0: not match
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-08-09     qzy      Create             \n
 */
static int32_t isFlowContentMatch_V50(uint8_t *buf, uint16_t len)
{
    uint8_t frame_type = 0;
    int32_t is_match = 0;

    do{
        TRANSFER_FRAMEWORK_STRU_V50 *p_recv_header = (TRANSFER_FRAMEWORK_STRU_V50 *)buf;
        uint16_t crc = 0;
        if(p_recv_header->header != CANRBUS_FLOW_HEADER_V50){
            break;
        }
        frame_type = p_recv_header->frame_type;
        if(TRANSFER_V50_IS_CORRECT_RESP(frame_type) == 0){
            break;
        }
        if (len < 2)
            break;
        /*发送的长度中没有包含 CRC长度*/
        crc = BmsMsg_Crc16(buf, len);
        if(crc != 0){
            break;
        }
        {
            /*回复的消息中应为单播*/
            TRANSFER_FRAME_TYPE_STRU_V50 *pBroLevel =  (TRANSFER_FRAME_TYPE_STRU_V50 *)&frame_type;
            if(pBroLevel->isBro > 0)
                break;
        }

        is_match = 1;
    }while(0);
    return is_match;
}

/*!
 * @brief       获取功能码(V50)
 *
 * @param[in]   uint8_t *buf  数据包
 * @return      cmd_code    功能码
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
static uint8_t getCmdCode_V50(uint8_t *buf)
{
    uint8_t cmd_code = 0;
    TRANSFER_FRAMEWORK_STRU_V50 *p_recv_header = (TRANSFER_FRAMEWORK_STRU_V50 *)buf;
    cmd_code = p_recv_header->cmd_code;
    return cmd_code;
}

/*!
 * @brief       根据设备层级获取有效设备id(v50)
 *
 * @param[in]   CanrbusFlow_Infor_t *pCanrInfor
 * @param[in]   uint8_t *buf                  数据包
 * @return      Select_VD_Id                  level_id
 * @retval      uint8_t
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2023-10-24     qzy      Create             \n
 */
static uint8_t selectVDId_V50(CanrbusFlow_Infor_t *pCanrInfor, uint8_t *buf)
{
    uint8_t select_valid_id = 0;
    uint8_t bmu_id = 0, bcu_id = 0, bau_id = 0;
    TRANSFER_FRAMEWORK_STRU_V50 *p_recv_header = (TRANSFER_FRAMEWORK_STRU_V50 *)buf;
    uint32_t addr = LITTLE_ENDIAN_TO_HOST_32(p_recv_header->dst_id);
    TRANSFER_DEVADDR_STRU_V50 *p_addr =  (TRANSFER_DEVADDR_STRU_V50 *)&addr;
    bau_id = p_addr->level3_id;
    bcu_id = p_addr->level2_id;
    bmu_id = p_addr->level1_id;
    if(pCanrInfor->isHierMode){
        if((pCanrInfor->devlevel == BMS_HW_LEVEL_1) || (pCanrInfor->devlevel == BMS_HW_LEVEL_2)){
            select_valid_id = bcu_id;
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    else{
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_1){
            select_valid_id = bmu_id;
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_2){
            select_valid_id = bcu_id; 
        }
        if(pCanrInfor->devlevel == BMS_HW_LEVEL_3){
            select_valid_id = bau_id;
        }
    }
    return select_valid_id;
}
/******************************************** CANRBUS V50 *************************************************/