/*
 * @Author       : ChenJie
 * @Date         : 2022-01-21 09:28:20
 * @Version      : V3.0
 * @LastEditors  : ChenJie
 * @LastEditTime : 2022-02-14 15:23:30
 * @Description  : file content
 * @FilePath     : \S32K146_4G\src\AppFuncLib.c
 */
/*
 * AppFuncLib.c
 *应用层函数库
 *  Created on: 2022年1月21日
 *      Author: QiXiang_CHENJIE
 */

#include "AppFuncLib.h"
#include "AppGlobalVar.h"
#include "Hal_Fls.h"
#include "AppTaskUart1.h"
/**
 * @brief : 获取故障码函数，从故障数组中获取故障码，并将之前的故障码向前移动
 * @param {UINT16} *ErrorArray
 * @param {UINT8} Errorlen
 * @return {*}
 */
static uint8 bcc_chk_fota(uint8 *data, uint8 length);
static uint8 Fota_crc_chk(uint8 *data, uint8 length);
uint16 GetErrorNum(uint16 *ErrorArray, uint8 Errorlen)
{
    uint16 OutNum;
    OutNum = *(ErrorArray);
    for (uint8 i = 0; i < Errorlen - 1; i++)
    {
        *(ErrorArray + i) = *(ErrorArray + i + 1);
        if (*(ErrorArray + i + 1) == 0)
            break;
    }
    return OutNum;
}
uint8 PutErrorNum(uint16 *ErrorArray, uint8 Errorlen, uint16 ErrorNum)
{
    for (uint8 i = 0; i < Errorlen; i++)
    {
        if (*(ErrorArray + i) == 0)
        {
            *(ErrorArray + i) = ErrorNum;
            return 0;
        }
        else
        {
            if (*(ErrorArray + i) == ErrorNum)
            {
                return 1;
            }
            else
            {
                continue;
            }
        }
    }
    return 2;
}
uint16 ATstrdel(char *str)
{
    char *p = str;
    bool flag = false;
    while (*str)
    {
        if (*str > 0x20)
        {
            *(p) = *str;
            p = p + 1;
            flag = false;
        }
        else
        {
            if (!flag)
            {
                *(p) = ',';
                p = p + 1;
                flag = true;
            }
        }
        str++;
    }
    *p = '\0';
    return 0;
}
uint16 mstrlen(const char *s)
{
    uint16 out = 0;
    const char *ss = s;
    while (*ss)
        ss++;
    out = (ss - s);
    return out;
}
int mstrncmp(const char *s1, const char *s2, int n)
{
    const unsigned char *c1 = (const unsigned char *)s1;
    const unsigned char *c2 = (const unsigned char *)s2;
    unsigned char ch;
    int d = 0;
    while (n--)
    {
        d = (int)(ch = *c1++) - (int)*c2++;
        if (d || !ch)
            break;
    }
    return d;
}
unsigned char HexToChar(unsigned char bHex)
{
    if ((bHex >= 0) && (bHex <= 9))
        bHex += 0x30;
    else if ((bHex >= 10) && (bHex <= 15)) //大写字母
        bHex += 0x37;
    else
        bHex = 0xff;
    return bHex;
}
unsigned char CharToHex(unsigned char bChar)
{
    if ((bChar >= 0x30) && (bChar <= 0x39))
        bChar -= 0x30;
    else if ((bChar >= 0x41) && (bChar <= 0x46)) //大写字母
        bChar -= 0x37;
    else if ((bChar >= 0x61) && (bChar <= 0x66)) //小写字母
        bChar -= 0x57;
    else
        bChar = 0xff;
    return bChar;
}
uint8 AtStrCompare(const char *a, const char *b)
{
    uint8 out = 1;
    while (1)
    {
        if (*a == '\0' || *b == '\0') //判断其中是否有字符串结束
        {
            if (strlen(a) == strlen(b))
            {
                out = 1;
                break;
            }
            else
            {
                out = 0;
                break;
            }
        }
        else
        {
            if (*a != *b)
            {
                out = 0;
                break;
            }
            else if (*a == '=' && *b == '=')
            {
                out = 1;
                break;
            }
        }
        a++;
        b++;
    }
    return out;
}
unsigned short CRC16_Modbus(unsigned char *pdata, int len)
{
    unsigned short crc = 0xFFFF;
    int i, j;
    for (j = 0; j < len; j++)
    {
        crc = crc ^ pdata[j];
        for (i = 0; i < 8; i++)
        {
            if ((crc & 0x0001) > 0)
            {
                crc = crc >> 1;
                crc = crc ^ 0xa001;
            }
            else
                crc = crc >> 1;
        }
    }
    return crc;
}
char *Myitoa(int value, char *result, int base)
{
    // check that the base if valid
    if (base < 2 || base > 36)
    {
        *result = '\0';
        return result;
    }

    char *ptr = result, *ptr1 = result, tmp_char;
    int tmp_value;

    do
    {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
    } while (value);

    // Apply negative sign
    if (tmp_value < 0)
        *ptr++ = '-';
    *ptr-- = '\0';
    while (ptr1 < ptr)
    {
        tmp_char = *ptr;
        *ptr-- = *ptr1;
        *ptr1++ = tmp_char;
    }
    return result;
}

