#ifndef __SOFT_WATER_H
#define __SOFT_WATER_H
#include "common.h"


typedef enum{
    SPARY_DEFAULT = 0,
    SPARY_GEMO = 1, //隔膜泵 需要带流量计
    SPARY_ROUXING = 2, //柔性泵 
    SPARY_TRANSFER = 3, //转接板集成喷洒 
}SPARY;
extern uint8_t spary_type;

typedef enum{
    NOZZLE_DEFAULT = 0,
    NOZZLE_NORMAL = 1,
    NOZZLE_TRANSFER = 2, //转接板集成喷
}NOZZLE;
extern uint8_t nozzle_type;

#pragma pack(1)
typedef struct{ 
    short liquid_percent;
    uint8_t warn_falg;
    int serial_num;
}liquid;
#pragma pack()
extern liquid liquid_inf;
extern comp_status liquid_link_status;
extern bool DM4Dmsg_send_fmu;
#define Pump1 (uint32_t)0x8810
#define Pump2 (uint32_t)0x8821
#define Nozzle1 (uint32_t)0x8832
#define Nozzle2 (uint32_t)0x8843
#define Nozzle3 (uint32_t)0x8854
#define Nozzle4 (uint32_t)0x8865
#define Spread (uint32_t)0x8899

#define Z70_Public (uint8_t)0
#define Z70_Pump1 (uint8_t)1
#define Z70_Pump2 (uint8_t)2
#define Z70_Nozzle1 (uint8_t)3
#define Z70_Nozzle2 (uint8_t)4
#define Z70_Nozzle3 (uint8_t)5
#define Z70_Nozzle4 (uint8_t)6
#define Z70_Churn (uint8_t)7
#define Z70_Turntable (uint8_t)8

void Z70_Pump_Nozzle_recieved_hookfuction(uint32_t CanID, uint8_t data[], uint8_t len);
#pragma pack(1)
typedef struct 
{
    uint8_t error_status;
    uint8_t control_mode;//pwm can
    uint16_t can_baudrate;
    short rpm;
    uint8_t reserve;
    uint8_t life;
}water_dev;
#pragma pack()
extern water_dev pump1;
extern water_dev pump2;
extern water_dev nozzle1;
extern water_dev nozzle2;
extern water_dev nozzle3;
extern water_dev nozzle4;
extern water_dev churn;
extern water_dev turntable;


#pragma pack(1)
typedef struct 
{
    uint8_t flag:4;
    uint16_t pump1:10;
    uint16_t pump2:10;
    uint16_t nozzle1:10;
    uint16_t nozzle2:10;
    uint16_t nozzle3:10;
    uint16_t nozzle4:10;
}soft_water70;
#pragma pack()

#pragma pack(1)
typedef struct 
{
    uint8_t reserve;
    uint16_t k1:14;
    uint16_t k2:14;
    uint16_t k3:14;
    uint16_t k4:14;
}z70_weight;
#pragma pack()

typedef union 
{
    uint8_t buf[8];
    z70_weight info;
}weight70_dev;
extern weight70_dev z70weight;
typedef union 
{
    uint8_t buf[8];
    soft_water70 dev_water70;
}water70_dev;
extern water70_dev water70_info;

/****************************************  Hobbywing ESC***************************************/
/****************************************  Hobbywing ESC***************************************/
/****************************************  Hobbywing ESC***************************************/

//===========current sensor  test================
#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_MAX_SIZE 55
#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_SIGNATURE (0x249C26548A711966ULL)

#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_ID 1092

struct uavcan_equipment_power_BatteryInfo 
{
    float temperature;                      // 16bit
    float voltage;                      // 16bit
    float current;                      // 16bit
    float average_power_10sec;                      // 16bit
    float remaining_capacity_wh;                      // 16bit
    float full_charge_capacity_wh;                      // 16bit
    float hours_to_full_charge;                      // 16bit
    uint16_t status_flags;                      // 11bit
    uint8_t state_of_health_pct;                      // 7bit
    uint8_t state_of_charge_pct;                      // 7bit
    uint8_t state_of_charge_pct_stdev;                      // 7bit
    uint8_t battery_id;                      // 8bit
    uint32_t model_instance_id;                      // 32bit
    struct { uint8_t len; uint8_t data[31]; }model_name;
};
extern struct uavcan_equipment_power_BatteryInfo power_BatteryInfo;

