// 网管中心模块
// 杭州秒寻科技有限公司
// 周涛
// 2023-10-12

#include "includes.h"

NMC_RECEIVE_BUFFER_T gNmc_stReceiveBuf = {0}; // 串口接收字符

// 初始化
uint8 nmc_init(void)
{
    uint8 byFlag = 0;

    byFlag = wifi_ble_init(); // wifi蓝牙模块初始化
    if (!byFlag)
    {
        return byFlag;
    }

    // 初始化全局变量
    SYS_MEMSET(&gNmc_stReceiveBuf, 0, sizeof(NMC_RECEIVE_BUFFER_T));

    return 1;
}

// NMC模块处理函数：负责从wifi串口读取数据
void nmc_process_func(void *pvPara)
{
    uint8 abyAtReadyFlag[7] = {0x72, 0x65, 0x61, 0x64, 0x79, 0x0D, 0x0A}; // AT模块启动信息

    // 响应成功帧
    uint8 abyAtRespOkFlag[6] = {0x0D, 0x0A, 0x4F, 0x4B, 0x0D, 0x0A}; // 成功响应帧\r\nOK\r\n

    // 响应失败帧
    uint8 abyAtRespErrHeadFlag[2] = {0x0D, 0x0A};                                                  // 失败响应帧头\r\n
    uint8 abyAtRespErrTailFlag[10] = {0x0D, 0x0A, 0x2B, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x0D, 0x0A}; // 失败响应帧尾\r\n+ERROR\r\n

    // 进入透传模式响应帧 ">"
    uint8 byAtRespTransFlag = 0x3E;

    // 模块广播事件帧头，"\r\n+EVENT:"
    uint8 abyRespEventHeadFlag[9] = {0x0D, 0x0A, 0x2B, 0x45, 0x56, 0x45, 0x4E, 0x54, 0x3A};

    pvPara = pvPara;

    // 从wifi串口接收数据(有可能是网管数据，也可能是WIFI模块AT命令的响应，还有可能是WIFI模块的事件通知)
    gNmc_stReceiveBuf.dwDataLen += driver_wifi_receive_data((uint8 *)&(gNmc_stReceiveBuf.abyDataBuf[gNmc_stReceiveBuf.dwDataLen]), NMC_FRAME_MAX_LEN - gNmc_stReceiveBuf.dwDataLen);

    if (gNmc_stReceiveBuf.dwDataLen > 0)
    {
        // 解析OAM帧
        nmc_oam_frame(&gNmc_stReceiveBuf);

        if (!gNmc_stReceiveBuf.byTransparentFlag)
        {
            // wifi模块启动帧(模块上电就会输出，这里抓不到启动信息)
            // nmc_at_start_info(&gNmc_stReceiveBuf, abyAtReadyFlag);

            // 解析AT命令响应成功帧
            nmc_at_resp_ok(&gNmc_stReceiveBuf, abyAtRespOkFlag);

            // 解析AT命令响应失败帧
            nmc_at_resp_error(&gNmc_stReceiveBuf, abyAtRespErrHeadFlag, abyAtRespErrTailFlag);

            // 解析进入透传模式的响应字符“>\r\n”
            nmc_at_resp_transparent(&gNmc_stReceiveBuf, byAtRespTransFlag);
        }

        // 解析模块广播事件
        nmc_at_resp_event(&gNmc_stReceiveBuf, abyRespEventHeadFlag, abyAtRespErrHeadFlag);
    }
}

