/*
 * @Author: mbw
 * @Date: 2024-12-03 10:31:45
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2025-05-09 16:48:18
 * @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_bt.c
 * @Description: 
 * 
 * Copyright (c) 2025 by ${git_name_email}, All Rights Reserved. 
 */
#include "bsp_bt.h"
#include "bsp_ml307.h"
#include "bsp_flash.h"
#include "rtdef.h"
#include "lwrb.h"
#include "finsh.h"
#include "user_sys.h"

#define LOG_TAG "bsp_bt"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>

#define BT_UART "uart5"

static rt_device_t rt_bt_device;

static struct rt_semaphore bt_rx_sem; //
struct rt_semaphore bt_ctr_sem;       // 控制阀门信号量
struct rt_semaphore bt_reg_sem;       // 注册阀门信号量
struct rt_semaphore bt_rem_sem;       // 移除阀门信号量
struct rt_semaphore bt_rep_sem;       // 更换阀门信号量

#define BT_THREAD_TIMESLICE  (20)
#define BT_THREAD_PRIORITY   (10)
#define BT_THREAD_STACK_SIZE (2048)

ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t bt_thread_stack[BT_THREAD_STACK_SIZE] = {0};
static struct rt_thread bt_thread                       = {0};

lwrb_t bt_lwrb_rx;
static char bt_rx_buffer[1024] = {0};
BTFrameData bt_frame           = {0};

valve_data valve[MAX_VALVE_NUM] = {0};

rt_size_t BSP_Bt_Send_Data(uint8_t *data, size_t size)
{
    return rt_device_write(rt_bt_device, 0, data, size);
}

rt_size_t BSP_Bt_Recv_Data(uint8_t *data, size_t size)
{
    return lwrb_read(&bt_lwrb_rx, data, size);
}

static rt_err_t bt_getchar(char *ch, rt_int32_t timeout)
{
    rt_err_t result = RT_EOK;

    while (rt_device_read(rt_bt_device, 0, ch, 1) == 0)
    {
        result = rt_sem_take(&bt_rx_sem, rt_tick_from_millisecond(timeout));
        if (result != RT_EOK)
        {
            return result;
        }
    }
    return RT_EOK;
}

static int bt_recv_readline(void)
{
    rt_size_t read_len = 0;
    char ch = 0, last_ch = 0;
    rt_bool_t is_full = RT_FALSE;

    while (1)
    {
        bt_getchar(&ch, RT_WAITING_FOREVER);
        if (read_len < lwrb_get_free(&bt_lwrb_rx))
        {
            lwrb_write(&bt_lwrb_rx, &ch, 1);
        }
        else
        {
            is_full = RT_TRUE;
        }
        if (ch == '\n' && last_ch == '\r')
        {
            if (is_full)
            {
                LOG_E("read line failed. The line data length is out of buffer size(%d)!", lwrb_get_free(&bt_lwrb_rx));
                return -RT_EFULL;
            }

            break;
        }
        last_ch = ch;
    }
    return lwrb_get_full(&bt_lwrb_rx);
}

/*发送数据帧处理*/
rt_uint8_t BT_GenerateRawFrame(BTFrameData *pRawData, const rt_uint8_t *p_src, rt_uint8_t src_len)
{
    pRawData->len = src_len + 4;

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

    pRawData->buf[0] = BT_FRAME_HEAD_DATA;
    pRawData->buf[1] = src_len;

    rt_memmove(&pRawData->buf[2], p_src, src_len);

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

    LOG_HEX("BTFrameData", 16, &pRawData->buf[0], pRawData->len);

    return RT_EOK;
}

/*用于控制阀门的状态
 * id: 1-8
 * mac_addr: 6字节
 * status: 0-关闭 1-打开
 */
int BSP_Bt_Valve_Ctr(rt_uint8_t id, rt_uint8_t *mac_addr, WireLessState status)
{
    rt_uint8_t ret = 0;

    BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 8);
    ptr->cmd      = kValveCmdCtr;
    ptr->buf[0]   = id;
    rt_memcpy(&ptr->buf[1], mac_addr, 6);
    ptr->buf[7] = status;
    BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 9);
    rt_free(ptr);

    ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len);
    if (ret == bt_frame.len)
    {
        return RT_EOK;
    }

    return RT_ERROR;
}

/*注册阀门信息*/
int BSP_Bt_Register_Valve(rt_uint8_t id, rt_uint8_t *mac_addr)
{
    rt_uint8_t ret = 0;
    BtData_t *ptr  = (BtData_t *)rt_malloc(sizeof(BtData_t) + 7);
    ptr->cmd       = kValveCmdReg;
    ptr->buf[0]    = id;
    rt_memcpy(&ptr->buf[1], mac_addr, 6);
    BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 8);
    rt_free(ptr);
    ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len);
    if (ret == bt_frame.len)
    {
        return RT_EOK;
    }

    return RT_ERROR;
}

