/*
 * @Author: mbw
 * @Date: 2024-12-09 11:40:10
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2024-12-11 15:43:47
 * @FilePath: \ble_-tyq_-bjq_-ch584-m\bsp\src\bsp_valve.c
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
#include "bsp_valve.h"
#include "bsp_flash.h"
#include "bsp_uart.h"

#include "bsp_beep_led_emv.h"
// 0xAA CMD/DATA/ DATA_LEN (DATA) checksum 0x55


#include "log.h"

#undef LOG_ENABLE
#define LOG_ENABLE 0

#undef LOG_TAG
#define LOG_TAG "BSP_VALVE"



/**
 * @description: 从帧起始符开始到校验码之前所有字节的和的模256，即各字节不计超过255的溢出值的二进制算术和。
 * @param {uint8_t} *data
 * @param {uint16_t} len
 * @return {*}
 */
uint8_t CheckSum(const uint8_t *data, size_t len)
{
    uint8_t sum = 0;

    for (size_t i = 0; i < len; i++)
    {
        sum += data[i];
    }

    return sum;
}

#if 0
/**
 * @description: 从接收缓冲区中获取一帧有效数据
 * @param {TsFrameData} *pFrameData 主机帧
 * @param {uint8_t} *p_src      接收缓冲区
 * @param {uint16_t} src_len    接收缓冲区长度
 * @return {*}
 */
TsFrameData *HR_GetFrameData(const uint8_t *p_src, const uint8_t src_len)
{
    uint8_t data_field_len = 0;
    uint8_t check_sum      = 0;

    TsFrameData *get_buffer =  NULL;

    for (uint8_t i = 0; i < src_len; i++)
    {
        // 找帧头
        if (p_src[i] == FRAME_HEADER)
        {
            // 找数据长度
            data_field_len = p_src[i + 2];
            // 找帧尾
            if (p_src[i + 2 + data_field_len + 2] == FRAME_TAIL)
            {
                check_sum = CheckSum(&p_src[i], (3 + data_field_len));

                if (p_src[i + 2 + data_field_len + 1] == check_sum)
                {
                    get_buffer = (TsFrameData *)tmos_msg_allocate(sizeof(TsFrameData) + sizeof(uint8_t) * data_field_len);
                    if (get_buffer == NULL)
                    {
                        logError("tmos_msg_allocate fail");
                        return NULL;
                    }
                    get_buffer->cmd  = p_src[i + 1];
                    get_buffer->len = data_field_len;

                    if (data_field_len > 0)
                    {
                        tmos_memcmp(get_buffer->data, &p_src[i + 4], data_field_len);
                    }
                    logDebug("HR_GetDataFrame Success!");

                    return get_buffer;
                }
            }
        }
    }
    logError("HR_GetDataFrame Fail!");

    return get_buffer;
}
#endif