#pragma pack(1)
typedef struct 
{
    uint8_t dev_type;
    uint16_t rpm;
    uint8_t warning;
    uint8_t reserve1;
    uint8_t reserve2;
    uint8_t reserve3;
    uint8_t count;
}Z70_tranfer;
#pragma pack()
extern Z70_tranfer z70_info;

extern uint16_t LiftingWeight_warning;
/*
Set_Id_Mode
0x55：可直接通过广播帧设置 ID
0xAA：需要在正常 0 油门下才能通过广播帧设置 ID
*/
#define HW_SETIDMODE_MODE1     0x55
#define HW_SETIDMODE_MODE2     0xAA
/*
Ready_Control
0x55：不需要启动命令就能驱动电调
0xAA：驱动电调之前必须发生启动命令
*/
#define HW_SETIDMODE_CONTROL1  0x55
#define HW_SETIDMODE_CONTROL2  0xAA

/*
0x00：节点 ESC 开启总线测试模式后定时上报使用该值
0xAA：开启节点 ESC 总线测试模式
0x55：关闭节点 ESC 总线测试模式
*/
#define HW_CANTEST_OPTDEF  0x00
#define HW_CANTEST_OPTOPE  0xAA
#define HW_CANTEST_OPTCLS  0x55

#define  HW_PRI_MEDIUM             0x10

#define  HW_CANID_PRI_POS         (24)
#define  HW_CANID_PRI_MASK        (0x1F000000)   // 1 1111 0000 0000 0000 0000 0000 0000
#define  HW_PRI_HIGHEST            0x00
#define  HW_PRI_HIGH               0x08
#define  HW_PRI_MEDIUM             0x10
#define  HW_PRI_LOW                0x18
#define  HW_PRI_LOWEST             0x1F

#define  HW_CANID_MSGID_POS       (8)
#define  HW_CANID_MSGID_MASK      (0x00FFFF00)   // 0 0000 1111 1111 1111 1111 0000 0000

#define  HW_CANID_SNM_POS         (7)
#define  HW_CANID_SNM_MASK        (0x00000080)   // 0 0000 0000 0000 0000 0000 1000 0000
#define  HW_TYPE_MSG               0x0           // 广播帧(message farm)
#define  HW_TYPE_SER               0x1           // 服务帧

#define  HW_CANID_SRCNODE_POS     (0)
#define  HW_CANID_SRCNODE_MASK    (0x0000007F)   // 0 0000 0000 0000 0000 0000 0111 1111
#define  HW_NODE_BDC               0x10          // 广播节点

//================================SER FRAM==============================================
#define  HW_CANID_SERID_POS       (16)
#define  HW_CANID_SERID_MASK      (0x00FF0000)   // 0 0000 1111 1111 0000 0000 0000 0000


#define  HW_CANID_RNR_POS         (15)
#define  HW_CANID_RNR_MASK        (0x00008000)   // 0 0000 0000 0000 1000 0000 0000 0000
#define  HW_TYPE_RES               0x0
#define  HW_TYPE_REQ               0x1

#define  HW_CANID_DESNODE_POS     (8)
#define  HW_CANID_DESNODE_MASK    (0x00007F00)   // 0 0000 0000 0000 0111 1111 0000 0000


