#include "COH2.h"
#include "usart.h"
#include <stdint.h>
#include <stdio.h>  // printf
#include <string.h>
//#include "tim.h"  // 用于传感器超时100ms处理 

#define RS485_TX_MODE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET)   // 使能RS485发送模式
#define RS485_RX_MODE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET) // 使能RS485接收模式

extern uint8_t dataReceive2[];

//#define NUM_CO_SENSORS 4  // CO传感器数量
//#define NUM_H2_SENSORS 4  // H2传感器数量
//// CO传感器地址
//uint8_t CO_addresses[NUM_CO_SENSORS] = {0x0E, 0x0F, 0x10, 0x11};
//// H2传感器地址
//uint8_t H2_addresses[NUM_H2_SENSORS] = {0x0B, 0x0A, 0x0C, 0x0D};
#define NUM_CO_SENSORS 1  // CO传感器数量
#define NUM_H2_SENSORS 1  // H2传感器数量
// CO传感器地址
uint8_t CO_addresses[NUM_CO_SENSORS] = {0x0E};
// H2传感器地址
uint8_t H2_addresses[NUM_H2_SENSORS] = {0x0B};

uint16_t calculate_crc16(uint8_t *data, uint16_t length) 
{
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < length; i++) {
        crc ^= (uint16_t)data[i];
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

// 查找传感器地址在数组中的索引
int find_sensor_index(uint8_t address, uint8_t *address_array, int num_sensors) 
{
    for (int i = 0; i < num_sensors; i++) {
        if (address == address_array[i]) {
            return i;
        }
    }
    return -1;  // 地址未找到
}

// 发送MODBUS指令读取传感器数据
void send_modbus_command(uint8_t sensor_address) 
{
    uint8_t command[8];
    command[0] = sensor_address;  // 传感器地址
    command[1] = 0x03;            // 功能码：读取保持寄存器
    command[2] = 0x00;            // 起始地址高字节
    command[3] = 0x00;            // 起始地址低字节
    command[4] = 0x00;            // 读取寄存器数量高字节
    command[5] = 0x02;            // 读取寄存器数量低字节

    uint16_t crc = calculate_crc16(command, 6);
    command[6] = crc & 0xFF;      // CRC低字节
    command[7] = (crc >> 8) & 0xFF; // CRC高字节

    RS485_TX_MODE;  // 切换到发送模式

		HAL_UART_Transmit(&huart2, command, 8,1000);//不用阻塞函数，防止系统卡死

    // 注意：在这里不要立即切换到接收模式，需要在发送完成回调中处理
}
void send_H2_0x0B_command(void) 
{
    uint8_t command[8];
    command[0] = 0x0B;  // 传感器地址
    command[1] = 0x03;            // 功能码：读取保持寄存器
    command[2] = 0x00;            // 起始地址高字节
    command[3] = 0x00;            // 起始地址低字节
    command[4] = 0x00;            // 读取寄存器数量高字节
    command[5] = 0x02;            // 读取寄存器数量低字节

    uint16_t crc = calculate_crc16(command, 6);
    command[6] = crc & 0xFF;      // CRC低字节
    command[7] = (crc >> 8) & 0xFF; // CRC高字节

    RS485_TX_MODE;  // 切换到发送模式

    HAL_UART_Transmit(&huart2, command, 8,1000);

    // 注意：在这里不要立即切换到接收模式，需要在发送完成回调中处理
}
void send_CO_0x0E_command(void) 
{
    uint8_t command[8];
    command[0] = 0x0E;  // 传感器地址
    command[1] = 0x03;  // 功能码：读取保持寄存器
    command[2] = 0x00;  // 起始地址高字节
    command[3] = 0x00;  // 起始地址低字节
    command[4] = 0x00;  // 读取寄存器数量高字节
    command[5] = 0x02;  // 读取寄存器数量低字节

    uint16_t crc = calculate_crc16(command, 6);
    command[6] = crc & 0xFF;      // CRC低字节
    command[7] = (crc >> 8) & 0xFF; // CRC高字节

    RS485_TX_MODE;  // 切换到发送模式

    HAL_UART_Transmit(&huart2, command, 8,1000);

    // 注意：在这里不要立即切换到接收模式，需要在发送完成回调中处理
}
// 处理接收的数据并转换为浮点数
void receive_and_store_data(uint8_t sensor_address) 
{
//    uint8_t received_data[9];  // 接收缓冲区，接收9字节

//    HAL_UART_Receive_DMA(&huart2, received_data, 9);
		HAL_Delay(50);
    uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7];
    uint16_t crc_calculated = calculate_crc16(dataReceive2, 7);

    if (crc_received == crc_calculated) 
		{
					// 提取有效数据部分并转换为浮点数
					uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]};
					float result = modbus_to_float(data_part);

					// 检查地址是否属于CO传感器
					int index = find_sensor_index(sensor_address, CO_addresses, NUM_CO_SENSORS);
					if (index != -1) {
							CO_data[index] = result;  // 存储到CO数据数组
					} 
					// 检查地址是否属于H2传感器
					else if ((index = find_sensor_index(sensor_address, H2_addresses, NUM_H2_SENSORS)) != -1) {
							H2_data[index] = result;  // 存储到H2数据数组
					}

//					printf("sensor %02X: %.2f\n", sensor_address, result);
			} 
		else {
//					printf("CRC fail:%02X\n", sensor_address);
			}
}
// 处理接收的数据并转换为浮点数
void receive_and_store_data_CO_0E(void) 
{
    uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7];
    uint16_t crc_calculated = calculate_crc16(dataReceive2, 7);

    if (crc_received == crc_calculated) 
		{
					// 提取有效数据部分并转换为浮点数
					uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]};
					float result = modbus_to_float(data_part);
					CO_data[0] = result;  // 存储到CO数据数组

//					printf("CO 0x0E: %.2f\n",  result);
			} 
}
// 处理接收的数据并转换为浮点数
void receive_and_store_data_H2_0B(void) 
{
    uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7];
    uint16_t crc_calculated = calculate_crc16(dataReceive2, 7);

    if (crc_received == crc_calculated) 
		{
					// 提取有效数据部分并转换为浮点数
					uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]};
					float result = modbus_to_float(data_part);
					H2_data[0] = result;  // 存储到CO数据数组

//					printf("H2 0x0B: %.2f\n",  result);
			} 
}
// 将MODBUS数据转换为IEEE-754浮点数
float modbus_to_float(uint8_t *data) 
{
    uint8_t reordered_data[4];
    reordered_data[0] = data[2];  // 高字节1
    reordered_data[1] = data[3];  // 高字节2
    reordered_data[2] = data[0];  // 低字节1
    reordered_data[3] = data[1];  // 低字节2

    float result;
    memcpy(&result, reordered_data, sizeof(float));

    return result;
}

void read_gas_sensors_485data(void) 
{
//    for (int i = 0; i < NUM_CO_SENSORS; i++) {
//        send_modbus_command(CO_addresses[i]);
//        receive_and_store_data(CO_addresses[i]);
//    }
//    for (int i = 0; i < NUM_H2_SENSORS; i++) {
//        send_modbus_command(H2_addresses[i]);
//        receive_and_store_data(H2_addresses[i]);
//    }
	send_H2_0x0B_command();
	receive_and_store_data(CO_addresses[0]);
	send_CO_0x0E_command();
	receive_and_store_data(H2_addresses[0]);
}