// OAM管理帧
void nmc_oam_frame(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer)
{
    uint16 head = 0;      // 帧头索引
    uint16 tail = 0;      // 帧尾索引
    uint16 wFrameLen = 0; // 帧长 = tail - head + 1
    uint8 byExist = 0;
    uint16 wStopIndex = 0;

    // 帧长合法
    if (pstNmcReceiveBuffer->dwDataLen > UDP_FRAME_MIN_LEN)
    {
        // 找帧头
        wStopIndex = pstNmcReceiveBuffer->dwDataLen - 1;
        for (uint16 i = 0; i < pstNmcReceiveBuffer->dwDataLen; i++)
        {
            if (i < wStopIndex)
            {
                if (pstNmcReceiveBuffer->abyDataBuf[i] == PS_AP_HEAD_FLAG && pstNmcReceiveBuffer->abyDataBuf[i + 1] != PS_AP_HEAD_FLAG)
                {
                    head = i;
                    byExist = 1;
                    break;
                }
            }
            else
            {
                if (pstNmcReceiveBuffer->abyDataBuf[i] == PS_AP_HEAD_FLAG)
                {
                    head = i;
                    byExist = 1;
                    break;
                }
            }
        }

        // 找到了帧头
        if (byExist)
        {
            // 找帧尾
            byExist = 0;
            for (uint16 j = head + 1; j < pstNmcReceiveBuffer->dwDataLen; j++)
            {
                if (pstNmcReceiveBuffer->abyDataBuf[j] == PS_AP_TAIL_FLAG)
                {
                    tail = j;
                    byExist = 1;
                    break;
                }
            }

            // 找到了帧尾
            if (byExist)
            {
                wFrameLen = tail - head + 1;       // 计算帧长
                if (wFrameLen > UDP_FRAME_MIN_LEN) // 帧长合法
                {
                    // 把消息送到协议栈
                    ps_receive_data_from_outsite(&pstNmcReceiveBuffer->abyDataBuf[head], PS_SOURCE_CENTER, wFrameLen);
                }

                // 队列处理
                pstNmcReceiveBuffer->dwDataLen -= (tail + 1); // 剩余数据长度
                nmc_parse_backward(pstNmcReceiveBuffer->abyDataBuf, tail, pstNmcReceiveBuffer->dwDataLen);
            }
        }
    }

    return;
}

// wifi模块启动默认细腻些
void nmc_at_start_info(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer, uint8 *pbyAtReadyFlag)
{
    uint8 *pbyData = pstNmcReceiveBuffer->abyDataBuf;
    uint16 wdataListLen = pstNmcReceiveBuffer->dwDataLen;

    int16 i = 0;
    int16 head = 0;
    int16 tail = 0;

    uint8 byExist = 0;
    int16 wFrameLen = 0;
    int16 wBackHalfLen = 0; // 后半部队列长度

    // AT命令成功响应ready\r\n
    if (wdataListLen > 7)
    {
        i = 0;
        tail = 0;

        // 确定帧在队列中的位置
        for (i = 0; i <= wdataListLen - 5; i++)
        {
            byExist = 0;
            for (uint8 j = 0; j < 5; j++)
            {
                if (pbyAtReadyFlag[j] == pbyData[i + j])
                {
                    if (!byExist)
                    {
                        byExist = 1;
                        tail = i;
                    }
                }
                else
                {
                    byExist = 0;
                    tail = 0;
                    break;
                }
            }
        }

        // 找到模块启动帧
        if (byExist)
        {
            wFrameLen = tail + 1;                        // 当前帧长
            pstNmcReceiveBuffer->dwDataLen -= wFrameLen; // 调整队列长度

            // 队列剩余长度
            wBackHalfLen = GUI_FRAME_MAX_LEN - wFrameLen;
            if (wBackHalfLen > 0)
            {
                // 移动后续队列数据
                SYS_MEMMOVE((void *)pstNmcReceiveBuffer->abyDataBuf, (void *)&pstNmcReceiveBuffer->abyDataBuf[tail + 1], wBackHalfLen);
            }
            else
            {
                SYS_MEMSET(pstNmcReceiveBuffer->abyDataBuf, 0, GUI_FRAME_MAX_LEN);
                pstNmcReceiveBuffer->dwDataLen = 0;
            }
        }
    }
}

