#ifndef BMS_TRANSFER_DATA_H__
#define BMS_TRANSFER_DATA_H__
#include "platmacro.h"
#include <stdint.h>
#include "define_base.h"
#include "can_rbus.h"

typedef int32_t (*NET_MSG_SEND_FUNC)(ComIf_Handle_Type handleId, Std_Buf_Type *pMsg, Std_Size_Type len);

typedef enum  /*组包协议框架的说明*/
{
    TRANS_VERSION = 0,  /*byte0: 组包框架版本号*/
    TRANS_DEST_DEV_LB,   /*byte1: 消息目的设备地址低字节*/
    TRANS_DEST_DEV_HB,   /*byte2: 消息目的设备地址高字节*/
    TRANS_MSG_TYPE,      /*byte3: 消息类型*/
    TRANS_MSG_LENGTH,    /*byte4: 消息长度*/
    TRANS_MSG_START     /*byte5: 消息起始*/
} TRANSFER_FRAMEWORK_ENUM;


typedef struct
{
#if (HOST_ENDIAN_TYPE == BIG_ENDIAN_TYPE)
    uint8_t isCorretResp:1;
    uint8_t isHier:1;
    uint8_t isTunnel:1;
    uint8_t isResp:1;
    uint8_t cmdType:4;
#else
    uint8_t cmdType:4;
    uint8_t isResp:1;
    uint8_t isTunnel:1;
    uint8_t isHier:1;
    uint8_t isCorretResp:1;
#endif

}TRANSFER_MSG_TYPE_STRU;
#define TRANSFER_START_BTYE         0x30u   /* 第一个字节小于该值为modbus消息，大于等于改值为传输消息 */

#define TRANSFER_ASCII_BUTT       0xD0
#define TRANSFER_PROTOCOL_VERSION 0xD0


/***************************以下为CANRBUS 数据流字节位置定义*******************************************/
#define CANRBUS_FLOW_ID_BYTE_POS       0        /*流的帧标识字节位置*/
#define CANRBUS_FLOW_DST_ADDR_POS      1        /*流的目的地址的字节位置*/
#define CANRBUS_FLOW_MSG_TYPE_POS      3        /*流的消息类型的字节位置*/
#define CANRBUS_FLOW_LEN_BYTE_POS      4        /*流的数据帧长度字节位置*/
/***************************结束 CANRBUS 数据流字节位置定义*******************************************/


/***************组网相关start*******/
#define BMS_HW_INF_NULL  0xFF /*没有端口*/
#define BMS_HW_INF_SELF  0xFE /*表示指令已经到达目的地，不需要转发*/

/*
----------------------------------------------------------------------------------
广播时:
长度(bit)	1(Bit15)     	3(Bit14:12)        3(Bit11:9)	6(Bit8-3)   7(Bit1:0)
              1               目标层级          BAU           BCU       广播类型
----------------------------------------------------------------------------------
非广播:
长度(bit)	1(Bit15)     	2(Bit14:13)        6(Bit12:7)	      7(Bit6:0)
              0               BAU ID           BCU ID               BMU ID
----------------------------------------------------------------------------------
*/
#define HWID_LEVEL_1_MASK		0x7F	/*7bit*/
#define HWID_LEVEL_1_SHIFT		0
#define HWID_LEVEL_2_MASK		0x3F	/*6bit*/
#define HWID_LEVEL_2_SHIFT		7
#define HWID_LEVEL_3_MASK		0x03	/*2bit*/
#define HWID_LEVEL_3_SHIFT		13

#define HWID_BRO_DESTLEVEL_MASK		    0x07	/*3bit*/
#define HWID_BRO_DESTLEVEL_SHIFT		12
#define HWID_BRO_BAU_MASK		        0x07	/*3bit*/
#define HWID_BRO_BAU_SHIFT		        9
#define HWID_BRO_BCU_MASK		        0x3F    /*6bit*/
#define HWID_BRO_BCU_SHIFT		        3
#define HWID_BRO_TYPE_MASK		        0x7		/*3bit*/
#define HWID_BRO_TYPE_SHIFT		        0

