/******************************************************************************
 * @file      drv_qfc41d.c
 * @brief     drv_qfc41d driver
 * @version   V1.0
 * @author    Gary
 * @copyright
 ******************************************************************************/

#include "drv_qfc41d.h"
#include "eeprom_manager.h"

uint8_t rev_buff[QFC41D_MAX_RECV_SIZE] __attribute__((section(".ccmram")));
uint8_t send_buff[QFC41D_MAX_SEND_SIZE]__attribute__((section(".ccmram")));

#define MAX_PAYLOAD_LEN 128
char cmd[1000] = {0}; //降低栈空间使用

#define TX_DMA_BUFFER_SIZE 2000

volatile uint8_t dma_tx_busy = 0;
uint8_t dma_tx_buffer[2][TX_DMA_BUFFER_SIZE] __attribute__((section(".sram2")));
volatile uint8_t current_buffer = 0; // 0表示正常缓冲区，1表示高优先级缓冲区

extern char deviceSN[17];
extern char mqtt_topic_period[42];

//定义
WifiBleItem qfc41dItem = {
    .dev = QFC41D_UART_PORT,
    .buf_pos = 0,
    .buf_size = QFC41D_MAX_RECV_SIZE,
    .buf = rev_buff,
    .sendCall  = NULL,
};

typedef struct {
		uint16_t start_addr;
		uint16_t reg_num;
} RegSegment;
				
RegSegment segments[] = {
		{3000, 3},	//BMU个数，电芯总数，温感总数
		{3010, 1},	//Can通讯协议
		{3017, 1},  //设备地址
		{3041, 1},  //SOC
		{3068, 2},  //SOC满放校准电压，满充校准电压
		{3092, 1},  //充电末端降流电压
		{4000, 72}, //放电欠压值
		{4198, 72}  //充电过压值
};
const uint8_t segment_count = sizeof(segments) / sizeof(segments[0]);

void parse_mqtt_message(char* message) 
{
		// +QMTRECV: 0,31,"bluesun/bms/control/123",11,"MQ3156+1MQ"
		uint16_t first = 0;
		uint16_t second = 0;
		uint8_t buffer[5];  
		uint16_t length;      
		uint8_t data = 0;    
		char data_str[6] = {0};
	
    char* quotes[4] = {0};
    int quote_count = 0;
    for(char* p = message; *p && quote_count < 4; p++) 
		{
        if(*p == '\"') 
				{
            quotes[quote_count++] = p;
        }
    }
    
    if(quote_count < 4)
		{
        return;
    }
    
    char* payload_start = quotes[2] + 1;
    char* payload_end = quotes[3];
    size_t payload_len = payload_end - payload_start;
    
    if(payload_len >= MAX_PAYLOAD_LEN)
		{
        return;
    }
    
    char payload[MAX_PAYLOAD_LEN];
    strncpy(payload, payload_start, payload_len);
    payload[payload_len] = '\0';
    
    char* processed = payload;
    size_t len = strlen(processed);
    
    // 去除开头"MQ"
    if(len >= 2 && strncmp(processed, "MQ", 2) == 0)
		{
        processed += 2;
        len -= 2;
    }
    
    // 去除结尾"MQ"
    if(len >= 2 && strcmp(processed + len - 2, "MQ") == 0) 
		{
        processed[len - 2] = '\0';
        len -= 2;
    }

    char* plus_pos = strchr(processed, '+');
    if(!plus_pos) 
		{
        return;
    }
		
    *plus_pos = '\0'; 
    first = atoi(processed);
    second = atoi(plus_pos + 1);
		
		if(strstr(message, "control") != NULL)
    {
				buffer[0] = (second >> 8) & 0xFF; 
				buffer[1] = second & 0xFF; 
				if (first == 3156 && second == 1)
				{
						bms_soft_reset_save(kSoftReset_CmdCtrl, NULL, 0);
						drv_misc_reset_mcu();
				}
				else
				{
						data = bcu_modbus_485_0x06_fun(first, 1, buffer, &length);
				}
				
				
				if (data == 0) 
				{
						drv_mqtt_publish_control_no_respose("ok", 2);
				}
		}
		else if (strstr(message, "read") != NULL)
		{
				char data_str[650] = {0}; 
				uint8_t is_first_data = 1; // 标记是否为第一个数据
				uint8_t read_success = 1;  
				
				for (uint8_t i = 0; i < segment_count; i++) 
				{
						uint16_t start_addr = segments[i].start_addr;
						uint16_t reg_num = segments[i].reg_num;
						uint16_t length = 0;
						uint8_t read_buffer[150] = {0}; 
						
						uint8_t err = bcu_modbus_485_0x03_fun(start_addr, reg_num, read_buffer, &length);
						
						if (err != 0 || length != (reg_num << 1)) 
						{
								read_success = 0;
								break;
						}
						
						for (uint16_t j = 0; j < reg_num; j++) 
						{
								uint16_t value = (read_buffer[j * 2] << 8) | read_buffer[j * 2 + 1];
								
								if (!is_first_data) 
								{
										strcat(data_str, "+");
								} 
								else 
								{
										is_first_data = 0;
								}
								
								char val_str[6];
								snprintf(val_str, sizeof(val_str), "%u", value);
								strcat(data_str, val_str);
						}
				}
				
				if (read_success && strlen(data_str) > 0) 
				{
						drv_mqtt_publish_read_no_respose(data_str, strlen(data_str));
				}
		}
}

