/*
 * @Author: mbw
 * @Date: 2024-12-09 11:40:10
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2025-01-02 14:44:19
 * @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 "CH58xBLE_LIB.h"
#include "bsp_uart.h"
#include "multiCentral.h"


/*
接收的蓝牙从机info：
接收数据帧格式： 帧头 + 命令 + 数据长度 + 心跳数据包 + 校验码 + 帧尾
发送数据帧格式： 帧头 + 命令 + 数据长度 + 控制数据 + 校验码 + 帧尾
*/

#undef LOG_ENABLE
#define LOG_ENABLE 1

#include "log.h"

valve_data_list_t valve_list = {0};
BTFrameData valve_frame_data = {0};


uint8_t Valve_GenerateRawFrame(BTFrameData *pRawData, const 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] = 0XAA;
    pRawData->buf[1] = cmd;
    pRawData->buf[2] = src_len;
    if (src_len > 0)
    {
        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] = 0X55;
    logInfo("向从机发送的数据:");
    logHexDumpAll(pRawData->buf, pRawData->len);

    return 0;
}

int BSP_Valve_Close(uint8_t valve_id)
{
    uint8_t num             = Flash_Get_Valve_Num();
    uint8_t valve_ctr_valve = WirelessValveClose;
    if ((valve_id > 8) && (num == 0))
    {
        logError("BSP_Valve_Close: valve id error");

        return -1;
    }
    logDebug("BSP_Valve_Close: valve id: %d", valve_id);
    //  TODO:检查是否连接， 如果连接，则发送数据，将关闭阀门指令发送过去,然后等待数据接收响应，如果接收到响应是关闭状态0x01，则返回成功，否则失败

    Valve_GenerateRawFrame(&valve_frame_data, kCmdCloseVavle, &valve_ctr_valve, 1);

    return BSP_Master_Send(centralConnList, CONNECT0_ITEM, &valve_frame_data.buf[0], valve_frame_data.len);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
                 BSP_Valve_Close, BSP_Valve_Close, "valve_id:CONNECT0_ITEM = 0");

/*用于控制阀门的状态
 * id: 1-8
 * mac_addr: 6字节
 * status: 0-关闭 1-打开
 */
int BSP_Bt_Valve_Ctr(uint8_t *data, uint8_t len)
{
    uint8_t mac_addr[FLASH_MAC_INFO_LEN] = {0};
    if ((data[0] >= 1) && (data[0] <= 8))
    {
        Flash_Get_Mac_Addr(mac_addr, data[0]);
    }
    else
    {
        logError("BSP_Bt_Valve_Ctr: id error");
        return -1;
    }
    if (tmos_memcmp(&data[1], mac_addr, FLASH_MAC_INFO_LEN) != TRUE)
    {
        logError("mac addr error read mac addr : %02X %02X %02X %02X %02X %02X != bt_rx mac addr: %02X %02X %02X %02X %02X %02X",
                 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], data[1], data[2], data[3], data[4], data[5], data[6]);

        return -2;
    }
    /*如果到这里了，说明ID和MAC地址对应没问题，则关闭对应阀门*/
    return BSP_Valve_Close(data[0]);
}

/*注册阀门信息*/
int BSP_Bt_Register_Valve(uint8_t *data, uint8_t len)
{
    uint8_t mac_addr[FLASH_MAC_INFO_LEN] = {0};

    if ((data[0] >= 1) && (data[0] <= 8))
    {
        Flash_Get_Mac_Addr(mac_addr, data[0]);
    }
    else
    {
        logError("valve id error");

        return 1;
    }
    if (tmos_isbufset(&data[1], 0, FLASH_MAC_INFO_LEN) == TRUE)
    {
        logError("阀门写值错误为0");
        return 1;
    }
    logDebug("注册阀门信息:");
    if (tmos_memcmp(&data[1], mac_addr, FLASH_MAC_INFO_LEN) == TRUE)
    {
        logError("已经注册过了");
        return 0; // 说明已经注册过了
    }
    else
    {
        if (tmos_isbufset(&mac_addr[0], 0xFF, 6) == TRUE) // 说明没有数据，那就全部写入
        {
            logDebug("没有数据，全部写入:");
            logDebug("写入MAC 地址: %02X %02X %02X %02X %02X %02X", data[1], data[2], data[3], data[4], data[5], data[6]);
            if (Flash_Set_Mac_Addr(&data[1], data[0]) != 0)
            {
                logError("阀门注册写入flash 错误");
                return 3;
            }
            else
            { 
                uint8_t num    = Flash_Get_Valve_Num();
                logDebug("num : %02X ",  num);
                Flash_Set_Valve_Num(num + 1);
                logDebug("写入成功，当前阀门数量为: %d", num + 1);
                BSP_Bt_Valve_Updata(); // 更新阀门信息
                
            }
        }
        else
        {
            logDebug("有数据 请检查");
        }
    }

    return 0;
}