#define GetBroLevelFromAddr(addr)  ((addr >> HWID_BRO_DESTLEVEL_SHIFT) &  HWID_BRO_DESTLEVEL_MASK)
#define GetBroTypeFromAddr(addr)  ((addr >> HWID_BRO_TYPE_SHIFT) &  HWID_BRO_TYPE_MASK)

#define HWID_BROADCAST_MASK		0x1		/*1bit*/
#define HWID_BROADCAST_SHIFT	15
#define HWID_INVALID_ID				0xFFFF

#define BROADCAST_LEVEL_1_SLAVE     1u  /*广播层级1的从控*/
#define BROADCAST_LEVEL_1_BALANCE16 2u  /*广播层级1的均衡1.6*/
#define BROADCAST_LEVEL_2_MASTER    1u  /*广播层级2的主控*/
#define BROADCAST_LEVEL_2_IBU       2u  /*广播层级2的一体机*/
#define BROADCAST_LEVEL_3_HUB       1u  /*广播层级3的总控*/


/*CMD  数据帧类型
-------------------------------------------------------------------------------------------------
    Bit0-3:               |     Bit4       |       Bit5  |   Bi6:  |   Bit7:                    |
--------------------------|----------------|-------------|---------|----------------------------|
    CMD指令类型：         |    响应与指令；| 1：非隧道； | 0：中转 |   正确响应与错误响应；     |
    0--在线升级           |   0：表示指令；| 0：隧道;    | 1：分层 |   当Bit4指示为响应时,      |
    1--记录导出           |   1：标识响应  |             |         |   置1标示正确响应；        |
    2--读写DB             |                |             |         |   FF作为正确响应的特殊指令;|
    3--运行debug指令      |                |             |         |   80预留为错误响应；       |
    4--HMI配置信息在线升级|                |             |         |                            |
-------------------------------------------------------------------------------------------------
*/
#define TRANSFER_TYPE_TUNNEL_POS     5
#define TRANSFER_TYPE_TUNNEL_MASK    (1<<TRANSFER_TYPE_TUNNEL_POS)
#define TRANSFER_TYPE_MOD_POS        6
#define TRANSFER_TYPE_MOD_MASK       (1<<TRANSFER_TYPE_MOD_POS)
#define TRANSFER_TYPE_CMDORRESP_POS  4
#define TRANSFER_TYPE_CMDORRESP_MASK (1<<TRANSFER_TYPE_CMDORRESP_POS)

#define TRANSFER_TYPE_RESP_VD_POS    7
#define TRANSFER_TYPE_RESP_VD_MASK   (1<<TRANSFER_TYPE_RESP_VD_POS) /*由于查看是否为返回消息类型 Bit7置为为Response*/
#define TRANSFER_TYPE_CMDTYPE_POS    (0x0)    /*TYPE 类型的有效位*/
#define TRANSFER_TYPE_CMDTYPE_MASK   (0x0F)

#define TRANSFER_TYPE_IS_CORRECT_RESP(msg_type) (((msg_type & TRANSFER_TYPE_CMDORRESP_MASK) > 0) && \
                                                 ((msg_type & TRANSFER_TYPE_RESP_VD_MASK) > 0))

#define TRANSFER_TYPE_ERR_RESPONSE   0x80
#define TRANSFER_TYPE_BRO_RESPONSE   0xFE
#define TRANSFER_TYPE_DATA_RESPONSE  0xFF


#define TRANSFER_CAL_MSG_TYPE(respOk,hier,tunnel,isresp,cmd) \
            ((respOk<<TRANSFER_TYPE_RESP_VD_POS)|(hier<<TRANSFER_TYPE_MOD_POS)|\
                (tunnel<<TRANSFER_TYPE_TUNNEL_POS)|(cmd<<TRANSFER_TYPE_CMDTYPE_POS))

#define TRANSFER_GET_MSGTYPE(msgType) (msgType & TRANSFER_TYPE_CMDTYPE_MASK)