/************************************************************************
 * @brief 整数转字符串
 * @param[in] num 整数
 * @param[out] buf 字符串
 * @return 返回字符串长度
 ************************************************************************/
inline int _itoa(int num, char buf[32])
{
    return _i2a(num, buf, 10);
}

/************************************************************************
 * @brief 整数转字符串
 * @param[in] num 整数
 * @param[out] buf 字符串
 * @param[in] radix 进位制整数
 * @return 返回字符串长度
 ************************************************************************/
int _i2a(int num, char buf[32], int radix)
{
    static const char s[] = "0123456789abcdef";
    int n = num, R = radix;
    char *dst = buf;
    if (n < 0)
    {
        *dst++ = '-';
        n = -n;
    }
    if (n < 10)
    {
        *dst++ = s[n];
        *dst = 0;
    }
    else
    {
        char tmp[32], *p = tmp;
        while (n)
        {
            *p++ = s[n % R];
            n /= R;
        }
        while (--p != tmp)
            *dst++ = *p;
        *dst++ = *tmp;
        *dst = 0;
    }
    return dst - buf;
}

/************************************************************************
 * @brief 浮点数转字符串
 * @param[in] val 浮点数
 * @param[out] buf 字符串
 * @param[in] eps 精度(小数位)
 * @return 返回字符串长度
 ************************************************************************/
int _ftoa(double val, char buf[32], int eps)
{
    double f = val;
    char *p = buf;
    if (val < 0)
    {
        *p++ = '-';
        f = -f;
    }
    int n = f;
    int len = _itoa(n, p);
    return len + __ftoa(f - n, p + len, eps);
}

/************************************************************************
 * @brief 浮点数转字符串：范围(-1, 1)
 * @param[in] val 浮点数
 * @param[out] buf 字符串
 * @param[in] eps 精度(小数位)
 * @return 返回字符串长度
 ************************************************************************/
int __ftoa(double val, char buf[32], int eps)
{
    double f = val;
    char *p = buf;
    static const char s[] = "0123456789";
    if (f < 0)
    {
        *p++ = '-';
        f = -f;
    }
    *p++ = '.';
    for (int i = eps + 1, n; --i; ++p, f -= n)
        *p = s[n = f *= 10.0];
    *p = 0;
    return p - buf;
}

/************************************************************************
 * @brief 替换sprintf
 * @ref 可变长参数列表误区与陷阱——va_arg不可接受的类型
 * http://www.cppblog.com/ownwaterloo/archive/2009/04/21/80655.aspx
 ************************************************************************/
int _sprintf(char *dst, const char *format, ...)
{
    char *s = dst;
    const char *f = format;
    va_list ap, another;
    va_start(ap, format);
    va_copy(another, ap);
    while (*f)
    {
        int n = 1;
        if ('%' != *f)
        {
            *s = *f;
        }
        else
        {
            ++f;
            switch (*f)
            {
            case 's': // 字符串
            {
                const char *p = va_arg(ap, char *);
                n = strlen(p);
                memcpy(s, p, n);
            }
            break;

            case 'd':
            case 'u': // 整数
            {
                char buf[32];
                n = _itoa(va_arg(ap, int), buf);
                memcpy(s, buf, n);
            }
            break;

            case 'f': // 浮点数
            {
                char buf[32];
                n = _ftoa(va_arg(ap, double), buf, 6);
                memcpy(s, buf, n);
            }
            break;

            case 'x': // 16进制数
            {
                char buf[32];
                n = _i2a(va_arg(ap, int), buf, 16);
                memcpy(s, buf, n);
            }
            break;

            case 'c': // 字符
            {
                *s = va_arg(ap, int);
            }
            break;

            case '%': // 百分号
            {
                *s = '%';
            }
            break;

            default:
            {
                va_end(ap);
                int x = vsprintf(dst, format, another);
                va_end(another);
                return x;
            }
            break;
            }
        }
        ++f;
        s += n;
    }
    *s = 0;
    va_end(ap);
    return s - dst;
}
uint8 bcc_chk(uint8 *data, uint16 length)
{
    uint8 bcc_chk_return = 0x00;
    uint16 count = 0;
    while (count < length)
    {
        bcc_chk_return ^= data[count];
        count++;
    }
    return bcc_chk_return;
}
uint16 crc_chk(uint8 *data, uint8 length)
{
    uint8 j;
    uint16 reg_crc = 0xFFFF;
    while (length--)
    {
        reg_crc ^= *data++;
        for (j = 0; j < 8; j++)
        {
            if (reg_crc & 0x01)
            {
                reg_crc = (reg_crc >> 1) ^ 0xA001;
            }
            else
            {
                reg_crc = reg_crc >> 1;
            }
        }
    }
    return reg_crc;
}
/**
 * @brief : Fota升级处理函数，将接收的数据进行校验，搬运至升级区域，并进行应答
 * @param {UINT8} *DataPtr
 * @param {INT32} connectId
 * @return {*}
 */