static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len)
{
    uint16_t i = 0;

    if((item != NULL) && (item->buf_pos + len < item->buf_size))
    {
        item->buf[item->buf_pos++] = buf[i];
        // 处理换行符，表示一条完整的 AT 指令返回
        if (buf[i] == '\n')
        {
            item->buf[item->buf_pos] = '\0';   // 添加结束符
						if (item->buf_pos < 100)
						{
							parse_mqtt_message(item->buf);    // 解析消息
						}
            item->buf_pos = 0;  			   // 重置索引，准备下一条数据
        }
    }
}


static void drv_qf41d_uart_rx_it_call(kit_ret_e res, void *data)
{
    OS_TRACE_ISR_ENTER();
    drv_qfc41d_push_data(&qfc41dItem, data, 1);
    OS_TRACE_ISR_EXIT();
}

// 发送单个字符
void drv_wireless_send_char(char c)
{
    while (!(USART2->SR & USART_SR_TXE));  // 等待发送缓冲区空
    USART2->DR = c;
}

// 发送字符串
void drv_wireless_send_string(const char *str)
{
    while (*str)
    {
        drv_wireless_send_char(*str++);
    }
    drv_wireless_send_char('\r');  // 发送 CR
    drv_wireless_send_char('\n');  // 发送 LF
}

void drv_wireless_send_string_dma_high_priority(const char *str)
{
    uint32_t start_time = kit_time_get_tick();

    while (dma_tx_busy && current_buffer == 0) 
		{
        if (kit_time_get_tick() - start_time > 180) 
				{ 
            __disable_irq(); 
            if (DMA1_Stream6->CR & DMA_SxCR_EN) 
						{
                DMA1_Stream6->CR &= ~DMA_SxCR_EN;
                while (DMA1_Stream6->CR & DMA_SxCR_EN);
                DMA1->HIFCR |= DMA_HIFCR_CTCIF6 | DMA_HIFCR_CTEIF6;
            }
            dma_tx_busy = 0;
            current_buffer = 0;
            USART2->CR3 &= ~USART_CR3_DMAT;
            __enable_irq();
            break;
        }
    }

    uint16_t len = 0;
    while (*str && len < TX_DMA_BUFFER_SIZE - 2) 
		{
        dma_tx_buffer[1][len++] = *str++;
    }
    dma_tx_buffer[1][len++] = '\r';
    dma_tx_buffer[1][len++] = '\n';

    __disable_irq(); 
    // 确保DMA已停止
    DMA1_Stream6->CR &= ~DMA_SxCR_EN;
    while (DMA1_Stream6->CR & DMA_SxCR_EN);

    DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[1];
    DMA1_Stream6->NDTR = len;

    dma_tx_busy = 1;
    current_buffer = 1;
    DMA1_Stream6->CR |= DMA_SxCR_EN;
    USART2->CR3 |= USART_CR3_DMAT;
    __enable_irq();
}

void drv_wireless_send_string_dma(const char *str)
{
    __disable_irq(); 
    if (dma_tx_busy || current_buffer == 1) 
		{
        __enable_irq();
        return;
    }
    __enable_irq();

    bsp_task_delay_ms(250);
    
    uint16_t len = 0;
    while (*str && len < TX_DMA_BUFFER_SIZE - 2) 
		{
        dma_tx_buffer[0][len++] = *str++;
    }
    dma_tx_buffer[0][len++] = '\r';
    dma_tx_buffer[0][len++] = '\n';

    __disable_irq();
    if (dma_tx_busy || current_buffer == 1)			
		{
        __enable_irq();
        return;
    }

    DMA1_Stream6->CR &= ~DMA_SxCR_EN;
    while (DMA1_Stream6->CR & DMA_SxCR_EN);

    DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[0];
    DMA1_Stream6->NDTR = len;

    dma_tx_busy = 1;
    current_buffer = 0;
    DMA1_Stream6->CR |= DMA_SxCR_EN;
    USART2->CR3 |= USART_CR3_DMAT;
    __enable_irq(); 
}


