/*
 * @Author       : stark1898y 1658608470@qq.com
 * @Date         : 2024-12-15 15:01:15
 * @LastEditors  : stark1898y 1658608470@qq.com
 * @LastEditTime : 2025-02-24 17:58:40
 * @FilePath     : \BLE_TYQ_CH584M\BSP\src\bsp_valve.c
 * @Description  :
 *
 * Copyright (c) 2024 by yzy, All Rights Reserved.
 */
#include "bsp_valve.h"
#include "bsp_motor.h"
// 0xAA CMD/DATA/ DATA_LEN (DATA) checksum 0x55

#include "bsp_uart.h"
#include "log.h"
#include "peripheral.h"
#include "SLEEP.h"
#include "bsp_adc.h"
#include "bsp_led.h"
#include "bsp_bmp390.h"            

#undef LOG_ENABLE
#define LOG_ENABLE 1

// #undef LOG_TAG
// #define LOG_TAG "BSP_VALVE"

TsValveData gValveData = {0};
TsRawFrameData RelyData;

tmosTaskID vavle_task_id = INVALID_TASK_ID;

#define ARRAY_SIZE(freq_arr) (sizeof(freq_arr) / sizeof((freq_arr)[0]))

/**
 * @description: From the frame start character to the sum of all bytes before the check code, modulo 256, i.e., the binary arithmetic sum of each byte without overflow value exceeding 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;
}

TsFrameData *BSP_VAVLE_GetFrameData(uint8_t *data, uint8_t len) // 获取阀门数据帧函数
{
    int ret        = 0;
    uint16_t index = 0;

    TsFrameData *get_buffer = NULL;

    if (len < 4)
    {
        logError("Data frame length insufficient");
        return NULL;
    }
    while (index < len && data[index] != FRAME_HEADER)
    {
        index++;
    }
    if (index >= len - 3)
    {
        logError("Data frame header error");
        return NULL;
    }
    uint16_t data_len = data[index + 2];
    if (index + 3 + data_len + 1 >= len)
    {
        logError("Data frame length error");
        return NULL;
    }

    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("Data frame checksum error check_sum = %02X, calculated_sum = %02X", check_sum, calculated_sum);
        return NULL;
    }
    if (data[index + 3 + data_len + 1] != FRAME_TAIL)
    {
        logError("Data frame tail error");
        return NULL;
    }
    logDebug("Data frame verification passed");

    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) // 生成原始帧函数
{
    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);

    pRawData->buf[pRawData->len - 2] = CheckSum(&pRawData->buf[0], pRawData->len - 2);
    pRawData->buf[pRawData->len - 1] = FRAME_TAIL;

    return 0;
}

void BSP_VALVE_Generate_UploadData(TsRawFrameData *pRawData) // 生成上传数据函数
{
    GenerateRawFrame(pRawData, kCmdData, (uint8_t *)&gValveData, sizeof(gValveData));
}

void BSP_VALVE_Generate_Data(TsRawFrameData *pRawData, uint8_t switch_status, uint8_t bat, int8_t temp, uint8_t humi) // 生成阀门数据函数
{
    TsValveData ValveData;

    ValveData.switch_status = 0;
    ValveData.temp          = temp;

    ValveData.in_pressure  = 0;
    ValveData.out_pressure = 0;
    ValveData.atm_pressure = 0;

    ValveData.type = kTyq;
    ValveData.bat  = bat;
    ValveData.humi  = humi;

    ValveData.rssi = 0;

    GenerateRawFrame(pRawData, kCmdData, (uint8_t *)&ValveData, sizeof(ValveData));
}

void BSP_VALVE_Generate_ValveResponse(TsRawFrameData *pRawData, TeFrameCmd cmd, uint8_t status) // 生成阀门响应函数
{
    uint8_t data = 0;
    data         = status;
    GenerateRawFrame(pRawData, cmd, &data, 1);
}

static void VAVLE_Task_ProcessTmosMsg(uint8_t *p_rev_msg) // 处理TMOS消息函数
{
    if (p_rev_msg)
    {
#if 1
        TsFrameData *HostFrameData = BSP_VAVLE_GetFrameData(&p_rev_msg[1], p_rev_msg[0]);
        if (HostFrameData != NULL)
        {
            switch (HostFrameData->cmd)
            {
                case kCmdCfg:          // 配置命令
                    logDebug("kCmdCfg");
                    break;
                case kCmdCloseVavle:   // 关阀命令
                    logDebug("kCmdCloseVavle");
                    tmos_set_event(vavle_task_id, VAVLE_CLOSE_START_EVT);

                    break;

                case kCmdOpenVavle:    // 开阀命令
                    logDebug("kCmdOpenVavle");
                    tmos_set_event(vavle_task_id, VAVLE_OPEN_START_EVT);
                    break;
                default:
                    logError("Invalid command");
                    break;
            }
        }
        else
        {
            logError("Data frame parsing failed");
        }
        tmos_msg_deallocate((uint8_t *)HostFrameData);
        HostFrameData = NULL;
#endif
    }
    else
    {
        logError("pMsg is NULL");
    }
}

static uint16_t VAVLE_Task_ProcessEvent(uint8_t task_id, uint16_t events) // 阀门任务事件处理函数
{
    if (events & SYS_EVENT_MSG)        // 系统消息事件
    {
        uint8_t *p_rev_msg;
        if ((p_rev_msg = tmos_msg_receive(vavle_task_id)) != NULL)
        {
            VAVLE_Task_ProcessTmosMsg(p_rev_msg);
            tmos_msg_deallocate(p_rev_msg);
        }
        return (events ^ SYS_EVENT_MSG);
    }
    if (events & VAVLE_RX_DATA_EVT)    // 阀门接收数据事件
    {
        logDebug("VAVLE_RX_DATA_EVT");

        return (events ^ VAVLE_RX_DATA_EVT);
    }
    if (events & VAVLE_TX_DATA_EVT)    // 阀门发送数据事件
    {
        logDebug("VAVLE_TX_DATA_EVT");

        return (events ^ VAVLE_TX_DATA_EVT);
    }
    if (events & VAVLE_CLOSE_START_EVT) // 阀门关闭开始事件
    {
        logDebug("VAVLE_CLOSE_START_EVT");

        BSP_BlockSleep();
        LED_VALVE_CLOSE;
        // DelayUs(200);

        VALVE_STOP();

        logDebug("MOTOR_INIT");

        tmos_start_task(vavle_task_id, VAVLE_CLOSE_ACTION_EVT, MS1_TO_SYSTEM_TIME(200));

        return (events ^ VAVLE_CLOSE_START_EVT);
    }
    if (events & VAVLE_CLOSE_ACTION_EVT) // 阀门关闭动作事件
    {
        BSP_BlockSleep();
        logDebug("VAVLE_CLOSE_ACTION_EVT");

        VALVE_CLOSE();

        logDebug("VALVE_CLOSE");

        tmos_start_task(vavle_task_id, VAVLE_CLOSE_END_EVT, MS1_TO_SYSTEM_TIME(CHARGE_TIME_MS));

        return (events ^ VAVLE_CLOSE_ACTION_EVT);
    }
    if (events & VAVLE_CLOSE_END_EVT)  // 阀门关闭结束事件
    {
        VALVE_STOP();
        LED_ALL_CLOSE;

        tmos_memset(&RelyData, 0, sizeof(RelyData));
        BSP_VALVE_Generate_ValveResponse(&RelyData, kCmdCloseVavle, 1);

        tmos_set_event(Peripheral_TaskID, SBP_REPLY_CMD_EVT);

        BSP_RequestSleep();
        logDebug("VAVLE_CLOSE_END_EVT");
        return (events ^ VAVLE_CLOSE_END_EVT);
    }
    
    if (events & VAVLE_OPEN_START_EVT)    // 阀门打开开始事件
    {
        logDebug("VAVLE_OPEN_START_EVT");
        
        BSP_BlockSleep();
        LED_VALVE_OPEN;
        // DelayUs(200);
        
        VALVE_STOP();
        
        logDebug("MOTOR_INIT");
        
        tmos_start_task(vavle_task_id, VAVLE_OPEN_ACTION_EVT, MS1_TO_SYSTEM_TIME(200));
        
        return (events ^ VAVLE_OPEN_START_EVT);
    }
    
    if (events & VAVLE_OPEN_ACTION_EVT)    // 阀门打开动作事件
    {
        BSP_BlockSleep();
        logDebug("VAVLE_OPEN_ACTION_EVT");
        
        VALVE_OPEN();
        keydown_flag = 1;
        logDebug("VALVE_OPEN");
        
        tmos_start_task(vavle_task_id, VAVLE_OPEN_END_EVT, MS1_TO_SYSTEM_TIME(CHARGE_TIME_MS));
        
        return (events ^ VAVLE_OPEN_ACTION_EVT);
    }
    
    if (events & VAVLE_OPEN_END_EVT)    // 阀门打开结束事件
    {
        VALVE_STOP();
        LED_ALL_CLOSE;
        
        tmos_memset(&RelyData, 0, sizeof(RelyData));
        BSP_VALVE_Generate_ValveResponse(&RelyData, kCmdOpenVavle, 1);
        
        tmos_set_event(Peripheral_TaskID, SBP_REPLY_CMD_EVT);
        BSP_RequestSleep();
        logDebug("VAVLE_OPEN_END_EVT");
        return (events ^ VAVLE_OPEN_END_EVT);
    }
    
    if (events & VAVLE_LOOP_DECT_EVT)    // 循环检测事件
    {
        logDebug("VAVLE_LOOP_DECT_EVT");

        gValveData.bat = BSP_ReadVbat();
        logDebug("BSP_ReadVbat %d",gValveData.bat);

        // 电压过低就关阀
        if (gValveData.bat <= LOW_VABAT_CLOSE_VALUE)
        {
            logDebug("gValveData.switch_status %d",gValveData.switch_status);
            if(gValveData.switch_status != kClosed)
            {
            tmos_set_event(vavle_task_id, VAVLE_CLOSE_START_EVT);
            }
        }
        else if (gValveData.bat <= LOW_VABAT_ALARM_VALUE)
        {
            tmos_set_event(vavle_task_id, VAVLE_LOW_VBAT_ALARM_EVT);
        }
        tmos_start_task(vavle_task_id, VAVLE_LOOP_DECT_EVT, MS1_TO_SYSTEM_TIME(VALVE_DECT_PERIOD_MS));

        return (events ^ VAVLE_LOOP_DECT_EVT);
    }

    if (events & VAVLE_LOW_VBAT_ALARM_EVT)  // 低电压报警事件
    {
        gValveData.bat = BSP_ReadVbat();
        if (gValveData.bat > 25)
        {
            return (events ^ VAVLE_LOW_VBAT_ALARM_EVT);
        }
        logDebug("VAVLE_LOW_VBAT_ALARM_EVT");  

        BSP_BlockSleep();            
        LED_VBAT_OPEN;

        tmos_start_task(vavle_task_id, VAVLE_LOW_VBAT_LED_OFF_EVT, MS1_TO_SYSTEM_TIME(500));

        tmos_start_task(vavle_task_id, VAVLE_LOW_VBAT_ALARM_EVT, MS1_TO_SYSTEM_TIME(5000));  // VALVE_LOW_VBAT_ALARM_PERIOD_MS

        // tmos_set_event(vavle_task_id, VAVLE_CLOSE_START_EVT);  // 设置阀门关闭开始事件

        // tmos_start_task(vavle_task_id, VAVLE_LOW_VBAT_ALARM_EVT, MS1_TO_SYSTEM_TIME(VALVE_LOW_VBAT_ALARM_PERIOD_MS));  // 启动低电压报警事件，延时一段时间

        return (events ^ VAVLE_LOW_VBAT_ALARM_EVT);  
    }
    if (events & VAVLE_LOW_VBAT_LED_OFF_EVT) // 低电压LED关闭事件
    {
        LED_VBAT_CLOSE;
        BSP_RequestSleep();         
        return (events ^ VAVLE_LOW_VBAT_LED_OFF_EVT);
    }

    return 0;
}

void BSP_VAVLE_Init(void)  // 阀门初始化函数
{
    vavle_task_id = TMOS_ProcessEventRegister(VAVLE_Task_ProcessEvent);
    tmos_memset(&gValveData, 0, sizeof(gValveData));

    gValveData.temp = -100;
    gValveData.in_pressure = 0;
    gValveData.out_pressure = 0;
    gValveData.atm_pressure = 0;

    gValveData.type = kTyq;            // 设置阀门类型
    gValveData.bat = BSP_ReadVbat();   // 读取电池电压

    BSP_MOTOR_Init();                  // 初始化电机

    tmos_start_task(vavle_task_id, VAVLE_LOOP_DECT_EVT, MS1_TO_SYSTEM_TIME(1000));  //VALVE_DECT_PERIOD_MS

    logInfo("BSP_Valve_Init");
}