//===========================广播帧==================================
#define HW_MSGCONTROL_ID            (20010)  //暂停/恢复主动数据上报指令
#define HW_FRAME_MSG_GET_ESC_ID     (20013)  //查询电调 ID 及油门通道命令为广播帧
#define HW_FRAME_MSG_SET_ID_MODE    (20014)  //进入 ID 及油门通道设置模式为广播帧
#define HW_MSG1_ID                  (20050)  //MSG1 数据是 ESC 主动上报给主节点的数据,50HZ
#define HW_MSG2_ID                  (20051)  //MSG2 数据是 ESC 主动上报给主节点的数据,10HZ
#define HW_MSG3_ID                  (20052)  //MSG3 数据是 ESC 主动上报给主节点的数据,1HZ
#define HW_RAWCOMMAND_ID            (20100)  //RawCommand 发送油门的命令，为广播帧不需要应答，总线上所有 ESC 同时接收解析。
#define HW_MSGACCLE_ID              (20150)  //MSG Accel 是 ESC 主动上报给主节点的数据，仅对配有六轴传感器的 ESC 有效
#define HW_MSGGYRO_ID               (20151)  //MSG Gyro 是 ESC 主动上报给主节点的数据，仅对配有六轴传感器的 ESC 有效。
#define HW_MSGBRUSHESC_ID           (20200)  //MSG BrushEsc 是有刷电调节点自动上报数据实时数据的数据帧
#define HW_RAWCOMMANDB_ID           (20250)  //RawCommand2 是飞控(FMU)发送有刷电调油门的命令，广播帧不需要应答，总线上所有 ESC 同时接收解析。
#define HW_DLKMSG1_ID               (20800)  //DLK MSG1 数据是 DATALINK 转发的数据帧(DATALINK 将串口协议电调数据转换为 CAN 数据帧)
#define HW_DLKMSG2_ID               (20801)  //DLK MSG2 数据是 DATALINK 转发的数据帧(DATALINK 将串口协议电调数据转换为 CAN 数据帧)


//===========================服务帧==================================
#define HW_MSGCOMMAND_ID            (200)    //供应商命令-消息命令
#define HW_UPGCOMMAND_ID            (201)    //供应商命令-升级命令
#define HW_DBGCOMMAND_ID            (202)    //供应商命令-调试命令
#define HW_SETID_ID                 (210)    //Set Id 是给 ESC 节点设置 ID 的命令，每个 ESC 对应一个 ID。(ID 0x01~0x7F,油门通道 1~8)
#define HW_SETBAUD_ID               (211)    //设置 CAN 总线速率，设置后重新上电生效。
#define HW_SETLED_ID                (212)    //Set Led Color 是主节点发送给 ESC 设置 Led 灯颜色的命令。
#define HW_SETROTATION_ID           (213)    //Set Rotation 是主节点发送给 ESC 设置电机旋转方向（顺时针/逆时针）的命令。
#define HW_SETGET_FREQ_ID           (214)    //Set Freq 是主节点发送给 ESC 设置数据上报频率的命令,会保存 FLASH 内，掉电不丢失，
#define HW_THRSELEXT_ID             (215)    //Throttle Select 是飞控 FMU 发送选择油门信号源的命令，支持 PWM 脉宽油门与 CAN 数字油门。
#define HW_SELFTEST_ID              (216)    //Self Test 是查询电调自检状态的命令。
#define HW_SETANGLE_ID              (217)    //Set Angle 是主节点设置 ESC 桨叶定位角度的命令，ESC 停止运行时桨叶会停止在设置的角度位置。
#define HW_ACCGYROCONFIG_ID         (218)    //Accel-Gyro Configuration 是六轴加速度计陀螺仪传感器配置命令，仅对配有六轴传感器的 ESC 有效。
#define HW_BRUSHESCCONFIG_ID        (219)    //Brush Esc Configuration 是主节点设置有刷电调配置参数的命令。
#define HW_SERSETID_ID              (220)    //Ser Set Id 是给 ESC 节点设置 ID 的命令，每个 ESC 对应一个 ID。
#define HW_ESCINFO_ID               (240)    //ESC Information 是获取当前电调驱动程序信息的命令。
#define HW_GETMAJORCONF_ID          (242)    //Get Major Configuration 是主节点快速获取电调主要参数配置信息的数据帧