/*移除阀门信息*/
int BSP_Bt_Remove_Valve(uint8_t *data, uint8_t len)
{
    size_t i                                 = 0;
    uint8_t mac_addr[FLASH_MAC_INFO_LEN + 2] = {0};
    if ((data[0] >= 1) && (data[0] <= 8))// 判断是否是正确的ID 
    {
        Flash_Get_Mac_Addr(mac_addr, data[0]);
    }
    else
    {
        logError("valve id error:");
        logHexDumpAll(data, len);
        return -1;
    }
    if (tmos_memcmp(&data[1], mac_addr, FLASH_MAC_INFO_LEN) != TRUE)// 判断是否是相同的MAC地址
    {
        logError("mac addr error");
         logHexDumpAll(data, len);
        return -2;
    }
    else
    {
        tmos_memset(mac_addr, 0xFF, FLASH_MAC_INFO_LEN);
        if (Flash_Set_Mac_Addr(mac_addr, data[0]) != 0) // 清空掉对应位置MAC数据
        {
            logError("移除阀门信息失败");
             logHexDumpAll(data, len);
            return -2;
        }
        uint8_t num    = Flash_Get_Valve_Num();
        if (Flash_Set_Valve_Num(num - 1) != 0) // 移除一个阀门
        {
            logError("移除阀门信息失败");
            logHexDumpAll(data, len);
            return -2;
        }
        BSP_Bt_Valve_Updata();
        Master_DisConnect();
    }

    return 0;
}

/*移除所有阀门信息*/
int BSP_Bt_Remove_All_Valve(void)
{
    uint8_t mac_addr[FLASH_MAC_INFO_LEN + 2] = {0};
    uint8_t num    = Flash_Get_Valve_Num();
    if(num == 0)
    {
        logError("没有找到任何阀门信息");
        return 0;
    }
    tmos_memset(mac_addr, 0xFF, FLASH_MAC_INFO_LEN);
    if (Flash_Set_Mac_Addr(mac_addr, 1) != 0)
    {
        logError("移除阀门信息失败[-2]");
        return -2;
    }
    if (Flash_Set_Valve_Num(0) != 0) // 移除一个阀门
    {
        logError("移除阀门信息失败[-3]");
        return -3;
    }
    BSP_Bt_Valve_Updata();
    Master_DisConnect();
    return 0;
}

/*更换阀门信息*/
int BSP_Bt_Replace_Valve(uint8_t *data, uint8_t len)
{
    size_t i                             = 0;
    uint8_t mac_addr[FLASH_MAC_INFO_LEN] = {0};
    logDebug("更换阀门信息:");
    logHexDumpAll(data, len);
    if ((len == 0) || (len < 13))//新旧MAC地址长度加id 6 + 6 + 1 = 13至少要大于12
    {
        logError("data len error");
        return -1;
    }
    if ((data[0] >= 1) && (data[0] <= 8))
    {
        Flash_Get_Mac_Addr(mac_addr, data[0]);
    }
    else
    {
        logError("valve id error");
        return -2;
    }
    if (tmos_memcmp(&data[1], mac_addr, FLASH_MAC_INFO_LEN) == TRUE)
    {
        logError("已经注册过了"); // 不需要重复写入
        return 0;                 // 说明已经注册过了
    }
    else
    {
        //新阀门数据在前
        if (Flash_Set_Mac_Addr(&data[1], data[0]) != 0)
        {
            logError("阀门注册写入flash 错误");
            return 3;
        }
        BSP_Bt_Valve_Updata(); // 更新阀门信息
        Master_DisConnect();//更新后先断联接
    }
    return 0;
}

/*更新阀门信息*/
void BSP_Bt_Valve_Updata(void)
{
    uint8_t cnt    = 0;
    __attribute__((aligned(4)))
    uint8_t mac[6] = {0};

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

int BSP_Bt_Valve_Resp(uint8_t cmd, uint8_t id, uint8_t *mac_addr, uint8_t state)
{
    uint8_t ret   = 0;
    BtData_t *ptr = (BtData_t *)tmos_msg_allocate(sizeof(struct valve_data));
    ptr->cmd      = cmd;
    switch (cmd)
    {
        case kValveCmdCtr:
        case kValveCmdReg:
        case kValveCmdRem:
        case kValveCmdRep:
            ptr->buf[0] = id;
            tmos_memcpy(&ptr->buf[1], mac_addr, 6);
            ptr->buf[7] = state;
            BT_GenerateRawFrame(&valve_frame_data, (uint8_t *)ptr, 9);
            break;
        case kValveCmdRemAll:
            ptr->buf[0] = state;
            BT_GenerateRawFrame(&valve_frame_data, (uint8_t *)ptr, 2);
            break;
        case kValveEventStatus:
            tmos_memcpy(&ptr->buf[0], &valve_list.valve_data[id - 1], sizeof(struct valve_data));
            BT_GenerateRawFrame(&valve_frame_data, (uint8_t *)ptr, sizeof(struct valve_data));
            break;
        default:
            break;
    }
    tmos_msg_deallocate((uint8_t *)ptr);
    ret = BSP_Uart1_Send_Data((uint8_t *)&valve_frame_data.buf[0], valve_frame_data.len);
    tmos_start_task(BtRxTaskId, BT_SEND_EVT, 50);
    if (ret == valve_frame_data.len)
    {
        return 0;
    }

    return -1;
}
 
void BSP_Valve_Init(void)
{
    logDebug("BSP_Valve_Init");
    BSP_Bt_Valve_Updata();
}
