
#include "soft_okcell.h"
#include "string.h"
#include "common.h"
#include "crc.h"
#include "soft_can.h"
#include "soft_crc.h"
//在数组中array查找是否存在字符串str
//不能使用strstr函数，数组中存在'\0'的话会被结束
int findStrInArray(uint8_t *array, int aLen, const char *str);

uint8_t group_num = 0; //电池组数

#define RESET_OKIDCODE_DELAY  (3)
unsigned char okcell_sha1_out[20] = {0};
//结构体指针类型
_OKCELL_DEVICE okcell_device1 = {.Okcell_Link.connect_status = COMP_NOEXIST,
                                 .Okcell_get_s = false,
                                 .okcell_inf.cell_D0.cell_d0[6] = 0}, 
               okcell_device2 = {.Okcell_Link.connect_status = COMP_NOEXIST,
                                 .Okcell_get_s = false,
                                 .okcell_inf.cell_D0.cell_d0[6] = 0};


void OkcellCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len)
{
    _OKCELL_DEVICE *OKptr = NULL;
    //添加兼容两组电池
    static uint8_t OKIdCode1counts = 0,OKIdCode2counts = 0;
    //判断是哪个电池的ID，通过ID来区分电池。并支持飞控不断电更换电池
    if(cellCanID != okcell_device1.deviceCanID && cellCanID != okcell_device2.deviceCanID)
    {
        //分配给1号结构体
        if(OKIdCode1counts == 0){
            OKIdCode1counts = RESET_OKIDCODE_DELAY;
            
            OKptr = &okcell_device1;
            OKptr->deviceCanID = cellCanID;

            group_num = 1;
        }
        //分配给2号结构体
        else if(OKIdCode2counts == 0) {
            OKIdCode2counts = RESET_OKIDCODE_DELAY;
            
            OKptr = &okcell_device2;
            OKptr->deviceCanID = cellCanID;

            group_num = 2;
        }
        //不分配结构体
        else{
            OKIdCode1counts>0 ? OKIdCode1counts-- : OKIdCode1counts;
            OKIdCode2counts>0 ? OKIdCode2counts-- : OKIdCode2counts;
        }
    }
    else if(cellCanID == okcell_device1.deviceCanID)
    {
        OKIdCode1counts = RESET_OKIDCODE_DELAY;
            
        OKptr = &okcell_device1;
        OKptr->deviceCanID = cellCanID;
    }
    else if(cellCanID == okcell_device2.deviceCanID)
    {
        OKIdCode2counts = RESET_OKIDCODE_DELAY;
        
        OKptr = &okcell_device2;
        OKptr->deviceCanID = cellCanID;
    }
    
    
    //如果指针找到了存放数据的结构体
    if(OKptr != NULL)
    {
        //找到开头，开始接收
        //strncmp比较字符串，遇到'\0'会结束，所以不适合用字数组比较
        if(memcmp(data,"ZFKJ",4) == 0){
            OKptr->Okcell_recv_index = 0;
            OKptr->Okcell_get_s = true;
        }

        //溢出检测
        if(OKptr->Okcell_recv_index + len > OKCELL_MAXLEN)
        {
            memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index);
            OKptr->Okcell_recv_index = 0;
            OKptr->Okcell_get_s = false;
        }
        
        //接收到起始标志后开始存数组
        if(OKptr->Okcell_get_s == true){
            //复制数据
            memcpy(&OKptr->Okcell_recv_buf[OKptr->Okcell_recv_index], data, len);
            OKptr->Okcell_recv_index += len;
        }

        
        //找到结尾，开始解析,不能用strstr
        if(OKptr->Okcell_get_s == true && findStrInArray(OKptr->Okcell_recv_buf, OKptr->Okcell_recv_index, "END") != 0)
        {
            OKptr->Okcell_get_s = false;
            
            unsigned char loadflag = OKptr->Okcell_recv_buf[7];
            //负载标识为固定的OxBB
            if(loadflag == 0xBB)
            {
                unsigned char cellLoadLen = OKptr->Okcell_recv_buf[6];
                
                //避免错误数据造成的数组溢出
                if(cellLoadLen < OKCELL_MAXLEN-9)
                {
                    unsigned int cellCheck = OKptr->Okcell_recv_buf[8+cellLoadLen]*256 + OKptr->Okcell_recv_buf[9+cellLoadLen];
                    //校验通过,测试没通过
                    if(((crc_ccitt(&OKptr->Okcell_recv_buf[8], cellLoadLen))&0xffff) == cellCheck)
                    {
                        unsigned short cellCmd = (OKptr->Okcell_recv_buf[4]<<8) + OKptr->Okcell_recv_buf[5];
                        
                        OKptr->Okcell_Link.connect_status = COMP_NORMAL;
                        
                        //用于判断电池波特率锁定，实测只要给电池发送数据，电池收到后就会锁定波特率
                        //由于锁定波特率缺少反馈应答，5s内收到多于10包正确的数据则认为波特率锁定成功。
                        if(OKptr->cell_bps_lock_success == false)
                        {
                            OKptr->recv_celldata_counts++;
                            if(OKptr->recv_celldata_counts == 1){
                                OKptr->recv_celldata_time = HAL_GetTick();
                            }
                            else if(OKptr->recv_celldata_counts >= 10)
                            {
                                OKptr->recv_celldata_counts = 0;
                                uint32_t timeperiod = HAL_GetTick() - OKptr->recv_celldata_time;
                                if(timeperiod < 5000000)
                                {
                                    OKptr->cell_bps_lock_success = true;
                                }
                            }
                        }
                        
                        //更新电池数据到来时间
                        OKptr->Okcell_Link.recv_time = HAL_GetTick();
                        
                        switch(cellCmd)
                        {
                            case 0x0000:
                                //stm32为小段模式，OKCELL发送过来的数据为大端模式，不能使用memcpy
                                //memcpy(&cell_D0,&Okcell_recv_buf[8],cellLoadLen);
                                //避免电池厂家私自增加协议造成的数组溢出
                                if(cellLoadLen <= sizeof(_CELL_D0))
                                {
                                    for(unsigned char i=0; i<cellLoadLen/2; i++)
                                    {
                                        OKptr->okcell_inf.cell_D0.cell_d0[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2];
                                    }
                                }
                                break;
                            case 0x0300:
                                //cell_inf1.cell_D3.cell_d3[4] = (Okcell_recv_buf[16] << 8) + Okcell_recv_buf[17];
                                //避免电池厂家私自增加协议造成的数组溢出
                                if(cellLoadLen <= sizeof(_CELL_D3))
                                {
                                    for(unsigned char i=0; i<cellLoadLen/2; i++)
                                    {
                                        OKptr->okcell_inf.cell_D3.cell_d3[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2];
                                    }
                                }
                                break;
                            case 0x8200://SHA1加密文密码查询
                                //避免电池厂家私自增加协议造成的数组溢出
                                if(cellLoadLen <= sizeof(_CELL_P2))
                                {
                                    for(unsigned char i=0; i<cellLoadLen; i++)
                                    {
                                        OKptr->okcell_inf.cell_P2.cell_p2[i] = OKptr->Okcell_recv_buf[8 + i];
                                    }
                                }
                                
                                if(memcmp(OKptr->okcell_inf.cell_P2.cell_p2, okcell_sha1_out, sizeof(_CELL_P2)) == 0)
                                {
                                    //收到了正确密文
                                    OKptr->get_cellEncryption = true;
                                }
                                break;
                            case 0x8300://获取电池编号
                                OKptr->get_cellNumber = true;
                                //避免电池厂家私自增加协议造成的数组溢出
                                if(cellLoadLen <= sizeof(_CELL_P3))
                                {
                                    for(uint8_t i=0; i<cellLoadLen; i++)
                                    {
                                        OKptr->okcell_inf.cell_P3.cell_p3[i] = OKptr->Okcell_recv_buf[8 + i];
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            
            //清理buff
            memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index);
            
            //包数完整重新计数
            OKptr->Okcell_recv_index = 0;
        }
    }
}




/*

上电前10s持续发送数据给智能电池，用于设置通信速率
*/



struct OkCell_P80 okcell_p80;
struct OkCell_P82 okcell_p82;
struct OkCell_P83 okcell_p83;

uint32_t time_okcell_p80 = 0;
uint32_t time_okcell_p82 = 0;
uint32_t time_okcell_p83 = 0;
bool send_okcell_p80data = false;
bool send_okcell_p82data = false;
bool send_okcell_p83data = false;

void send_msg_to_okcell(void)
{
    //自动锁定波特率，正方电池开机自动循环500K/1M发送数据。正方电池缺少一个波特率锁定的反馈应答
    //电池开机会自动1M/500k切换波特率给飞控发信息，所以不用用是否连接来判断。
    if(/*okcell_device1.okcell_link_status == COMP_NOEXIST &&*/ send_okcell_p80data == false && 
        okcell_device1.cell_bps_lock_success == false && HAL_GetTick() < 30000 && 
        HAL_GetTick() - time_okcell_p80 > 250)
    {
        time_okcell_p80 = HAL_GetTick();

        okcell_p80.ok_s[0] = 'Z';
        okcell_p80.ok_s[1] = 'F';
        okcell_p80.ok_s[2] = 'K';
        okcell_p80.ok_s[3] = 'J';
        
        okcell_p80.ok_cmd[0] = 0x80;
        okcell_p80.ok_cmd[1] = 0x00;
        okcell_p80.ok_len = 1;
        okcell_p80.ok_flag = 0xbb;
        okcell_p80.ok_data = 0x79;
        
        short OKcellCRC = crc_ccitt((uint8_t *)&okcell_p80.ok_data,okcell_p80.ok_len);
        okcell_p80.ok_crc[0] = (OKcellCRC>>8) & 0xff;
        okcell_p80.ok_crc[1] = OKcellCRC & 0xff;
        
        okcell_p80.ok_e[0] = 'E';
        okcell_p80.ok_e[1] = 'N';
        okcell_p80.ok_e[2] = 'D';
        
        send_okcell_p80data = true;
    }
    
    if(send_okcell_p80data == true){
        send_okcell_p80data =false;
        can_send_msg_normal((unsigned char *)&okcell_p80,sizeof(okcell_p80),CAN_OKCELL_SEND_ID);
    }
    
    if(send_okcell_p82data == true){
        send_okcell_p82data =false;
        can_send_msg_normal((unsigned char *)&okcell_p82,sizeof(okcell_p82),okcell_device1.deviceCanID);
    }
    
    
    
    //获取电池编号
    if(okcell_device1.Okcell_Link.connect_status == COMP_NORMAL && okcell_device1.cell_bps_lock_success == true && 
        okcell_device1.get_cellNumber == false && 
        send_okcell_p83data == false && HAL_GetTick() - time_okcell_p83 > 1000)
    {
        time_okcell_p83 = HAL_GetTick();
        
        okcell_p83.ok_s[0] = 'Z';
        okcell_p83.ok_s[1] = 'F';
        okcell_p83.ok_s[2] = 'K';
        okcell_p83.ok_s[3] = 'J';
        
        okcell_p83.ok_cmd[0] = 0x83;
        okcell_p83.ok_cmd[1] = 0x00;
        okcell_p83.ok_len = 0;
        okcell_p83.ok_flag = 0xbb;
        okcell_p83.ok_crc[0] = 0xff;
        okcell_p83.ok_crc[1] = 0xff;
        
        okcell_p83.ok_e[0] = 'E';
        okcell_p83.ok_e[1] = 'N';
        okcell_p83.ok_e[2] = 'D';
        
        send_okcell_p83data = true;
    }
    
    if(send_okcell_p83data == true){
        send_okcell_p83data =false;
        can_send_msg_normal((unsigned char *)&okcell_p83,sizeof(okcell_p83),okcell_device1.deviceCanID);
    }
}