#define HW_MSGCOMMAND_SIG            ((uint64_t)0x8c4acf8adb0375cf)
#define HW_UPGCOMMAND_SIG            ((uint64_t)0xada98653b52de435)
#define HW_DBGCOMMAND_SIG            ((uint64_t)0xe524989ae0471097)
#define HW_SETID_SIG                 ((uint64_t)0xc323cb5e9ec2b6f7)
#define HW_SETBAUD_SIG               ((uint64_t)0xed47dea06da1d619)
#define HW_SETLED_SIG                ((uint64_t)0xb493bd48c0853ee5)
#define HW_SETROTATION_SIG           ((uint64_t)0x9d793111d262ba68)
#define HW_SETGET_FREQ_SIG           ((uint64_t)0x1fd0404420983deb)
#define HW_THRSELEXT_SIG             ((uint64_t)0x0c248faaefe5e29a)
#define HW_SELFTEST_SIG              ((uint64_t)0xc48d4de61c5295df)
#define HW_SETANGLE_SIG              ((uint64_t)0x81d9b10761c28e0a)
#define HW_ACCGYROCONFIG_SIG         ((uint64_t)0xa1ed58b0897d7d5a)
#define HW_BRUSHESCCONFIG_SIG        ((uint64_t)0x1302d2cf8a1a5a71)
#define HW_SERSETID_SIG              ((uint64_t)0xc323cb5e9ec2b6f7)
#define HW_ESCINFO_SIG               ((uint64_t)0xd7fe2a212374089b)
#define HW_MAINTANCEINFO_SIG         ((uint64_t)0xb81dbd4ec9a5977d)
#define HW_GETMAJORCONF_SIG          ((uint64_t)0x1506774da3930bfd)

#define HW_CRC_INITVALUE             0xFFFF
#define HW_ESCINFO_OPT00             0x00  //电调通信程序版本
#define HW_ESCINFO_OPT01             0x01  //电调驱动程序版本
#define HW_ESCINFO_OPT02             0x02  //电调硬件版本

#define HW_MAJORCONF_OPT0            0x00  //获取配置信息

#define HW_GETESCID_OPT0             0x00  //获取ESCID及通道信息
typedef struct
{
    Connect_check Esc_Link;
    
    //MSG1(20050)
    uint16_t motorRPM;          //转速
    uint16_t pwm_value;         //PWM
    /*
    bit14:油门信号源  bit14:保留  bit13:通信异常  bit10、11、12、14保留  bit9:方向标志位  bit8:定位完成
    bit7:短路  bit6:电机断相  bit5:油门异常  bit4:电压异常  bit3:停转  bit2:堵转  bit1:过流  bit0:过温*/
    uint16_t warn_flag;

    //MSG2(20051)
    float esc_voltage;              //电调输入电压V(float16_t 类型)
    float esc_current;              //母线电流A(float16_t 类型)
    uint8_t esc_temperature;        //电调温度C

    //MSG3(20052)
    uint8_t esc_mosTemp;            //电调MOS温度C
    uint8_t esc_capTemp;            //电调电容温度C
    uint8_t esc_motorTemp;          //电机温度C
    //ack
    uint8_t MsgCtrOpt;              //0x4EA2
    uint32_t MsgCtrCmd;             //0x4EA2
    
    bool GetESCid;
    uint8_t GetEscNodeID;           //0x4E2D  ID
    uint8_t GetEscThrCh;            //0X4E2D  油门通道

    bool ResSetIDModeExit;          //
    bool ResSetID;                  //设置CANid的反馈
    uint8_t SetIDNodeID;            //设置CAN总线连接电调的node id（1~0x7D）
    uint8_t SetIDThrCh;             //选择当前node id所使用的数字油门通道
    uint8_t SetBaud;                //CAN总线速率设置

    uint8_t SetLEDOpt;              //设置灯的颜色
    uint8_t SetLEDClr;              //颜色
    uint8_t SetLEDBlk;              //闪烁时间

    uint8_t SetRotDir;              //ESC电机旋转方向设置

    uint8_t SetFreqOpt;             //设置MSG23上报频率
    uint16_t SetFreqID;
    uint8_t SetFreqFreq;

    uint8_t ThrSrc;                 //设置油门输出方式

    uint8_t SelfCheckSta;           //自检状态

    
    uint8_t _VerBuf[68];            //版本信息buf
    uint8_t _VerBufIndex;
    bool _VerBufGetS;
    
    bool GetESCInfoOpt00;
    uint8_t LinkSoftVer[16];      //电调通讯软件版本
    uint8_t LinkHardVer[16];      //电调通讯硬件版本
    uint8_t LinkDevVer[16];       //电调通讯设备类型
    uint8_t LinkSN[8];            //电调通讯软件唯一码
    
    bool GetESCInfoOpt01;
    uint8_t DriveSoftVer[16];     //电调驱动软件版本
    uint8_t DriveHardVer[16];     //电调驱动硬件版本
    uint8_t DriveDevVer[16];      //电调驱动设备类型
    uint8_t DriveSN[8];           //电调驱动软件唯一码
    
    bool GetESCInfoOpt02;
    uint8_t HardSN[16];           //电调硬件
    uint8_t ProtocolVer[8];       //电调协议版本号
    uint8_t rsv[32];              //预留

    bool GetMInfo;
    uint32_t MTLifeCycle;         //运作总共时间
    uint32_t MTLatestCycle;       //上一次运作时间
    
    bool GetMajorConf;
    uint8_t MajorConfRot;
    uint8_t MajorConfThrSrc;
    uint8_t MajorConfThrCh;
    uint8_t MajorConfLEDBlink;
    uint8_t MajorConfLEDColor;
    uint8_t MajorConfMSG2UPHZ;
    uint8_t MajorConfMSG1UPHZ;
    uint8_t MajorConfInstAngle;
} _EscLinkDevice;
extern _EscLinkDevice EscMsg[4+1];