TsFrameData* BSP_VAVLE_GetFrameData(uint8_t *data, uint16_t len)
{
    int ret              = 0;
    uint16_t index       = 0;

    TsFrameData *get_buffer = NULL;
    // 解析接收到的数据帧，先寻找AA开头，然后再找AA下一个字节，其代表了数据长度，然后找到代表长度的值的长度的下一位，其为校验码，校验码后为结束码0x55，
    // 如果数据正确，则提取数据，不正确，则不处理
    if (len < 4)
    { // 至少需要 4 个字节：起始码、长度、校验码、结束码
        logError("数据帧长度不足");
        logHexDumpAll(data, len);
        // return 1;
    }
    while (index < len && data[index] != FRAME_HEADER) // 寻找起始码 0xAA
    {
        index++;
    }
    if (index >= len - 3) // 不够空间容纳长度、校验码和结束码
    {
        logError("数据帧起始码错误");
        logHexDumpAll(data, len);
        // return 2;
    }
    uint16_t data_len = data[index + 2]; // 读取数据长度
    if (index + 3 + data_len + 1 >= len) // 检查数据长度是否合理 数据长度 + 校验码 + 结束码
    {
        logError("数据帧长度错误");
        logHexDumpAll(data, len);
        // return 3;
    }

    uint8_t check_sum      = data[index + 3 + data_len];            // 读取校验码
    uint8_t calculated_sum = CheckSum(&data[index], data_len + 3);  // 计算校验码
    if (check_sum != calculated_sum)
    {
        logError("数据帧校验码错误 check_sum = %02X, calculated_sum = %02X", check_sum, calculated_sum);
        logHexDumpAll(data, len);
        // return 4;
    }
    if (data[index + 3 + data_len + 1] != FRAME_TAIL) // 检查结束码
    {
        logError("数据帧结束码错误");
        logHexDumpAll(data, len);
        // return 5;
    }
    logDebug("数据帧校验通过");

    get_buffer = (TsFrameData *)tmos_msg_allocate(sizeof(TsFrameData) + sizeof(uint8_t) * data_len);
    if (get_buffer == NULL)
    {
        logError("tmos_msg_allocate fail");
        return NULL;
    }

    get_buffer->cmd  = data[index + 1];
    get_buffer->len = data_len;
//    get_buffer->data = data;

    if (data_len > 0)
    {
        tmos_memcpy(get_buffer->data, &data[index + 3], data_len);
        return get_buffer;
    }

    // //有效数据长度
    // size_t data_len = (data_len + 5);
    // //到这一步说明数据没问题，将接收到的数据通过中心任务发送出去
    // uint8_t *p_data;
    // p_data = tmos_msg_allocate(data_len);
    // if (p_data)
    // {
    //     tmos_memcpy(p_data, data, data_len);
    //     tmos_msg_send(BtRxTaskId, p_data);
    //     tmos_start_task(BtRxTaskId, SYS_EVENT_MSG, 0);
    // }
}

uint8_t _GenerateRawFrame(TsRawFrameData *pRawData, uint8_t cmd, const uint8_t *p_src, uint8_t src_len)
{
    // 0xAA CMD/DATA/ DATA_LEN (DATA) checksum 0x55
    pRawData->len = src_len + 5;

    tmos_memset(pRawData->buf, 0, sizeof(pRawData->buf));

    pRawData->buf[0] = FRAME_HEADER;
    pRawData->buf[1] = cmd;
    pRawData->buf[2] = src_len;

    tmos_memcpy(&pRawData->buf[3], p_src, src_len);

    // 从帧起始符开始到校验码之前所有字节的和的模256
    // ，即各字节不计超过255的溢出值的二进制算术和。
    pRawData->buf[pRawData->len - 2] = CheckSum(&pRawData->buf[0], pRawData->len - 2);
    pRawData->buf[pRawData->len - 1] = FRAME_TAIL;

    logHexDumpAll(&pRawData->buf[0], pRawData->len);

    return 0;
}

void BSP_VALVE_Generate_Data(TsRawFrameData *pRawData, uint8_t bat, int8_t temp, uint8_t hum)
{
    TsValveData ValveData;

    ValveData.type = kTyq;  // 阀门类型
    ValveData.bat = bat;    // 电池电压 30=3V,18=1.8V
    ValveData.temp = temp;  // 阀门温度 有符号整数 25 ℃
    ValveData.hum = hum;    // 阀门湿度 %RH

    _GenerateRawFrame(pRawData, kCmdData, (uint8_t*)&ValveData, sizeof(ValveData));
    logHexDumpAll(&pRawData->buf[0], pRawData->len);
}

void BSP_VALVE_Generate_ValveResponse(TsRawFrameData *pRawData, TeFrameCmd cmd, uint8_t status)
{
    uint8_t data = 0;
    data = status;
    _GenerateRawFrame(pRawData, cmd, &data, 1);
    logHexDumpAll(&pRawData->buf[0], pRawData->len);
}

void BSP_CloseValve(void)
{
    // EMV_CHARGE
    EMV_CHARGE_EN;
    logDebug("EMV_CHARGE_EN");

    DelayMs(1000);

    EMV_CHARGE_OFF_DEINIT;
    logDebug("EMV_CHARGE_OFF_DEINIT 500 ms");

    // EMV_CTRL
    EMV_ON;
    logDebug("EMV_ON\n");
    DelayMs(100);
}

void BSP_VAVLE_Init(void)
{

    logInfo("BSP_Valve_Init");
}