// AT命令响应成功帧同步
void nmc_at_resp_ok(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer, uint8 *pbyFrameFlag)
{
    uint8 *pbyData = pstNmcReceiveBuffer->abyDataBuf;
    uint16 wdataListLen = pstNmcReceiveBuffer->dwDataLen;

    int16 i = 0;
    int16 head = 0;
    int16 tail = 0;

    uint8 byExist = 0;
    int16 wFrameLen = 0;

    // AT命令成功响应\r\nOK\r\n
    if (wdataListLen >= 6)
    {
        i = 0;
        tail = 0;

        // 确定帧尾在队列中的位置
        for (i = 0; i <= wdataListLen - 6; i++)
        {
            byExist = 0;
            for (uint8 j = 0; j < 6; j++)
            {
                if (pbyFrameFlag[j] == pbyData[i + j])
                {
                    if (!byExist)
                    {
                        byExist = 1;
                        tail = i;
                    }
                }
                else
                {
                    byExist = 0;
                    tail = 0;
                    break;
                }
            }
        }

        // 找到响应Ok帧尾
        if (byExist)
        {
            // 如果是查询命令的响应，则向前查找响应帧的帧头
            byExist = 0;
            for (int16 k = (tail - 1); k > 0; k--)
            {
                if (pbyData[k] == pbyFrameFlag[1] && pbyData[k - 1] == pbyFrameFlag[0])
                {
                    byExist = 1;
                    head = k - 1;
                    break;
                }
            }

            if (!byExist)
            {
                head = tail;
            }
            tail += 5; // 帧尾

            // 帧合法
            if (tail > head)
            {
                // 把消息送到蓝牙命令响应消息处理函数
                ble_resp_ok(&pbyData[head]);

                // 调整帧长度
                pstNmcReceiveBuffer->dwDataLen -= (tail + 1);
                nmc_parse_backward(pstNmcReceiveBuffer->abyDataBuf, tail, pstNmcReceiveBuffer->dwDataLen);
            }
        }
    }

    return;
}

// AT命令响应失败帧同步
void nmc_at_resp_error(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer, uint8 *pbyFrameHeadFlag, uint8 *pbyFrameTailFlag)
{
    uint8 *pbyData = pstNmcReceiveBuffer->abyDataBuf;
    uint16 wdataListLen = pstNmcReceiveBuffer->dwDataLen;

    int16 i = 0;
    int16 head = 0;
    int16 tail = 0;

    uint8 byExist = 0;
    int16 wFrameLen = 0;

    // AT命令错误响应帧格式\r\n<CMD>:<error_code>\r\n+ERROR\r\n，最小帧长12
    if (wdataListLen > 12)
    {
        i = 0;
        tail = 0;

        // 确定帧尾在队列中的起始位置，\r\n+ERROR\r\n
        for (i = 0; i <= wdataListLen - 10; i++)
        {
            byExist = 0;
            for (uint8 j = 0; j < 10; j++)
            {
                if (pbyFrameTailFlag[j] == pbyData[i + j])
                {
                    if (!byExist)
                    {
                        byExist = 1;
                        tail = i;
                    }
                }
                else
                {
                    byExist = 0;
                    tail = 0;
                    break;
                }
            }
        }

        // 找到了ERROR帧的帧尾
        if (byExist)
        {
            // 如果是查询命令的响应，则向前查找响应的帧头
            byExist = 0;
            for (int16 k = (tail - 1); k > 0; k--)
            {
                if (pbyData[k] == pbyFrameHeadFlag[1] && pbyData[k - 1] == pbyFrameHeadFlag[0])
                {
                    byExist = 1;
                    head = k - 1;
                    break;
                }
            }

            // 找到帧头
            if (byExist)
            {
                // 帧合法
                if (tail > head)
                {
                    // 把消息送到蓝牙命令响应消息处理函数
                    ble_resp_err(&pbyData[head]);

                    // 调整帧长度
                    pstNmcReceiveBuffer->dwDataLen -= (tail + 1);
                    nmc_parse_backward(pstNmcReceiveBuffer->abyDataBuf, tail, pstNmcReceiveBuffer->dwDataLen);
                }
            }
        }
    }

    return;
}