typedef enum
{
    SETESCID_INIT  = 0,
    SETESCID_ENTER = 1,
    SETESCID_SET   = 2,
    SETESCID_EXIT  = 3,
    SETESCID_END,
}_setescid_t;
typedef struct
{
    int8_t reTxMaxCnt;
    _setescid_t setESCidStep;
    bool getSetIDModeRes;
    uint16_t getSetIDModeResCnt;
    
    uint8_t setESCidNum;   //配置第几个电调
    
    uint32_t setEscIDDelayTime;  //步骤2的PWM失能判定时间
    
}_setESCidInfo;
extern _setESCidInfo setESCidInfo;
typedef struct _hwCanTail
{
    uint8_t tranid: 5; /* 1：数值范围 0~31。
                          2：对于相同 Data Type ID 的数据，每发送一包数据，Transfer ID 加 1，0~31 循环累加。
                          3：对于同一包数据中的多个数据帧，该值不变。*/
    uint8_t toggle: 1; /* 1：对于 Single frame transfer，Toggle bit 这一位永远为 0。
                          2：对于 Multi frame transfer，数据包的首帧该位为 0，此后每发一帧该位翻转一次。*/
    uint8_t end:    1; /* 1：对于 Single frame transfer，End of transfer 这一 bit 位永远为 1。
                          2：对于 Multi frame transfer，如果当前帧是数据包的最后一帧，该位为 1，否则为 0。*/
    uint8_t start:  1; /* 1：对于 Single frame transfer，start of transfer 位永远为 1。
                          2：对于 Multi frame transfer，如果当前帧是数据包的首帧，该位为 1，否则为 0。*/
} __PACKED hwCanTail;
typedef union _HWTail
{

    uint8_t HWTailByte;
    hwCanTail HWTailBit;
} HWTail;

extern bool set_HWesc_ESCid;
/****************************************  Hobbywing ESC***************************************/
/****************************************  Hobbywing ESC***************************************/
/****************************************  Hobbywing ESC***************************************/

void Hobbywing_esc_func(void);
void liquid_recieved_hookfuction(uint32_t cellCanID,uint8_t data[], uint8_t len);
void Eft_Pump_Nozzle_recieved_hookfuction(uint32_t CanID, uint8_t data[], uint8_t len);
void can_sendmsg_eft_water(void);
int decode_liquid_info(void);
void Eft_Dev_Ack_recieved_hookfuction(uint32_t CanID, uint8_t data[], uint8_t len);
void HobbywingCanRecvHookFunction(uint32_t id, uint8_t *recv_buf, uint8_t len);
#endif