/*移除阀门信息*/
int BSP_Bt_Remove_Valve(rt_uint8_t id, rt_uint8_t *mac_addr)
{
    rt_uint8_t ret = 0;

    BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 7);
    ptr->cmd      = kValveCmdRem;
    ptr->buf[0]   = id;
    rt_memcpy(&ptr->buf[1], mac_addr, 6);
    BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 8);
    rt_free(ptr);

    ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len);
    if (ret == bt_frame.len)
    {
        return RT_EOK;
    }

    return RT_ERROR;
}

/*移除所有阀门信息*/
int BSP_Bt_Remove_All_Valve(void)
{
    rt_uint8_t ret = 0;

    BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 7);
    ptr->cmd      = kValveCmdRemAll;
    ptr->buf[0]   = 0;
    BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 2);
    rt_free(ptr);

    ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len);
    if (ret == bt_frame.len)
    {
        return RT_EOK;
    }

    return RT_ERROR;
}

/*更换阀门信息*/
int BSP_Bt_Replace_Valve(rt_uint8_t id, rt_uint8_t *mac_addr, rt_uint8_t *new_mac_addr)
{
    rt_uint8_t ret = 0;

    BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 14);
    ptr->cmd      = kValveCmdRep;
    ptr->buf[0]   = id;
    rt_memcpy(&ptr->buf[1], mac_addr, 6);
    rt_memcpy(&ptr->buf[7], new_mac_addr, 6);
    BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, (sizeof(BtData_t) + 14));
    rt_free(ptr);

    ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len);
    if (ret == bt_frame.len)
    {
        return RT_EOK;
    }

    return RT_ERROR;
}

int Bt_Valve_Handler(ValveCmdType type, rt_uint8_t id, rt_uint8_t *data)
{
    int ret = RT_EOK;
    switch (type)
    {
        case kValveCmdCtr:                                                                       // 阀门控制
            ret = BSP_Bt_Valve_Ctr(id, &data[0], WirelessValveClose); // 关阀门
            break;
        case kValveCmdReg: // 阀门注册
            ret = BSP_Bt_Register_Valve(id, &data[0]);
            break;
        case kValveCmdRem: // 阀门移除
            ret = BSP_Bt_Remove_Valve(id, &data[0]);
            break;
        case kValveCmdRep: // 阀门更换
            ret = BSP_Bt_Replace_Valve(id, &data[0], &data[6]);
            break;
        case kValveCmdRemAll: // 阀门更换
        ret = BSP_Bt_Remove_All_Valve();
        break;
        default:
            ret = -RT_ERROR;
            LOG_E("unknown valve command type");
            break;
    }

    return ret;
}