// 进入透传模式响应字符解析
void nmc_at_resp_transparent(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer, uint8 byFrameFlag)
{
    uint8 *pbyData = pstNmcReceiveBuffer->abyDataBuf;
    uint16 wdataListLen = pstNmcReceiveBuffer->dwDataLen;

    int16 i = 0;
    int16 head = 0;
    int16 tail = 0;

    uint8 byExist = 0;
    int16 wFrameLen = 0;

    // 进入透传响应帧格式">"
    if (wdataListLen > 0)
    {
        // 确定帧在队列中的起始位置，>\r\n
        for (i = 0; i < wdataListLen; i++)
        {
            if (pbyData[i] == byFrameFlag)
            {
                byExist = 1;
                head = i;
                tail = i;

                gNmc_stReceiveBuf.byTransparentFlag = 1; // socket进入透传模式
                break;
            }
        }

        // 找到了进入透传模式响应帧
        if (byExist)
        {
            // 把消息送到wifi蓝牙模块命令响应成功消息处理函数
            ble_resp_ok(&pbyData[head]);

            // 调整帧长度
            pstNmcReceiveBuffer->dwDataLen -= tail + 1;
            nmc_parse_backward(pstNmcReceiveBuffer->abyDataBuf, tail, pstNmcReceiveBuffer->dwDataLen);
        }
    }
    return;
}

// wifi蓝牙模块事件通知解析
void nmc_at_resp_event(NMC_RECEIVE_BUFFER_T *pstNmcReceiveBuffer, uint8 *pbyFrameHeadFlag, uint8 *pbyFrameTailFlag)
{
    uint8 *pbyData = pstNmcReceiveBuffer->abyDataBuf;
    uint16 wdataListLen = pstNmcReceiveBuffer->dwDataLen;

    int16 i = 0;
    int16 head = 0;
    int16 tail = 0;

    uint8 byExist = 0;
    int16 wFrameLen = 0;

    // event帧
    if (wdataListLen > 11)
    {
        i = 0;
        tail = 0;

        // 确定帧头在队列中的位置，\r\n+EVENT:
        for (i = 0; i <= wdataListLen - 9; i++)
        {
            byExist = 0;
            for (uint8 j = 0; j < 9; j++)
            {
                if (pbyData[i + j] == pbyFrameHeadFlag[j])
                {
                    if (!byExist)
                    {
                        head = i;
                        byExist = 1;
                    }
                }
                else
                {
                    head = 0;
                    byExist = 0;
                    break;
                }
            }

            // 找到帧头
            if (byExist)
            {
                break;
            }
        }

        // 找到帧头
        if (byExist)
        {
            // 找帧尾
            byExist = 0;
            for (int16 k = (head + 1); k < wdataListLen - 1; k++)
            {
                if (pbyData[k] == pbyFrameTailFlag[0] && pbyData[k + 1] == pbyFrameTailFlag[1])
                {
                    byExist = 1;
                    tail = k + 1;
                    break;
                }
            }

            // 找到帧尾
            if (byExist)
            {
                // 帧合法
                if (tail > head)
                {
                    // 把消息送到蓝牙命令响应消息处理函数
                    ble_event_main(&pbyData[head]);

                    // 调整帧长度
                    pstNmcReceiveBuffer->dwDataLen -= tail + 1;
                    nmc_parse_backward(pstNmcReceiveBuffer->abyDataBuf, tail, pstNmcReceiveBuffer->dwDataLen);
                }
            }
        }
    }
    return;
}

// 帧解析后向处理
// pbyData:数据队列
// wTail:上一帧的帧尾
// wLen:上一帧剩余数据长度
void nmc_parse_backward(uint8 *pbyData, uint16 wTail, uint16 wLen)
{
    if (wLen <= 0)
    {
        SYS_MEMSET(pbyData, 0, NMC_FRAME_MAX_LEN); // 队列置零
    }
    else
    {
        SYS_MEMCPY((void *)pbyData, (void *)&pbyData[wTail + 1], wLen); // 拷贝队列剩余数据
        SYS_MEMSET(&pbyData[wLen], 0, NMC_FRAME_MAX_LEN - wLen);        // 队列置零
    }

    return;
}

// NMC模块将数据发送到wifi模块
// pbyData:数据
// wLen:数据长度
void nmc_send_data_to_wifi(uint8 *pbyData, uint16 wLen)
{
    uint8 byFlag = 0;

    // 数据容错处理
    if (pbyData == NULL || wLen <= 0)
    {
        return;
    }

    byFlag = driver_wifi_send_data(pbyData, wLen);
    if (!byFlag)
    {
        return;
    }

    return;
}

// 重置透传模式
void nmc_reset_transparent_mode()
{
    gNmc_stReceiveBuf.byTransparentFlag = 0;
}