void Fota_Func(uint8 *DataPtr, sint32 connectId)
{
	static uint32 currentAddr = 0;
    Fota_Type Fota_S;
    uint8 Fota_Answer[43];
    uint8 Fota_Cmd;
    sint8 ret;
    uint8 *Data_Read_Buffer = NULL;
    uint8 Data_Read_Crc;
    if (*(DataPtr + 30) == 0x01)
    {
        uint32 FlashAddStart = 0;
        uint32 appReceviedCRC;
        Hal_FlsGetAppVectorTableStartAddr(&FlashAddStart);
        Fota_S.Fota_Flash_Addres = FlashAddStart;
        Fota_Cmd = *(DataPtr + 31);
        Fota_Answer[0] = TCP_START_SYM1;
        Fota_Answer[1] = TCP_START_SYM2;
        Fota_Answer[2] = TCP_CONCMD_SYM;
        switch (Fota_Cmd)
        {
        case 0x01:
        {
            Fota_S.Fota_All_Data_Len = *(DataPtr + 33) << 24 | *(DataPtr + 34) << 16 | *(DataPtr + 35) << 8 | *(DataPtr + 36);
            Fota_S.Fota_Current_Addres = *(DataPtr + 37) << 24 | *(DataPtr + 38) << 16 | *(DataPtr + 39) << 8 | *(DataPtr + 40);
            if (Fota_S.Fota_All_Data_Len >= 0x7FE00)
            {
                Fota_Answer[3] = 0x02;
            }
            else
            {
                Fota_Answer[3] = 0x01;
                appReceviedCRC = (uint32)(*(DataPtr + 42) << 8 | *(DataPtr + 43));
                Hal_FlsErase(Fota_S.Fota_Flash_Addres, Fota_S.Fota_All_Data_Len, 5);
                Hal_SetAppInfo(Fota_S.Fota_All_Data_Len, appReceviedCRC, CONTROLLER_SELF);
            }
            memcpy(&Fota_Answer[4], (DataPtr + 4), BATT_SN_LEN);
            Fota_Answer[21] = TCP_ENCPT_DISABLE;
            Fota_Answer[22] = 0x00;
            Fota_Answer[23] = 0x12;
            memcpy(&Fota_Answer[24], (DataPtr + 24), 18);
            Fota_Answer[42] = bcc_chk_fota(Fota_Answer, 42);
            tcpipConnectionSend(connectId, Fota_Answer, 43);
            break;
        }
        case 0x02:
        {
            Fota_S.Fota_All_Data_Len = *(DataPtr + 33) << 24 | *(DataPtr + 34) << 16 | *(DataPtr + 35) << 8 | *(DataPtr + 36);
            Fota_S.Fota_Current_Addres = *(DataPtr + 37) << 24 | *(DataPtr + 38) << 16 | *(DataPtr + 39) << 8 | *(DataPtr + 40);
            currentAddr = Fota_S.Fota_Current_Addres;
            Fota_S.Fota_Recv_Data_Len = *(DataPtr + 41);
            Fota_S.Fota_Recv_DataPtr = (DataPtr + 42);
            Fota_S.Fota_CRC = Fota_crc_chk(Fota_S.Fota_Recv_DataPtr, Fota_S.Fota_Recv_Data_Len);
            if (Fota_S.Fota_CRC == *(DataPtr + Fota_S.Fota_Recv_Data_Len + 42))
            {
                uint8 Fota_Recv_Data_Len_8 = 0;
                if (Fota_S.Fota_Recv_Data_Len % FLS_INTERNAL_WRITE_SIZE != 0)
                {
                	Fota_Recv_Data_Len_8 = Fota_S.Fota_Recv_Data_Len + FLS_INTERNAL_WRITE_SIZE - (Fota_S.Fota_Recv_Data_Len % FLS_INTERNAL_WRITE_SIZE);
                }
                else
                {
                	Fota_Recv_Data_Len_8 = Fota_S.Fota_Recv_Data_Len;
                }
                Data_Read_Buffer = malloc(Fota_S.Fota_Recv_Data_Len);
                Hal_FlsWrite(Fota_S.Fota_Flash_Addres + Fota_S.Fota_Current_Addres, Fota_S.Fota_Recv_DataPtr, Fota_Recv_Data_Len_8, 100);
                memset(Data_Read_Buffer, 0x00, Fota_S.Fota_Recv_Data_Len);
                Hal_FlsRead(Fota_S.Fota_Flash_Addres + Fota_S.Fota_Current_Addres, Data_Read_Buffer, Fota_S.Fota_Recv_Data_Len, 100);
                Data_Read_Crc = Fota_crc_chk(Data_Read_Buffer, Fota_S.Fota_Recv_Data_Len);
                if (Data_Read_Crc == Fota_S.Fota_CRC)
                {
                    Fota_Answer[3] = 0x01;
                }
                else
                {
                    Fota_Answer[3] = 0x02;
//                    Hal_FlsErase(Fota_S.Fota_Flash_Addres + Fota_S.Fota_Current_Addres, Fota_Recv_Data_Len_8, 5);
                }
            }
            else //数据校验失败
            {
                Fota_Answer[3] = 0x02;
            }
            if (Data_Read_Buffer != NULL)
                free(Data_Read_Buffer);
            Data_Read_Buffer = NULL;
            memcpy(&Fota_Answer[4], (DataPtr + 4), BATT_SN_LEN);
            Fota_Answer[21] = TCP_ENCPT_DISABLE;
            Fota_Answer[22] = 0x00;
            Fota_Answer[23] = 0x12;
            memcpy(&Fota_Answer[24], (DataPtr + 24), 18);
            Fota_Answer[42] = bcc_chk_fota(Fota_Answer, 42);
            tcpipConnectionSend(connectId, Fota_Answer, 43);
            break;
        }
        case 0x03:
        {
            Fota_S.Fota_All_Data_Len = *(DataPtr + 33) << 24 | *(DataPtr + 34) << 16 | *(DataPtr + 35) << 8 | *(DataPtr + 36);
            Fota_S.Fota_Current_Addres = *(DataPtr + 37) << 24 | *(DataPtr + 38) << 16 | *(DataPtr + 39) << 8 | *(DataPtr + 40);
            Fota_Answer[3] = 0x01;
            memcpy(&Fota_Answer[4], (DataPtr + 4), BATT_SN_LEN);
            Fota_Answer[21] = TCP_ENCPT_DISABLE;
            Fota_Answer[22] = 0x00;
            Fota_Answer[23] = 0x12;
            memcpy(&Fota_Answer[24], (DataPtr + 24), 18);
            Fota_Answer[42] = bcc_chk_fota(Fota_Answer, 42);
            tcpipConnectionSend(connectId, Fota_Answer, 43);
            if (Fota_S.Fota_All_Data_Len == Fota_S.Fota_Current_Addres)
            {
                Hal_FlsCheckIsTransferSucceed();
                Fota_update_flag = TRUE;
            }
            else
            {
                Fota_update_flag = FALSE;
            }
            break;
        }
        default:
        {
            Fota_Answer[3] = 0x02;
            memcpy(&Fota_Answer[4], (DataPtr + 4), BATT_SN_LEN);
            Fota_Answer[21] = TCP_ENCPT_DISABLE;
            Fota_Answer[22] = 0x00;
            Fota_Answer[23] = 0x12;
            memcpy(&Fota_Answer[24], (DataPtr + 24), 18);
            Fota_Answer[42] = bcc_chk_fota(Fota_Answer, 42);
            tcpipConnectionSend(connectId, Fota_Answer, 43);
            break;
        }
        }
    }
}
/**
 * @brief : fota网络校验函数
 * @param {UINT8} *data
 * @param {UINT8} length
 * @return {*}
 */
static uint8 bcc_chk_fota(uint8 *data, uint8 length)
{
    uint8 bcc_chk_return = 0x00;
    uint8 count = 0;
    while (count < length)
    {
        bcc_chk_return ^= data[count];
        count++;
    }
    return bcc_chk_return;
}
/**
 * @brief : Fota校验函数
 * @param {UINT8} *data
 * @param {UINT8} length
 * @return {*}
 */
static uint8 Fota_crc_chk(uint8 *data, uint8 length)
{
    uint8 reg_crc = 0x00;
    while (length--)
    {
        reg_crc ^= *data++;
    }
    return reg_crc;
}