int BSP_Bt_Process(uint8_t *data, uint16_t len)
{
    int ret               = 0;
    uint16_t index        = 0;
    rt_uint8_t end_index = 0;
    uint8_t data_buf[256] = {0};
    // 解析接收到的数据帧，先寻找AA开头，然后再找AA下一个字节，其代表了数据长度，然后找到代表长度的值的长度的下一位，其为校验码，校验码后为结束码0x55，
    // 如果数据正确，则提取数据，不正确，则不处理
    LOG_HEX("BT_RX_DATA", 16, data, len);
    LOG_D("len = %d", len);
    if (len < 4)
    { // 至少需要 4 个字节：起始码、长度、校验码、结束码
        LOG_E("长度不对 [1]");
        ;
        return 1;
    }
    while (index < len && data[index] != 0xAA) // 寻找起始码 0xAA
    {
        index++;
    }
    for (size_t i = 0; i < (len - 3); i++)//发现了一种情况，会出现两个AA，用这种方法排除一下
    {
        if (data[index + i + 1] == 0XAA)
        {
            index++;
        }
        else
        {
            break;
        }
    }
    while (end_index < len && data[end_index] != 0x55) // 寻找起始码 0xAA
    {
        end_index++;
    }
    uint16_t datalength = data[index + 1]; // 读取数据长度
    LOG_D("datalength = %d", datalength);

    uint8_t rx_sum         = data[index + 2 + datalength];               // 读取校验码
    uint8_t calculated_sum = XOR_CheckSum(&data[index], datalength + 2); // 计算校验码
    if (rx_sum != calculated_sum)
    {
        LOG_E("校验和不对 rx_sum[%02X] != calculated_sum[%02X]", rx_sum, calculated_sum);
        LOG_HEX("bt_rx_data:", 16, data, len);
        lwrb_reset(&bt_lwrb_rx);
        return 4;
    }

    if (data[index + 1 + datalength + 2] != data[end_index])// 检查结束码
    {
        LOG_E("结束码位置错误");
        LOG_HEX("bt_rx_data:", 16, data, len);
        lwrb_reset(&bt_lwrb_rx);
        return 5;
    }
    rt_uint8_t fram_len = datalength + 4;
    // 当程序走到这里时，就说明接收到了正确的数据帧，开始解析响应
    rt_memcpy(data_buf, &data[index], fram_len);
    switch (data[index + 2])
    {
        case kValveEventCtr:
            LOG_D("valve control event");
            if (data_buf[fram_len - 3] == WirelessValveClose) // 关闭成功
            {
                rt_sem_release(&bt_ctr_sem);
            }
            break;
        case kValveEventReg:
            if (data_buf[fram_len - 3] == RT_TRUE) // 注册成功)
            {
                LOG_I("接收到阀门注册响应:");
                LOG_HEX("bt_rx_data:", 16, data_buf, fram_len);

                rt_sem_release(&bt_reg_sem);
            }
            break;
        case kValveEventRem:
            if (data_buf[fram_len - 3] == RT_TRUE) // 移除成功
            {
                LOG_D("移除阀门响应成功");
                rt_sem_release(&bt_rem_sem);
            }
            break;
        case kValveEventRep:
            if (data_buf[fram_len - 3] == RT_TRUE) // 更换成功
            {
                LOG_D("阀门更换响应成功");
                rt_sem_release(&bt_rep_sem);
            }
            else
            {
                LOG_E("阀门更换失败");
            }
            break;
        case kValveEventRemAll:
            LOG_I("接收到移除所有阀门信息回应");
            LOG_HEX("bt_rx_data:", 16, data_buf, fram_len);
            if (data_buf[fram_len - 3] == RT_TRUE) // 移除成功
            {
                LOG_D("移除阀门响应成功");
                rt_sem_release(&bt_rem_sem);
            }
            break;
        case kValveEventStatus:
            LOG_I("接收到阀门心跳数据：");
            LOG_HEX("bt_rx_data:", 16, data_buf, fram_len);
            // TODO:添加阀门数据处理函数
            rt_memcpy(&valve[data_buf[3] - 1], &data_buf[3], sizeof(struct valve_t));
            LOG_HEX("valve_data:", 16, (rt_uint8_t *)&valve[data_buf[3] - 1], sizeof(struct valve_t));

            break;
        case kValveEventConnect:
            LOG_I("接收到阀门连接状态数据");
            LOG_HEX("bt_rx_data:", 16, data_buf, fram_len);
            
            rt_memcpy(&valve[data_buf[3] - 1], &data_buf[3], sizeof(struct valve_t) - 14);//只要前面的一部分数据，后面的不要
            LOG_HEX("valve_data:", 16, (rt_uint8_t *)&valve[data_buf[3] - 1], sizeof(struct valve_t));
            if(valve[data_buf[3] - 1].valve_connct_status == 1)
            {
                LOG_D("阀门连接");
                Ml307_Send_Event(kMl307ValveConnectEvent);
            }
            else
            {
                LOG_D("阀门断开");
                Ml307_Send_Event(KMl307ValveDisconnectEvent);
            }
            break;
        default:
            LOG_W("unknow cmd: %02X", data[index + 2]);
            break;
    }

    return ret;
}

static void BSP_Bt_Parse_Data(void)
{
    rt_size_t len = lwrb_get_full(&bt_lwrb_rx);
    char *rx_ptr  = rt_malloc(len + 1);
    // rt_uint8_t bt_rx_buf[256] = {0};

    BSP_Bt_Recv_Data((uint8_t *)rx_ptr, len);
    // 发送过来的数据格式为：帧头 + 数据长度 + 事件类型 + 数据 + 校验码 + 帧尾
    BSP_Bt_Process((uint8_t *)rx_ptr, len);
    rt_free(rx_ptr);
}

void BSP_Bt_Valve_Updata(void)
{
    uint8_t cnt    = 0;
    uint8_t mac[6] = {0};

    uint8_t num    = Flash_Get_Valve_Num();
    LOG_D("BSP_Bt_Valve_Updata num: %d ", num);
    if (num == 0)
    {
        return;
    }
    
    rt_memset(&valve[0], 0, sizeof(valve_data));
    
    for (int i = 1; i <= MAX_VALVE_NUM; i++) // 这个循环是为了将数据拷贝到valve_list中， 并且保证id号和flash对应起来
    {
        if (Flash_Get_Mac_Addr(mac, i) == RT_EOK) // 说明有MAC数据
        {
            rt_memcpy(valve[cnt].valve_mac, mac, 6); // 这样做的目的就是读取方便，只需要根据flash中读取到的数量进行读取前N个值
            valve[cnt].valve_id = i;
            LOG_D("updata valve_id: %d, valve_mac: %02X %02X %02X %02X %02X %02X",
                     valve[cnt].valve_id,
                     valve[cnt].valve_mac[0],
                     valve[cnt].valve_mac[1],
                     valve[cnt].valve_mac[2],
                     valve[cnt].valve_mac[3],
                     valve[cnt].valve_mac[4],
                     valve[cnt].valve_mac[5]);
            cnt++;
            break;
        }
        else
        {
            LOG_D("BSP_Bt_Valve_Updata: flash read error");
            break;
        }
    }
    Flash_Set_Valve_Num(cnt);
    
}