// 发送 AT 指令并等待返回值
int drv_at_send_cmd(const char *cmd, const char *response, uint32_t timeout)
{
    memset(qfc41dItem.buf, 0, QFC41D_MAX_RECV_SIZE);
    qfc41dItem.buf_pos = 0;  // 清空接收缓冲区索引

    drv_wireless_send_string(cmd);

    uint32_t start_time = kit_time_get_tick();  // 获取当前时间
    while (kit_time_get_tick() - start_time < timeout)
    {
        if (strstr((char *)qfc41dItem.buf, response))
        {
            return 1;  // 成功匹配返回值
        }
    }
    return 0;  // 超时未收到期望数据
}

static uint8_t drv_wifi_init()
{

    if (!drv_at_send_cmd("AT", "OK", WIFI_TIMEOUT))
    {
        return 1 ;
    }
		
		if (!drv_at_send_cmd("AT+QSTASTOP", "OK", WIFI_TIMEOUT))
    {
        return 1;
    }
		
		if (!drv_at_send_cmd("AT+QSOFTAPSTOP", "OK", WIFI_TIMEOUT))
    {
        return 1;
    }
		
	return 0;
}

uint8_t drv_ble_init()
{
		char at_cmd[42];  
		snprintf(at_cmd, sizeof(at_cmd), "AT+QBLENAME=BSM%s", deviceSN);
	
		if (!drv_at_send_cmd("AT+QBLEINIT=3", "OK", WIFI_TIMEOUT))
    {
        return 1;
    }

    //设置wifi名称，必须以BSM开头，后缀可以加sn码
    if (!drv_at_send_cmd(at_cmd, "OK", WIFI_TIMEOUT)) 
		{
			return 1;
		}
		
    return 0;
}


uint8_t drv_qfc41d_init(void)
{
    //初始化串口
    drv_uart_init((UartDev)qfc41dItem.dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_WIRELESSUart_Tx, kGpioType_WIRELESSUart_Rx);
	
	USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE;
    //设置接收回调函数
    drv_uart_set_interrupt(QFC41D_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, drv_qf41d_uart_rx_it_call);//#define SIM_UART_PORT     	kUartDev_2

		//初始化蓝牙（BLE）
    if (drv_ble_init() != 0)
    {
        return 1;
    }


	return 0;
}

#define MQTT_BROKER     "47.120.14.45"   // 你的 MQTT 服务器地址
#define MQTT_PORT       3011               // MQTT 端口
#define MQTT_CLIENT_ID  "fc41d_client"       // 客户端 ID
#define MQTT_USER       "user"               // MQTT 用户名
#define MQTT_PASSWORD   "password"           // MQTT 密码      
#define MQTT_TOPIC_CONTROL_PREFIX  "bluesun/bms/control/reply/"
#define MQTT_TOPIC_READ_PREFIX     "bluesun/bms/read/reply/"

static uint8_t drv_mqtt_subscribe()
{
    snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,1,\"%s\",2", mqtt_topic_period);
    drv_wireless_send_string(cmd);
    return 0;
}

uint8_t drv_mqtt_publish(char* str,uint16_t length)
{
    snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,%s,%d,%s",mqtt_topic_period, length, str);
    if (!drv_at_send_cmd(cmd, "OK\0", WIFI_TIMEOUT))
    {
        return 1;
    }

    return 0;
}

uint8_t drv_mqtt_publish_no_respose(char* str,uint16_t length)
{
//    snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str);
		snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", mqtt_topic_period, length, str);
//    drv_wireless_send_string(cmd);  // 未使用DMA
		drv_wireless_send_string_dma(cmd);  // 使用DMA
    return 0;
}

uint8_t drv_mqtt_publish_control_no_respose(char* str, uint16_t length) {
    char full_topic[44]; 
    snprintf(full_topic, sizeof(full_topic), "%s%s", MQTT_TOPIC_CONTROL_PREFIX, deviceSN);

    // 构造 AT 命令
    snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", full_topic, length, str);
    drv_wireless_send_string_dma_high_priority(cmd);
    return 0;
}

uint8_t drv_mqtt_publish_read_no_respose(char* str, uint16_t length) {
    char full_topic[44];
    snprintf(full_topic, sizeof(full_topic), "%s%s", MQTT_TOPIC_READ_PREFIX, deviceSN);

    snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", full_topic, length, str);
    drv_wireless_send_string_dma_high_priority(cmd);
    return 0;
}
