
#include "soft_poweramp.h"
#include "string.h"
#include "common.h"
#include "crc.h"
#include "soft_can.h"
#include "soft_okcell.h"
#include "soft_crc.h"

//在数组中array查找是否存在字符串str
//不能使用strstr函数，数组中存在'\0'的话会被结束
int findStrInArray(uint8_t *array, int aLen, const char *str);

short Poweramp_recv_index = 0;
//获取到起始标志位
bool Poweramp_get_s = false;

#define POWERAMP_MAXLEN 100
unsigned char Poweramp_recv_buf[POWERAMP_MAXLEN] = {0};

Connect_check Poweramp_Link;

_POWERAMP_INF poweramp_inf = {0};
_POWERAMP_VER poweramp_ver = {0};
_POWERAMP_SYS poweramp_sys = {0};


bool get_poweramp_handle_ack = false;
bool get_poweramp_pair_data = false;

bool get_poweramp_ver = false;
bool get_poweramp_sys = false;

void PowerAmpCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len)
{

    Poweramp_Link.recv_time = HAL_GetTick();
    
    //找到开头，开始接收
    //strncmp比较字符串，遇到'\0'会结束，所以不适合用字数组比较
    if(memcmp(data,"{",1) == 0){
        Poweramp_recv_index = 0;
        Poweramp_get_s = true;
    }
    
    //溢出检测
    if(Poweramp_recv_index + len > POWERAMP_MAXLEN)
    {
        memset(Poweramp_recv_buf,0,Poweramp_recv_index);
        Poweramp_recv_index = 0;
        Poweramp_get_s = false;
    }
    
    //接收到起始标志后开始存数组
    if(Poweramp_get_s == true){
        //复制数据
        memcpy(&Poweramp_recv_buf[Poweramp_recv_index], data, len);
        Poweramp_recv_index += len;
    }

    
    //找到结尾，开始解析,不能用strstr
    if(Poweramp_get_s == true && findStrInArray(Poweramp_recv_buf, Poweramp_recv_index, "}") != 0
        && Poweramp_recv_buf[1] == Poweramp_recv_index - 4)
    {
        Poweramp_get_s = false;
        
        unsigned char powamplength = Poweramp_recv_buf[1];
        unsigned char powampcommand = Poweramp_recv_buf[2];
        
        //字节数是否正确
        if(powamplength == Poweramp_recv_index-4)
        {
            unsigned char powerampCheck = Poweramp_recv_buf[powamplength+2];
            //校验通过,测试没通过
            if((poweramp_CRC8(&Poweramp_recv_buf[1], powamplength+1, POWERAMP_CRC8_KEY)) == powerampCheck)
            {
                time_poweramp_lastrecv = HAL_GetTick();
                
                switch(powampcommand)
                {
                    case 0x00:
                        //握手索引，0-握手反馈，1-加密数据反馈
                        switch(Poweramp_recv_buf[3])
                        {
                            case 0x00:
                                if(Poweramp_recv_buf[4] == 0x00)
                                    get_poweramp_handle_ack = true;
                                break;
                            case 0x01:
                                get_poweramp_pair_data = true;
                                break;
                            default:
                                break;
                        }
                        break;
                    case 0x01:
                        //前面握手阶段不能识别为连接状态，
                        Poweramp_Link.connect_status = COMP_NORMAL;
                
                        //避免电池厂家私自增加协议造成的数组溢出
                        if(powamplength-1 <= sizeof(_POWERAMP_INF))
                        {
                            memcpy((void *)&poweramp_inf, &Poweramp_recv_buf[3], powamplength-1);
                        }
                        break;
                    case 0x20:
                        get_poweramp_ver = true;
                        //避免电池厂家私自增加协议造成的数组溢出
                        if(powamplength-1 <= sizeof(_POWERAMP_VER))
                        {
                            memcpy((void *)&poweramp_ver, &Poweramp_recv_buf[3], powamplength-1);
                        }
                        break;
                    case 0x21:
                        get_poweramp_sys = true;
                        //避免电池厂家私自增加协议造成的数组溢出
                        if(powamplength-1 <= sizeof(_POWERAMP_SYS))
                        {
                            memcpy((void *)&poweramp_sys, &Poweramp_recv_buf[3], powamplength-1);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        
        //清理buff
        memset(Poweramp_recv_buf,0,Poweramp_recv_index);
        
        //包数完整重新计数
        Poweramp_recv_index = 0;
    }
}




/*

上电前10s持续发送握手数据给智能电池，用于启动供电
*/

#define CAN_POWERAMP_SEND_ID    (0x188)

#pragma pack(1)
struct Poweramp_Handshake{

    char amp_sof;
    char amp_length;
    char amp_command;
    char amp_data[14];
    char amp_crc;
    char amp_eof;
};
#pragma pack()
struct Poweramp_Handshake poweramp_handshake;



#pragma pack(1)
struct Poweramp_Handpair{

    char amp_sof;
    char amp_length;
    char amp_command;
    char amp_data[2];
    char amp_crc;
    char amp_eof;
};
#pragma pack()
struct Poweramp_Handpair poweramp_handpair;




#pragma pack(1)
struct Poweramp_Uavheart{

    char amp_sof;
    char amp_length;
    char amp_command;
    char amp_data[6];
    char amp_crc;
    char amp_eof;
};
#pragma pack()
struct Poweramp_Uavheart poweramp_uavheart;



#pragma pack(1)
struct Poweramp_Ver{

    char amp_sof;
    char amp_length;
    char amp_command;
    char amp_crc;
    char amp_eof;
};
#pragma pack()
struct Poweramp_Ver poweramp_sver;



#pragma pack(1)
struct Poweramp_Sys{

    char amp_sof;
    char amp_length;
    char amp_command;
    char amp_crc;
    char amp_eof;
};
#pragma pack()
struct Poweramp_Sys poweramp_ssys;



uint32_t time_poweramp_handle = 0;
bool send_poweramp_handle = false;

uint32_t time_poweramp_pairack = 0;
bool send_poweramp_pairack = false;

uint32_t time_poweramp_uavheart = 0;
bool send_poweramp_uavheart = false;

uint32_t time_poweramp_ver = 0;
bool send_poweramp_ver = false;

uint32_t time_poweramp_sys = 0;
bool send_poweramp_sys = false;

//上次发送时间，做延时间隔
uint32_t time_poweramp_lastsend = 0;


//极目电池485半双工，收到信息后最好延迟100ms再发送下一次
uint32_t time_poweramp_lastrecv = 0;

char send_poweramp_uavheart_counts = 0;
//握手发送次数
char send_poweramp_handle_counts = 0;
char send_poweramp_pairack_counts = 0;
char send_poweramp_ver_counts = 0;
char send_poweramp_sys_counts = 0;


#define HANDLE_COUNTS_MAX 5
#define PAIRACK_COUNTS_MAX 2
#define UAVHEART_COUNTS_MAX 5
#define VERSYS_COUNTS_MAX 5


void send_msg_to_poweramp(void)
{   
    //程序不关闭发握手不反馈，电池热插拔无法正常握手，发心跳才回复实时信息
    if((Poweramp_Link.connect_status == COMP_NOEXIST || Poweramp_Link.connect_status == COMP_RECON) && HAL_GetTick() > 5000)
    {
        //极目电池开机需要发送握手信息来启动通信。
        if(send_poweramp_handle == false && 
            get_poweramp_handle_ack == false && send_poweramp_handle_counts < HANDLE_COUNTS_MAX && 
            HAL_GetTick() - time_poweramp_handle > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
        {
            send_poweramp_handle_counts++;
            
            time_poweramp_handle = HAL_GetTick();
            time_poweramp_pairack = HAL_GetTick();
            time_poweramp_uavheart = HAL_GetTick();

            poweramp_handshake.amp_sof = '{';
            poweramp_handshake.amp_length = 15;
            poweramp_handshake.amp_command = 0;
            
            poweramp_handshake.amp_data[0] = 1;
            poweramp_handshake.amp_data[1] = 0;
            poweramp_handshake.amp_data[2] = 'E';
            poweramp_handshake.amp_data[3] = 'A';
            poweramp_handshake.amp_data[4] = 'V';
            poweramp_handshake.amp_data[5] = 'i';
            poweramp_handshake.amp_data[6] = 's';
            poweramp_handshake.amp_data[7] = 'i';
            poweramp_handshake.amp_data[8] = 'o';
            poweramp_handshake.amp_data[9] = 'n';
            poweramp_handshake.amp_data[10] = 't';
            poweramp_handshake.amp_data[11] = 'e';
            poweramp_handshake.amp_data[12] = 'c';
            poweramp_handshake.amp_data[13] = 'h';
            
            poweramp_handshake.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handshake.amp_length,poweramp_handshake.amp_length+1,POWERAMP_CRC8_KEY);
            
            poweramp_handshake.amp_eof = '}';
            
            send_poweramp_handle = true;
        }            
        //发送握手后电池回复握手并回复加密数据，收到极目电池的加密数据后回复确认信息,然后开始通信（回复确认消息时没有反馈的所以发送两次）
        else if(get_poweramp_pair_data == true && send_poweramp_pairack_counts < PAIRACK_COUNTS_MAX && 
           send_poweramp_pairack == false && HAL_GetTick() - time_poweramp_pairack > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
        {
            send_poweramp_pairack_counts++;
            
            time_poweramp_pairack = HAL_GetTick();
            time_poweramp_uavheart = HAL_GetTick();
            
            poweramp_handpair.amp_sof = '{';
            poweramp_handpair.amp_length = 3;
            poweramp_handpair.amp_command = 0;
            
            poweramp_handpair.amp_data[0] = 1;
            poweramp_handpair.amp_data[1] = 0;
            
            poweramp_handpair.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handpair.amp_length, poweramp_handpair.amp_length+1, POWERAMP_CRC8_KEY);
            
            poweramp_handpair.amp_eof = '}';
            
            send_poweramp_pairack = true;
        }
        //握手完成以及握手失败后直接发心跳，避免热插拔无法握手而通信失败
        else if(((get_poweramp_handle_ack == false && send_poweramp_handle_counts == HANDLE_COUNTS_MAX) || (get_poweramp_pair_data == true && send_poweramp_pairack_counts == PAIRACK_COUNTS_MAX)) && 
            send_poweramp_uavheart_counts < UAVHEART_COUNTS_MAX &&  
            send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
        {
            send_poweramp_uavheart_counts++;
            
            time_poweramp_uavheart = HAL_GetTick();
            time_poweramp_lastsend = HAL_GetTick();
            
            poweramp_uavheart.amp_sof = '{';
            poweramp_uavheart.amp_length = 7;
            poweramp_uavheart.amp_command = 0x25;
            
            poweramp_uavheart.amp_data[0] = 0x08;
            
            poweramp_uavheart.amp_data[1] = 0;
            poweramp_uavheart.amp_data[2] = 1;
            poweramp_uavheart.amp_data[3] = 2;
            poweramp_uavheart.amp_data[4] = 3;
            
            poweramp_uavheart.amp_data[5] = 2;
            
            poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY);
            
            poweramp_uavheart.amp_eof = '}';
            
            send_poweramp_uavheart = true;
        }
    }
    //极目电池的需要发送心跳信息才会回复电池信息,在握手后的状态再次发握手电池不反馈，此时电池还不吐数据，比较难判断
    else if(Poweramp_Link.connect_status == COMP_NORMAL || Poweramp_Link.connect_status == COMP_LOST)
    {
        //读取版本信息
        if(get_poweramp_ver == false && send_poweramp_ver_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_ver > 500 && 
           HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
        {
            send_poweramp_ver_counts++;
            time_poweramp_ver = HAL_GetTick();
            time_poweramp_sys = HAL_GetTick();
            time_poweramp_lastsend = HAL_GetTick();
            
            poweramp_sver.amp_sof = '{';
            poweramp_sver.amp_length = 1;
            poweramp_sver.amp_command = 0x20;
            
            poweramp_sver.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_sver.amp_length, poweramp_sver.amp_length+1, POWERAMP_CRC8_KEY);
            
            poweramp_sver.amp_eof = '}';
            
            send_poweramp_ver = true;
        }
        //获取系统信息
        else if((get_poweramp_ver == true || send_poweramp_ver_counts >= VERSYS_COUNTS_MAX) && get_poweramp_sys == false && 
                send_poweramp_sys_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_sys > 500 && 
                HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
        {
            send_poweramp_sys_counts++;
            time_poweramp_sys = HAL_GetTick();
            time_poweramp_lastsend = HAL_GetTick();
            
            poweramp_ssys.amp_sof = '{';
            poweramp_ssys.amp_length = 1;
            poweramp_ssys.amp_command = 0x21;
            
            poweramp_ssys.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_ssys.amp_length, poweramp_ssys.amp_length+1, POWERAMP_CRC8_KEY);
            
            poweramp_ssys.amp_eof = '}';
            
            send_poweramp_sys = true;
        }
        
        //每一秒钟发送心跳包
        if(send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 1000 && 
           HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
        {
            time_poweramp_uavheart = HAL_GetTick();
            time_poweramp_lastsend = HAL_GetTick();
            
            poweramp_uavheart.amp_sof = '{';
            poweramp_uavheart.amp_length = 7;
            poweramp_uavheart.amp_command = 0x25;
            
            poweramp_uavheart.amp_data[0] = 0x08;
            
            poweramp_uavheart.amp_data[1] = 0;
            poweramp_uavheart.amp_data[2] = 1;
            poweramp_uavheart.amp_data[3] = 2;
            poweramp_uavheart.amp_data[4] = 3;
            
            poweramp_uavheart.amp_data[5] = 2;
            
            poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY);
            
            poweramp_uavheart.amp_eof = '}';
            
            send_poweramp_uavheart = true;
        }
    }    

    //发送心跳
    if(send_poweramp_uavheart == true){
        send_poweramp_uavheart = false;
        can_send_msg_normalstd((unsigned char *)&poweramp_uavheart,sizeof(poweramp_uavheart),CAN_POWERAMP_SEND_ID);
    }
    //放在外部发送。不能放在条件内部，当条件不成立时会造成发送不完整。
    else if(send_poweramp_handle == true){
        send_poweramp_handle =false;
        can_send_msg_normalstd((unsigned char *)&poweramp_handshake,sizeof(poweramp_handshake),CAN_POWERAMP_SEND_ID);
    }
    //放在外部发送。不能放在条件内部，当条件不成立时会造成发送不完整。
    else if(send_poweramp_pairack == true){
        send_poweramp_pairack = false;
        can_send_msg_normalstd((unsigned char *)&poweramp_handpair,sizeof(poweramp_handpair),CAN_POWERAMP_SEND_ID);
    }
    //放在外部发送。不能放在条件内部，当条件不成立时会造成发送不完整。
    else if(send_poweramp_ver == true){
        send_poweramp_ver = false;
        can_send_msg_normalstd((unsigned char *)&poweramp_sver,sizeof(poweramp_sver),CAN_POWERAMP_SEND_ID);
    }
    //放在外部发送。不能放在条件内部，当条件不成立时会造成发送不完整。
    else if(send_poweramp_sys == true){
        send_poweramp_sys = false;
        can_send_msg_normalstd((unsigned char *)&poweramp_ssys,sizeof(poweramp_ssys),CAN_POWERAMP_SEND_ID);
    }
}




/**
  * @brief 智能电池连接监测
  */
unsigned int poweramp_reconnent_time = 0;

void check_poweramp_link(void)
{
    static short poweramp_lostcounts = 0;

    Poweramp_Link.error_time = HAL_GetTick() - Poweramp_Link.recv_time;

    // 如果存在且超过5s没有收到正确雷达数据，则表示智能电池连接有问题
    // 不是优先级非常高的，给予充足的时间来判断断开
    // 便于区分是最开始就没连接还是连接后断开了。
    if (Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time > 5000))
    {
        poweramp_lostcounts++;
        if(poweramp_lostcounts >= 50)
        {
            poweramp_lostcounts = 50;
            
            Poweramp_Link.connect_status = COMP_LOST;
            
            //清空电池信息数据
            //memset(&poweramp_inf, 0, sizeof(poweramp_inf));
            
            send_poweramp_uavheart_counts = 0;
            send_poweramp_handle_counts = 0;
            send_poweramp_pairack_counts = 0;
            send_poweramp_ver_counts = 0;
            send_poweramp_sys_counts = 0;
            
            //不重新回去版本及系统信息
            //get_poweramp_sys = false;
            //get_poweramp_ver = false;
            get_poweramp_handle_ack = false;
            get_poweramp_pair_data = false;
        }
    }
    else if((Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time < 5000)))
    {
        poweramp_lostcounts = 0;
    }
    //超过200s，电池会休眠
    else if((Poweramp_Link.connect_status == COMP_LOST && (Poweramp_Link.error_time > 200000)))
    {
        Poweramp_Link.connect_status = COMP_RECON;
    }
    //不存在或者重连状态是定时握手
    else if((Poweramp_Link.connect_status == COMP_RECON || Poweramp_Link.connect_status == COMP_NOEXIST) && 
            HAL_GetTick() - poweramp_reconnent_time > 10000)
    {
        poweramp_reconnent_time = HAL_GetTick();
        
        get_poweramp_handle_ack = false;
        get_poweramp_pair_data = false;
        
        send_poweramp_uavheart_counts = 0;
        //握手发送次数
        send_poweramp_handle_counts = 0;
        send_poweramp_pairack_counts = 0;
    }
}