static void Bt_Thread_Entry(void *parameter)
{
#if 0
//    初始化阀门信息  测试用
    valve[0].valve_id     = 1;
    valve[0].valve_mac[0] = 0X93;
    valve[0].valve_mac[1] = 0xB4;
    valve[0].valve_mac[2] = 0x8F;
    valve[0].valve_mac[3] = 0x10;
    valve[0].valve_mac[4] = 0x53;
    valve[0].valve_mac[5] = 0x5C;

     Flash_Set_Mac_Addr(valve[0].valve_mac, 0);
     Flash_Set_Valve_Num(1);
#endif //0 

    BSP_Bt_Valve_Updata();
    lwrb_init(&bt_lwrb_rx, bt_rx_buffer, sizeof(bt_rx_buffer));
    lwrb_reset(&bt_lwrb_rx);

    LOG_D("Bt_Thread_Entry");
    while (1)
    {
        if (bt_recv_readline())
        {
            BSP_Bt_Parse_Data();
        }
    }
}

/* 接收数据回调函数 */
static rt_err_t Bt_Rcv_Cb(rt_device_t dev, rt_size_t size)
{
    rt_sem_release(&bt_rx_sem);

    return RT_EOK;
}

int BSP_Bt_Init(void)
{
    rt_err_t ret = RT_EOK;

    rt_sem_init(&bt_rx_sem, "bt_rx_sem", 0, RT_IPC_FLAG_PRIO); /* 接收来自蓝牙主机的信号量 */
    rt_sem_init(&bt_ctr_sem, "bt_ctr_sem", 0, RT_IPC_FLAG_PRIO);
    rt_sem_init(&bt_reg_sem, "bt_reg_sem", 0, RT_IPC_FLAG_PRIO);
    rt_sem_init(&bt_rem_sem, "bt_rem_sem", 0, RT_IPC_FLAG_PRIO);
    rt_sem_init(&bt_rep_sem, "bt_rep_sem", 0, RT_IPC_FLAG_PRIO);

    /* 查找系统中的串口设备 */
    rt_bt_device = rt_device_find(BT_UART);
    if (!rt_bt_device)
    {
        LOG_E("find %s failed!\n", BT_UART);
        return RT_ERROR;
    }
    /* 以中断接收模式打开串口设备 */
    if (rt_device_open(rt_bt_device, RT_DEVICE_FLAG_INT_RX) != RT_EOK)
    {
        LOG_E("rt_device_open failed!\n");
        return RT_ERROR;
    }
    /* 设置接收回调函数 */
    if (rt_device_set_rx_indicate(rt_bt_device, Bt_Rcv_Cb) != RT_EOK)
    {
        LOG_E("rt_device_set_rx_indicate failed!\n");
        
        return RT_ERROR;
    }
    /* 静态初始化线程 1*/
    ret = rt_thread_init(&bt_thread, // 该线程用于数据解析
                         "bt_thread",
                         Bt_Thread_Entry,
                         RT_NULL,
                         &bt_thread_stack[0],
                         sizeof(bt_thread_stack),
                         BT_THREAD_PRIORITY,
                         BT_THREAD_TIMESLICE);
    /* 创建成功则启动线程 */
    rt_thread_startup(&bt_thread);

    return ret;
}
// INIT_COMPONENT_EXPORT(BSP_Bt_Init);

#ifdef TEST_ENABLE
static void TEST_BT_Send_Data(int argc, char **argv)
{
    if (argc == 3)
    {
        int mode = atoi(argv[1]);
        int id   = atoi(argv[2]) - 1;
        switch (mode)
        {
            case 1:
                Bt_Valve_Handler(kValveCmdCtr, id, RT_NULL);
                break;
            case 2:
                Flash_Set_Valve_Num(1);
                Bt_Valve_Handler(kValveCmdReg, id, RT_NULL);
                break;
            case 3:
                Bt_Valve_Handler(kValveCmdRem, id, RT_NULL);
                rt_memset(valve[0].valve_mac, 0, sizeof(struct valve_t));
                Flash_Set_Mac_Addr(valve[0].valve_mac, 0);
                Flash_Set_Valve_Num(0);
                break;
            case 4:
                Bt_Valve_Handler(kValveCmdRep, id, RT_NULL);
                break;
            default:
                break;
        }
    }
}
MSH_CMD_EXPORT(TEST_BT_Send_Data, "TEST_BT_Send_Data");
#endif