typedef enum
{
    TRANSFER_TYPE_UPDATE        = 0x00,     /*升级*/
    TRANSFER_TYPE_RECORD        = 0x01,     /*记录*/
    TRANSFER_TYPE_RWDB          = 0x02,     /*读写db*/
    TRANSFER_TYPE_DEBUG         = 0x03,	    /*debug消息*/
    TRANSFER_TYPE_HMI_CONFIG    = 0X04,     /*HMI配置消息*/
    TRANSFER_TYPE_BUTT          = 0X05 ,     /*最大的支持的类型*/

}TRANSFER_MSG_TYPE_ENUM;


#pragma pack(1)
typedef struct
{
    uint8_t version;		/*版本*/
    uint16_t destDevAddr;	/*目的设备地址*/
    uint8_t msgType;		/*消息类型*/
    uint8_t msgLength;		/*消息长度*/
} TRANSFER_FRAMEWORK_STRU;

/*
If bit15==1，表示广播，
    bit(14..12)表示广播层级，
    bit(6..0)表示广播设备类型，其余保留。
If bit15==0时，表示定向传输,
    bit(14..13)L3DevId,
    bit(12..7)L2DevId,
    bit(6..0)L1DevId。
    其中L1Dev为采样设备所在层级
    2022-07-18  DFS  BCU的长度增加为 6Bits，广播时为了跟之前兼容，广播目标层级为3bits
    */
typedef struct
{
#if (HOST_ENDIAN_TYPE == BIG_ENDIAN_TYPE)
    uint16_t bro:1;
    uint16_t level3:2;
    uint16_t level2:6;
    uint16_t level1:7;
#else
    uint16_t level1:7;
    uint16_t level2:6;
    uint16_t level3:2;
    uint16_t bro:1;
#endif
}TRANSFER_DEVADDR_STRU;

typedef struct
{
#if (HOST_ENDIAN_TYPE == BIG_ENDIAN_TYPE)
    uint16_t bro:1;
    uint16_t broLevel:3;
    uint16_t broBAU:3;
    uint16_t broBCU:6;
    uint16_t broType:3;
#else
    uint16_t broType:3;
    uint16_t broBCU:6;
    uint16_t broBAU:3;
    uint16_t broLevel:3;
    uint16_t bro:1;
#endif
}TRANSFER_DEVADDR_BRO_STRU;
#pragma pack()


#define MAX_MSG_SIZE 72
#define TRANSFER_FRAMEWORK_LENGTH 7		/*传输框架字节数*/

/*-----------------------------------------------------------------------------------------
 Discription:  初始化传输模块
               分配模拟堆
 Param:        @Param1:无
 Return:       0:操作成功
               1:操作失败
*-----------------------------------------------------------------------------------------*/
int32_t Transfer_Init(void);

/*-----------------------------------------------------------------------------------------
 Discription:  清空初始化传输模块
               分配模拟堆
 Param:        @Param1:无
 Return:       0:操作成功
               1:操作失败
*-----------------------------------------------------------------------------------------*/
int32_t Transfer_DeInit(void);

/*-----------------------------------------------------------------------------------------
 Description:  传输模块接收到消息的处理
*-----------------------------------------------------------------------------------------*/
int32_t Transfer_ProcessMsgPortal(CMD_OR_RESP_ENUM style, uint8_t *buf, uint32_t length);

/*-----------------------------------------------------------------------------------------
 Discription:  注册一个传输类型的回调
               需要增加一个传输类型只需要调用该注册函数即可
 Param:        @Param1:数据类型
               @Param2:该类型数据的回调
 Return:       0:操作成功
               1:操作失败
*-----------------------------------------------------------------------------------------*/
int32_t Transfer_RegCallBack(uint16_t type, BUF_CALLBACK_FUNC pFunc);

/*-----------------------------------------------------------------------------------------
 Discription:  计算16bitCRC校验
 Param:        @Param1:校验数据内容
               @Param2:数据长度
 Return:       0:操作成功
               1:操作失败
*-----------------------------------------------------------------------------------------*/
uint16_t CalculateU16XorCrc(uint8_t *arr_buff, uint32_t len);

/*-----------------------------------------------------------------------------------------
 Discription:  发送resp数据
 Param:        @Param1:响应类型
               @Param2:发送数据内容
               @Param3:数据长度
 Return:       无
*-----------------------------------------------------------------------------------------*/
void Transfer_RespData(RESP_DATA_TYPE_ENUM respType, uint8_t *resp_data, uint32_t length);

void Transfer_RespErrData(RESP_DATA_TYPE_ENUM respType, uint8_t *resp_data, uint32_t length);


/*-----------------------------------------------------------------------------------------
 Discription:  设置下层接收到的消息的ID来源
 Author:
 Create:       2016-12-2
 Modify:
*-----------------------------------------------------------------------------------------*/
void Transfer_SetResponseDevId(uint16_t devID);

/**@brief       注册网络发送回调
 * @param[in]   pfSendCallBack 发送函数指针
 * @return      int32_t
 * @retval      0:成功
 * @par         修改日志:
 * Date         Author      Description           \n
 * 2021-06-17   zwq  创建初始版本\n
 */
int32_t Transfer_NetSendFunc(NET_MSG_SEND_FUNC pfSendCallBack);

/**
 * @brief       获取向下行转发的状态(主要使用于主控向下给从控进行485转发使用)
 * @param[in]   none，
 * @return      Std_Bool_Enum
 * @retval      Std_False:没有在进行向下转发，Std_Ture:正在进行向下转发
 * @par         修改日志:
 * Date                Author     Description       \n
 * 2021-07-20          JYG        创建初始版本            \n
*/
Std_Bool_Enum Transfer_GetDownUpdateState(void);

/**
 * @brief       配置向下行转发的状态(主要使用于主控向下给从控进行485转发使用)
 * @param[in]   Std_Bool_Enum  Std_False:没有在进行向下转发，Std_Ture:正在进行向下转发，
 * @return      none
 * @retval      0:解析成功 非0:解析失败
 * @par         修改日志:
 * Date                Author     Description       \n
 * 2021-07-20          JYG        创建初始版本            \n
*/
void Transfer_SetDownUpdateState(Std_Bool_Enum isDownUpdate);



/*!
 * @brief       发送resp数据, resp_data只有数据段内容
 *
 * @param[in]   length
 * @param[in]   msgType  TRANSFER_MSG_TYPE_ENUM
 * @param[in]   respType
 * @param[in]   resp_data
 *
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2018-07-13     LQW      Create             \n
 * 2022-07-13     dfs     根据输入的源选择response的方式 \n
 */
void Transfer_RespDataNew(RESP_DATA_TYPE_ENUM respType, uint8_t msgType, uint8_t *resp_data, uint32_t length,void *param);


/*!
 * @brief       数据流接收转发函数  用于处理全部消息接口
 *
 * @param[in]   flow
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-7-12     dfs      Create             \n
 *
 */
int32_t Transfer_Process_Msg_NewPortal(CANRBUS_FlowMsg_Infor_Stru *flow);


/*-----------------------------------------------------------------------------------------
 Description: 通过can发送消息流内容
 Create:   LQW 2018-04-27
 Modify:   JYG 2019-9-20 上行发送CAN消息时要加入CAN的帧格式
           DFS 2020-08-13 使用保序的发送方式发送CAN消息
*-----------------------------------------------------------------------------------------*/
void Can_SendFlowMsg(uint8_t cmdCode, uint32_t canbusId, uint8_t *buf, uint32_t length);


/*!
 * @brief       发送CAN消息
 *              该处如果时Resp消息肯定分级管理模式消息
 *              需要对CANID进行处理 将下个层级的ID改为广播
 * @param[in]   canbusId
 * @param[in]   flow
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-7-12     dfs      Create             \n
 *
 */
void CANRBUS_FlowMsg_Send(uint32_t canbusId, CANRBUS_FlowMsg_Infor_Stru *flow);

#endif

