/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "timers.h" 
#include "usart.h"
#include "can.h"
#include "rtc.h"
#include "uType.h"
#include "remote.h"
#include "queue.h"
#include "iwdg.h"
#include "adc.h"
#include "WIFI.h"
#include "w25qxx.h"
#include "spi.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
typedef StaticQueue_t osStaticMessageQDef_t;
/* USER CODE BEGIN PTD */
extern RTC_HandleTypeDef hrtc;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/**
  * @breaf 485串口uart2接收数组定义
  */

extern uint8_t uart2RXDATAbuffer[BUFFER_SIZE2];
extern uint8_t dataReceive2[BUFFER_SIZE2];// 485
//extern volatile uint8_t uart2DataReady ;

#define MAX_FRAME_SIZE 40  // 一帧最大 40 字节

/**
  * @breaf 4G串口uart3接收数组定义
  */

extern uint8_t receiveBuff4G[BUFFER_SIZE4G];
//extern uint8_t receiveBuff4G_DMAbuffer[BUFFER_SIZE4G];

volatile uint16_t uart4GHead = 0;  // 缓冲区写指针
volatile uint16_t uart4GTail = 0;  // 缓冲区读指针


/**
  * @breaf ML307A参数定义
  */
typedef enum {
    AT,
		CPIN,	
    CEREG, 
    CFUN,	
		TIME,
		MUECONFIG,
		MDIALUPCFG,
		MQTTDISC,
		MQTTCFG_CLEAN,
		MQTTCFG_CACHED,
		MQTTCONNE,
		MQTTSUB,
		MQTTSUB1,
		MIP_CONNECT,
		MIPCFG,
		MIPCLOSE,
		MDIALUP,
		MIP_REGISTER,
		Heartbeat,
		Systemwarninglevel,
		Remote,	
		CHECK_AT,
		CHECK_CPIN,
		CHECK_MQTT,
		CHECK_MIPSTATE,
		IDLE0,
		IDLE,
		IDLE1,
		SEND_MLX	
} ML307A_StateTypeDef;
static ML307A_StateTypeDef ml307aState = AT; 
time_t epoch_time = 0;
static uint8_t mipclose_count = 0;

typedef enum {
    Debug_MODE,		// 试验模式
    WARNING_MODE,	// 预警模式
		SET_MODE,			// 设置模式
} SYSTEM_OPERATINGMODE;
volatile SYSTEM_OPERATINGMODE system_operatingmode = WARNING_MODE;

// 屏幕显示模式
typedef enum {
    DWIN_STATE_DEBUG,
    DWIN_STATE_WARNING,
    DWIN_STATE_SET,
		DWIN_STATE_AVIATION,
		DWIN_STATE_AVIATION_READ,
		DWIN_STATE_4G,
		DWIN_STATE_DEBUG_SWITCH,
		DWIN_STATE_WARNING_SWITCH,
		DWIN_STATE_SET_SWITCH,
    DWIN_STATE_IDLE
} DWIN_State_t;
volatile DWIN_State_t dwin_state = DWIN_STATE_WARNING;


SYSTEM_Cloud_MODE system_cloud_mode = Cloud_WIFI_MODE; // 系统为WIFI模式还是4G模式 // Cloud_WIFI_MODE // Cloud_4G_MODE

typedef enum {
  WIFI_AT,
	WIFI_RESTORE,
	WIFI_CWMODE,	
	WIFI_RST,	
	WIFI_TCPDATAMODE,
	WIFI_CIPSNTP,
	WIFI_TZONE,
	WIFI_DPM,
	WIFI_CWSTAT,
	WIFI_CWJAP,
	WIFI_CWQAP,	
	WIFI_CIPSTART,
	WIFI_CIPSEND_Register,
	WIFI_unixtime,
	WIFI_Remote,
	WIFI_TIME,
	WIFI_IDLE
} WIFI_StateTypeDef;
static WIFI_StateTypeDef wifistate = WIFI_CWMODE; 

// 温度预警等级
typedef enum {
    TEMP_LEVEL_0,	// 正常状态
    TEMP_LEVEL_1,	// 一级预警
    TEMP_LEVEL_2	// 二级报警
} TempSystemLevel_t;
volatile TempSystemLevel_t temp_system_level = TEMP_LEVEL_0;
uint8_t temp_level_buffer[MAX_TEMP_NODE_NUM] = {0};  // 状态变量记录每个温度小板的 temp_system_level
// 压力预警等级
typedef enum {
    PRE_LEVEL_0,	// 正常状态
    PRE_LEVEL_1,	// 一级预警
    PRE_LEVEL_2	// 二级报警
} PreSystemLevel_t;
volatile PreSystemLevel_t pre_system_level = PRE_LEVEL_0;
uint8_t pre_level_buffer[MAX_PRESSURE_NODE_NUM] = {0};  // 状态变量记录每个压力小板的 pre_system_level
// CO预警等级
typedef enum {
    CO_LEVEL_0,	// 正常状态
    CO_LEVEL_1,	// 一级预警
    CO_LEVEL_2	// 二级报警
} COSystemLevel_t;
volatile COSystemLevel_t co_system_level = CO_LEVEL_0;
float  co_level_buffer[MAX_CO_NODE_NUM] = {0.0f};  // 状态变量记录每个CO小板的 co_system_level
// H2预警等级
typedef enum {
    H2_LEVEL_0,	// 正常状态
    H2_LEVEL_1,	// 一级预警
    H2_LEVEL_2	// 二级报警
} H2SystemLevel_t;
volatile H2SystemLevel_t h2_system_level = H2_LEVEL_0;
float  h2_level_buffer[MAX_H2_NODE_NUM] = {0.0f};  // 状态变量记录每个CO小板的 h2_system_level

/**
  * @breaf 温度数据组包用
  */
typedef  struct _CANTemp_raw
 {
	uint8_t NodeId;
	uint8_t PacktSeq;	
	uint8_t SliceNum;
	uint16_t SliceMask;
	uint8_t data[SLICE_DATA_SIZE*MAX_SLICE_NUM];
	uint8_t Finished;
 }CanTemp_raw;
 CanTemp_raw g_canTempRaw[MAX_TEMP_NODE_NUM];
 
/**
  * @breaf 485串口2接收处理参数定义
  */
typedef  struct _UartTemp_raw
 {
	uint8_t NodeId;
	uint8_t Finished;
	uint8_t data[4];
 }UartTemp_raw;
 
 UartTemp_raw g_485TempRaw[MAX_H2_NODE_NUM];
 
/**
  * @breaf 供电标志位
  */
bool screen_powered = false;
bool actuator_powered = false;
bool gas_powered = false;

/**
	* @breaf 迪文屏状态显示等级
  */

int previous_actuator_state = actuator_closed;
static int previous_dwin_warning_state_level = SYSTEM_LEVEL_3;
static int previous_dwin_power_state = dwin_power_closed;

/**
	* @breaf 处理迪文待发送的数据的缓冲区
	* @breaf 用于比较数据是否与上次一样避免重复发送
  */
typedef struct _DwinTemp_data
{
	uint32_t count_ms;
	uint8_t	 recv_flag;
	uint8_t	 offline_flag;
	uint8_t  data[3];
}DwinTemp_Data;

DwinTemp_Data g_prevdata_temp[MAX_TEMP_NODE_NUM]__attribute__((section(".ccmram"))); 

typedef struct _DwinPress_data
{
	uint32_t count_ms;
	uint8_t	 recv_flag;
	uint8_t	 offline_flag;
	uint8_t  data[2];
}DwinPress_Data;

DwinPress_Data g_prevdata_press[MAX_PRESSURE_NODE_NUM]__attribute__((section(".ccmram"))); 

typedef struct _DwinH2_data
{
	uint32_t count_ms;
	uint8_t	 recv_flag;
	uint8_t	 offline_flag;
	uint8_t  data[4];
}DwinH2_Data;

DwinH2_Data g_prevdata_h2[MAX_H2_NODE_NUM]__attribute__((section(".ccmram"))); 

typedef struct _DwinCO_data
{
	uint32_t count_ms;
	uint8_t	 recv_flag;
	uint8_t	 offline_flag;
	uint8_t  data[4];
}DwinCO_Data;

DwinCO_Data g_prevdata_co[MAX_CO_NODE_NUM]__attribute__((section(".ccmram"))); 

/**
  * @breaf 标志位
  */
bool DWIN_stopsend_flag = true; 				// DWIN能否发送指令标志位。用于发送停止掉发送状态指令
bool flash_save_parameter_flag = false; // 修改参数时用于存入flash标志位
bool flash_save_terminal_flag = false; // 修改终端ID和手机号时用于存入flash标志位
bool gas_start_read_flag = false; 			// 气体读取标志位
bool DWIN_terminal_SHOW_flag = false;		// 迪文接收修改终端ID存入flash的标志位

/**
* @breaf 检查传感器在线状态的状态机
  */
typedef enum {
    SENSOR_STATE_TEMP,
    SENSOR_STATE_PRE,
    SENSOR_STATE_H2,
    SENSOR_STATE_CO,
    SENSOR_STATE_MAX 
} SensorCheckState;
static SensorCheckState current_state = SENSOR_STATE_TEMP; 

//#define TEMP_NODE_GROUP_SIZE 5 // 每次检测的温度传感器数量
//static uint8_t current_temp_group = 0; // 当前检测温度的组编号
      
FlashData flash_data = {	
		.controltransmit_flag = 0,							// 默认打开传输传感器数据
    .temp_first_threshold = 60, 						// 温度一级阈值 60 ℃
		.temp_second_threshold = 100, 					// 温度二级阈值 100 ℃
		.pressure_threshold = 100,							// 压力阈值 100 pa
		.co_threshold = 10,											// CO二级阈值 10 ppm
		.h2_threshold = 10,											// H2二级阈值 10 ppm
		.heart_upload_frequency = 30,						// 心跳上传云平台频率 30 s 
		.mainboard_upload_frequency = 3,				// 主板上传云平台频率 3 s
		.smallboard_upload_frequency = 1,				// 小板CAN上传至主板频率 1 s
		.object_emissivity = 95,								// 初始发射率 0.95（后续除100）
		.version = 1,														// 系统版本号
};

/**
  * @brief  AT指令应答内容
  */	

	char *MQTTSTATE_Responses[] = {
			"+MQTTSTATE: 1",  
			"+MQTTSTATE: 2",  
			"+MQTTSTATE: 3",    
			NULL                   
	};
	char *MQTTSTATEreceivedResponse = NULL;  // 用来存储MQTT连接状态接收到的响应
		
SensorDataBuffer sensor_data_buffer = {0};
SensorDWINDataBuffer sensor_dwin_data_buffer = {0};

uint8_t DWIN_STARTSHOW_flag = 0;
uint8_t DWIN_STARTSHOW_count = 0;

static char mqtt_sub_topic[100]__attribute__((section(".ccmram")));  // 订阅主题缓冲区
static char mqtt_sub_cmd[150]__attribute__((section(".ccmram"))); // AT 指令缓冲区

//QueueSetHandle_t xQueueSet;

bool check_can = true; // 轮流检查can和cloud的队列的标志位
bool check_dwin_gas = true; // 轮流检查can和cloud的队列的标志位
bool ReadHEXNDWIN_flag = true;
extern uint8_t terminalId[7];
extern uint8_t g_board_id[6];

#define STABLE_TIME_MS 1500  // 1.5秒稳定时间
#define TEMP_DEBOUNCE_TIME_MS 200  // 防止短时间内频繁变化
//static uint32_t last_change_time = 0; // 用于保存上次检测时的时间戳 
//static uint32_t last_temp_level_change_time = 0;  // 上次temp_level变更的时间
//static uint8_t last_tempmax_level = 0; // 上一次的最大温度等级

static DWIN_power_t last_dwin_power_state = dwin_power_closed;  // 初始为关闭
volatile DWIN_power_t dwin_power_state = dwin_power_closed;// 迪文供电情况标志位
volatile DWIN_Init_t dwin_init_state = dwin_Init_closed;  // 迪文屏初始化标志位
volatile DWIN_Show_t dwin_show_state = dwin_show_closed;  // 迪文屏发送数据标志位
volatile actuator_t actuator_powered_state = actuator_closed;
volatile SystemLevel_t system_level = SYSTEM_LEVEL_0;

uint8_t temp_buffer[MAX_FRAME_SIZE]__attribute__((section(".ccmram"))) = {0};  // 临时存放一帧数据
uint8_t Ambient_temperature = 0;

static int last_system_level = -1;

bool REGISTER_OK_start_flag = false;
bool REGISTER_OK_start_flag_DWIN = false;

static uint8_t gas_command_index = 0;
static uint8_t dwin_command_index = 0;

static uint32_t prev_extid = 0;
uint8_t sensor_status[6] = {0x3F, 0xFF, 0xFF, 0xFF, 0x77, 0x70};  // 传感器在线情况初始化全 0，0为掉线，1为在线
uint8_t prev_sensor_status[6] = {0}; // 记录上一次的状态
bool S_offline_flag = false;

uint16_t trigger_info[3] = {0}; // 存储触发信息

uint16_t send_remote_uploadfrequency = 0;

uint32_t adc_val = 0 ; // ADC读取电压
uint8_t voltage_int = 0;
uint8_t percent  = 0;
char display_str[10];
extern uint8_t receiveBuff4G_MIPURC[256];//4G处理mipurc的接收缓冲区
int g_cip_id = -1; // 初始无效

//uint8_t wifi_ssid[20] = "jiaLong";           // WiFi 名称
//uint8_t wifi_password[20] = "JL88888888";     // WiFi 密码
extern uint32_t W25_Tempaddress ;
extern volatile uint8_t flash_print_busy;

uint8_t flash_temp_prc0h2[512] = {0}; // 存入flash的温度和压力数据

WIFI_Config_t wifi_config = {
    .ssid = "jiaLong",
    .password = "JL88888888"
};
extern uint8_t rx_len;

#define WIFI_MAX_RETRY 3 // WIFI发送数据重试次数
uint32_t wifior4G_flag = 0;
volatile bool heartbeat_reply_received = false; // 心跳的通用应答标志位
volatile bool unixtime_reply_received = false; // unixtime的80FF应答标志位

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
void uart3_disable(void);
void MCU_REBOOT(void);
void sendWifiJoinCommand(uint8_t *ssid, uint8_t *password) ;
void Send_Remote(void);
void InitializeBoardDataProcess(void);
void ClearSensorDataBuffer(void) ;
void Uart2_ProcessNextMessage(void);
bool is_electric_actuator_response(uint8_t *data);
void process_electric_actuator(uint8_t *data);
void process_mode(uint8_t *data);
bool is_mode_response(uint8_t *data);
bool is_threshold_response(uint8_t *data);
void process_threshold(uint8_t *data) ;
bool is_wifi_response(uint8_t *data);// 判断是否为WIFI账号密码修改
void process_wifi(uint8_t *data); // 处理阈值数据
bool is_terminal_response(uint8_t *data);
void process_terminal_data(uint8_t *data);
bool is_gas_sensor_response(uint8_t *data);
void process_gas_sensor(uint8_t *data) ;
static inline float parse_modbus_float(uint8_t *data);
static void process_single_gas_sensor(uint8_t sensor_type, uint8_t id, uint8_t *data, 
                                      float *level_buffer, uint8_t max_nodes,
                                      float threshold, volatile uint8_t *system_level,
                                      uint8_t (*sensor_data_buffer)[4], uint8_t *sensor_valid);
bool is_restart_response(uint8_t *data) ;
uint8_t CalculateChecksum(uint8_t* data, uint16_t length);
//void CAN_Send_Parameter(uint32_t node_id , FlashData *flash_data , uint8_t len);
void ProcessQueues(void);
void ProcessDWINSHOW_gasread(void) ;
void MidProcessData(CanRx_msg *can_msg) ;
void MIDprocess_cloudmessage(Remote_msg *rt_msg) ;
void update_temp_cloud_send_buffer(uint8_t id);
void WriteToCircularBuffer(uint8_t *data, uint16_t length);
void print_SensorDataBuffer(SensorDataBuffer *buffer);
void DWIN_STARTSHOW(void);
void DWIN_WARNING_MODE(void);
void DWIN_SHOW(void);
DWIN_State_t get_current_dwin_state(void);
void DWIN_PARAM_SHOW(void);																		
void check_trigger_source(void);
void check_sensor_line(void);
void check_temp_line(void); 
void check_pre_line(void); 
void check_h2_line(void);
void check_co_line(void);
void read_gas(void);
void read_dwin(void) ;
void DWIN_CHECK(void);
void DWIN_START_CHECK(void);
void printCurrentRTCTime(void);
uint16_t calculate_crc16(uint8_t *data, uint16_t length) ;
void send_modbus_command(uint8_t sensor_address) ;
void Check_DWIN_Button(void);
float modbus_to_float(uint8_t *data) ;
double standard_to_float(const char* f_num) ;
void control_actuator(bool enable); 
void control_gas_sensors(bool enable) ;
void control_wifi_wakeup(bool enable) ; 
void Read_parameter_From_Flash(void) ;
void Read_terminal_From_Flash(void) ;
void Save_parameter_To_Flash(	uint8_t controltransmit_flag ,
															uint8_t temp_first_threshold ,
															uint8_t temp_second_threshold ,
															uint8_t pressure_threshold ,
															uint8_t co_threshold ,
															uint8_t h2_threshold ,
															uint8_t smallboard_upload_frequency ,
															uint8_t heart_upload_frequency ,
															uint8_t mainboard_upload_frequency,	
															uint8_t sensoronline_upload_frequency) ;  // 向 Flash 写入 parameter 
void Save_terminal_To_Flash(uint8_t* terminalId , uint8_t* g_board_id ,uint8_t version); // 向 Flash 写入 terminal 
void Save_W25_Tempaddress_To_Flash(void);
void Save_version_To_Flash(void);
void Save_wifior4G_flag_To_Flash(void);
void Save_WIFI_To_Flash(void);
void Load_WIFI_From_Flash(void);
void Read_Remaining_stack_space(void);
uint8_t CalculateBatteryLevel(uint32_t adcValue,uint8_t *voltage);
uint32_t ReadADCValue(void);
void Enter_SleepMode(void);
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */


/* USER CODE END Variables */
/* Definitions for HighestLevel */
osThreadId_t HighestLevelHandle;
const osThreadAttr_t HighestLevel_attributes = {
  .name = "HighestLevel",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityRealtime,
};
/* Definitions for Common */
osThreadId_t CommonHandle;
const osThreadAttr_t Common_attributes = {
  .name = "Common",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityNormal4,
};
/* Definitions for temp_pressure */
osThreadId_t temp_pressureHandle;
const osThreadAttr_t temp_pressure_attributes = {
  .name = "temp_pressure",
  .stack_size = 1024 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for check_sensor */
osThreadId_t check_sensorHandle;
const osThreadAttr_t check_sensor_attributes = {
  .name = "check_sensor",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityBelowNormal,
};
/* Definitions for display */
osThreadId_t displayHandle;
const osThreadAttr_t display_attributes = {
  .name = "display",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityHigh,
};
/* Definitions for cloud */
osThreadId_t cloudHandle;
const osThreadAttr_t cloud_attributes = {
  .name = "cloud",
  .stack_size = 1024 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for SystemStatus */
osThreadId_t SystemStatusHandle;
const osThreadAttr_t SystemStatus_attributes = {
  .name = "SystemStatus",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityAboveNormal,
};
/* Definitions for can_message_queue */
osMessageQueueId_t can_message_queueHandle;
uint8_t can_message_queueBuffer[ 512 * sizeof( CanRx_msg ) ];
osStaticMessageQDef_t can_message_queueControlBlock;
const osMessageQueueAttr_t can_message_queue_attributes = {
  .name = "can_message_queue",
  .cb_mem = &can_message_queueControlBlock,
  .cb_size = sizeof(can_message_queueControlBlock),
  .mq_mem = &can_message_queueBuffer,
  .mq_size = sizeof(can_message_queueBuffer)
};
/* Definitions for cloud_message_queue */
osMessageQueueId_t cloud_message_queueHandle;
uint8_t cloud_message_queueBuffer[ 512 * sizeof( Remote_msg ) ];
osStaticMessageQDef_t cloud_message_queueControlBlock;
const osMessageQueueAttr_t cloud_message_queue_attributes = {
  .name = "cloud_message_queue",
  .cb_mem = &cloud_message_queueControlBlock,
  .cb_size = sizeof(cloud_message_queueControlBlock),
  .mq_mem = &cloud_message_queueBuffer,
  .mq_size = sizeof(cloud_message_queueBuffer)
};
/* Definitions for uart2rxqueue */
osMessageQueueId_t uart2rxqueueHandle;
uint8_t uart2queueBuffer[ 64 * sizeof( Uart2Rx_msg ) ];
osStaticMessageQDef_t uart2queueControlBlock;
const osMessageQueueAttr_t uart2rxqueue_attributes = {
  .name = "uart2rxqueue",
  .cb_mem = &uart2queueControlBlock,
  .cb_size = sizeof(uart2queueControlBlock),
  .mq_mem = &uart2queueBuffer,
  .mq_size = sizeof(uart2queueBuffer)
};
/* Definitions for uart3rxqueue */
osMessageQueueId_t uart3rxqueueHandle;
uint8_t uart3rxqueueBuffer[ 30 * sizeof( Uart3Rx_msg ) ];
osStaticMessageQDef_t uart3rxqueueControlBlock;
const osMessageQueueAttr_t uart3rxqueue_attributes = {
  .name = "uart3rxqueue",
  .cb_mem = &uart3rxqueueControlBlock,
  .cb_size = sizeof(uart3rxqueueControlBlock),
  .mq_mem = &uart3rxqueueBuffer,
  .mq_size = sizeof(uart3rxqueueBuffer)
};
/* Definitions for dataMutex */
osMutexId_t dataMutexHandle;
const osMutexAttr_t dataMutex_attributes = {
  .name = "dataMutex"
};
/* Definitions for dataReadySem */
osSemaphoreId_t dataReadySemHandle;
const osSemaphoreAttr_t dataReadySem_attributes = {
  .name = "dataReadySem"
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */


/* USER CODE END FunctionPrototypes */

void HighestLevel_Task(void *argument);
void Common_Task(void *argument);
void temp_pressure_Task(void *argument);
void check_sensor_Task(void *argument);
void display_Task(void *argument);
void cloud_Task(void *argument);
void SystemStatus_Task(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */
  /* Create the mutex(es) */
  /* creation of dataMutex */
  dataMutexHandle = osMutexNew(&dataMutex_attributes);

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
 
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* creation of dataReadySem */
  dataReadySemHandle = osSemaphoreNew(1, 1, &dataReadySem_attributes);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */

				
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* creation of can_message_queue */
  can_message_queueHandle = osMessageQueueNew (512, sizeof(CanRx_msg), &can_message_queue_attributes);

  /* creation of cloud_message_queue */
  cloud_message_queueHandle = osMessageQueueNew (512, sizeof(Remote_msg), &cloud_message_queue_attributes);

  /* creation of uart2rxqueue */
  uart2rxqueueHandle = osMessageQueueNew (64, sizeof(Uart2Rx_msg), &uart2rxqueue_attributes);

  /* creation of uart3rxqueue */
  uart3rxqueueHandle = osMessageQueueNew (30, sizeof(Uart3Rx_msg), &uart3rxqueue_attributes);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
	if(system_cloud_mode == Cloud_4G_MODE)
	{
		wifior4G_flag = 0 ; // 4G模式 标志位为0
	}
	if(system_cloud_mode == Cloud_WIFI_MODE)
	{
		wifior4G_flag = 1 ; // WIFI模式 标志位为1
	}
	InitializeBoardDataProcess();
	ClearSensorDataBuffer();
	Save_version_To_Flash();
	Read_parameter_From_Flash();
	Read_terminal_From_Flash();
	Load_W25_Tempaddress_From_Flash();
	Read_wifior4G_flag_From_Flash();
	Load_version_From_Flash();
	
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of HighestLevel */
  HighestLevelHandle = osThreadNew(HighestLevel_Task, NULL, &HighestLevel_attributes);

  /* creation of Common */
  CommonHandle = osThreadNew(Common_Task, NULL, &Common_attributes);

  /* creation of temp_pressure */
  temp_pressureHandle = osThreadNew(temp_pressure_Task, NULL, &temp_pressure_attributes);

  /* creation of check_sensor */
  check_sensorHandle = osThreadNew(check_sensor_Task, NULL, &check_sensor_attributes);

  /* creation of display */
  displayHandle = osThreadNew(display_Task, NULL, &display_attributes);

  /* creation of cloud */
  cloudHandle = osThreadNew(cloud_Task, NULL, &cloud_attributes);

  /* creation of SystemStatus */
  SystemStatusHandle = osThreadNew(SystemStatus_Task, NULL, &SystemStatus_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */

  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */

  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_HighestLevel_Task */
/**
  * @brief  Function implementing the HighestLevel thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_HighestLevel_Task */
void HighestLevel_Task(void *argument)
{
  /* USER CODE BEGIN HighestLevel_Task */
  /* Infinite loop */
	uint16_t counter = 0; // 闪灯计数器
	uint16_t gas_counter = 0; // 气体计数器
	
  for(;;)
  {
    osDelay(5);
		counter++;
		
		Check_DWIN_Button();
    if (counter >= 100)
    {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); // 切换 LED 状态
      counter = 0; // 重置计数器
			HAL_IWDG_Refresh(&hiwdg);			
    }
		if(dwin_power_state != previous_dwin_power_state) // previous_dwin_warning_state_level
		{
//			previous_dwin_warning_state_level = SYSTEM_LEVEL_3;
			previous_dwin_power_state = dwin_power_state;
		}
		if (dwin_power_state == dwin_power_opened)
		{				
			if (last_dwin_power_state != dwin_power_opened)  // 状态刚从关闭变为开启
			{
					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // 外设DWIN 24V 高电平开启
					DWIN_STARTSHOW_flag = 1;
					dwin_state = DWIN_STATE_WARNING_SWITCH; 
					REGISTER_OK_start_flag_DWIN = false;
			}

			// 更新上一次状态
			last_dwin_power_state = dwin_power_opened;
		}
		else if(dwin_power_state == dwin_power_closed)
		{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // 外设DWIN 24V 低电平关闭
				dwin_state = DWIN_STATE_IDLE;
				dwin_show_state  = dwin_show_closed ;
				previous_dwin_warning_state_level = SYSTEM_LEVEL_3;
				previous_actuator_state = actuator_closed;
				REGISTER_OK_start_flag_DWIN = false;
				last_dwin_power_state = dwin_power_closed;// 更新上一次状态
		}
			
		if (temp_system_level == TEMP_LEVEL_1 || temp_system_level == TEMP_LEVEL_2) 
		{
				if (temp_system_level == TEMP_LEVEL_2 || 
						pre_system_level == PRE_LEVEL_2 || 
						co_system_level == CO_LEVEL_2 || 
						h2_system_level == H2_LEVEL_2) 
				{
						system_level = SYSTEM_LEVEL_2;  // 温度至少1级，且其他有2级时，触发2级
				} 
				else 
				{
						system_level = SYSTEM_LEVEL_1;  // 仅温度达到1级
				}
		} 
		else 
		{
				system_level = SYSTEM_LEVEL_0;  // 温度为0级，则系统也为0级
		}

		
		if (system_level == SYSTEM_LEVEL_2) 
		{
				gas_counter++;
//				dwin_warning_state_level = DWIN_WARNING_LEVEL_2_STATE;
				actuator_powered = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_11) == GPIO_PIN_RESET;
				if ( actuator_powered ) 
				{
					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // 使能 电推杆12V芯片 低电平开启
					control_actuator(true); 		// 开启电推杆供电
					HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET);
					
					printf("SYSTEM_LEVEL_2 actuator_power_opened\n");
					actuator_powered_state = actuator_opened;
				}
				gas_powered = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET;
				if ( gas_powered ) 
				{
					control_gas_sensors(true);	// 打开气体供电
					printf("gas_power_opened\n");
					if (gas_counter >= 8000) // 气体上电后等待40秒再开始读数
					{
						gas_start_read_flag = true;
//						printf("gas_start_read\n");
						gas_counter = 0;
					}
				}else{
						gas_start_read_flag = true;				
				}
		}
		else if (system_level == SYSTEM_LEVEL_0) 
		{
//			printf("system_level == SYSTEM_LEVEL_0\r\n");
//				dwin_warning_state_level = DWIN_WARNING_LEVEL_0_STATE;
//				actuator_powered = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_11) == GPIO_PIN_SET;
//				if ( actuator_powered ) 
//				{
//					control_actuator(false);		// 关闭电推杆供电
////					HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
////					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET);
//					
//					printf("actuator_power_closed\n");
//				}
				gas_powered = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET;
				if ( gas_powered ) 
				{
//					control_gas_sensors(true);	// 打开气体供电
//					printf("gas_power_closed\n");
//					printf("gas_power_opened_SYSTEM_LEVEL_0\n");
					gas_start_read_flag = false;
				}else{
					control_gas_sensors(false);	// 关闭气体供电
					gas_start_read_flag = false;
				}
//				gas_start_read_flag = false;
		}			
		if(system_cloud_mode == Cloud_WIFI_MODE)
		{
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); // PC7高电平唤醒WIFI
			HAL_GPIO_WritePin(GPIOC, V3_8V_4G_enable_Pin, GPIO_PIN_SET); // 4G电源3.8V高电平断电
			wifior4G_flag = 1; // WIFI模式
		}else{
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); // PC7低电平休眠WIFI
			HAL_GPIO_WritePin(GPIOC, V3_8V_4G_enable_Pin, GPIO_PIN_RESET); // 4G电源3.8V低电平开启
			wifior4G_flag = 0; // 4G模式
		}
  }
  /* USER CODE END HighestLevel_Task */
}

/* USER CODE BEGIN Header_Common_Task */
/**
* @brief Function implementing the Common thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Common_Task */
void Common_Task(void *argument)
{
  /* USER CODE BEGIN Common_Task */
  /* Infinite loop */
//	uint16_t adc = 0;
  for(;;)
  {							
    osDelay(100);
//		adc++;
//		if(adc > 20)
//		{
//			adc_val = ReadADCValue();
//			percent = CalculateBatteryLevel(adc_val, &voltage_int);
//			printf("adc %d %d %d\n",adc_val,voltage_int,percent);		
//		}
		Uart2_ProcessNextMessage();

		if(flash_save_parameter_flag)
		{			
			Save_parameter_To_Flash(	flash_data.controltransmit_flag ,
																flash_data.temp_first_threshold ,
																flash_data.temp_second_threshold ,
																flash_data.pressure_threshold ,
																flash_data.co_threshold ,
																flash_data.h2_threshold ,
																flash_data.smallboard_upload_frequency ,
																flash_data.heart_upload_frequency ,
																flash_data.mainboard_upload_frequency,	
																flash_data.sensoronline_upload_frequency);

			flash_save_parameter_flag = false;
		}
		
//			if(flash_save_terminal_flag)
//			{
////				vTaskSuspend(displayHandle);
////				vTaskSuspend(temp_pressureHandle);
//				Save_terminal_To_Flash(terminalId , g_board_id ,flash_data.version);
//				vTaskResume(displayHandle);
//				vTaskResume(temp_pressureHandle);
//				flash_save_terminal_flag = false;
//			}

		
  }
  /* USER CODE END Common_Task */
}

/* USER CODE BEGIN Header_temp_pressure_Task */
/**
* @brief Function implementing the temp_pressure thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_temp_pressure_Task */
void temp_pressure_Task(void *argument)
{
  /* USER CODE BEGIN temp_pressure_Task */
  /* Infinite loop */
//	InitializeBoardDataProcess();
	
  for(;;)
  {
		ProcessQueues();
    osDelay(20);
//		HAL_IWDG_Refresh(&hiwdg);		
//		DWIN_STARTSHOW();			
	
	}
  /* USER CODE END temp_pressure_Task */
}

/* USER CODE BEGIN Header_check_sensor_Task */
/**
* @brief Function implementing the check_sensor thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_check_sensor_Task */
void check_sensor_Task(void *argument)
{
  /* USER CODE BEGIN check_sensor_Task */
  /* Infinite loop */
	uint32_t delay_time = 0;
	uint32_t adc_delay_time = 0;
	
  for(;;)
  {		
//		process_uart3_buffer(); // 处理4G模组收到的数据
		osDelay(100);
		if( delay_time > 7000 )
		{			
			check_sensor_line();
			delay_time = 0;
		}
		delay_time += 100;
		
		if( adc_delay_time > 7000 )
		{			
			adc_val = ReadADCValue();
			percent = CalculateBatteryLevel(adc_val, &voltage_int);
			adc_delay_time = 0;
		}
		adc_delay_time += 100;
		Enter_SleepMode(); // 最低等级任务 空闲时刻让 CPU 进入低功耗
//		Read_Remaining_stack_space();
  
  }
  /* USER CODE END check_sensor_Task */
}

/* USER CODE BEGIN Header_display_Task */
/**
* @brief Function implementing the display thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_display_Task */
void display_Task(void *argument)
{
  /* USER CODE BEGIN display_Task */
  /* Infinite loop */	

  for(;;)
  {
		ProcessDWINSHOW_gasread();	
		vTaskDelay(pdMS_TO_TICKS(90));	
  }
  /* USER CODE END display_Task */
}

/* USER CODE BEGIN Header_cloud_Task */
/**
* @brief Function implementing the cloud thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_cloud_Task */
void cloud_Task(void *argument)
{
  /* USER CODE BEGIN cloud_Task */
  /* Infinite loop */
/**
* @brief  4G串口3使能
*/	
	__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart3, receiveBuff4G, BUFFER_SIZE4G); // 启动USART3的DMA接收	

  for(;;)
  {
		if(system_cloud_mode == Cloud_4G_MODE)
		{
		switch (ml307aState) 
				{
            case AT:
//								osDelay(200);
                if (sendCmd_4G_3("AT\r\n", "OK","OK",1, 1)) {
                    printf("AT_OK\r\n");
                    ml307aState = CPIN; // CFUN CPIN
										
                } else {
										printf("AT_fail\r\n");
										ml307aState = AT; // AT
                }
                break;
						
						case CPIN:
								osDelay(3000);
                if (sendCmd_4G("AT+CPIN?\r\n","+CPIN: READY", 2, 1)) { //  +CPIN: READY
                    printf("CPIN_OK\r\n");
                    ml307aState = CEREG;
                } else
								{
										printf("CPIN_fail\r\n");
										ml307aState = AT;										
                }
//								osDelay(100);
                break;
								
						case CEREG:
							osDelay(2000);
                if (sendCmd_4G("AT+CEREG?\r\n","+CEREG: 0,1", 2, 1)) {
                    printf("CEREG_OK\r\n");
                    ml307aState = CFUN;
                } else {
                    printf("CEREG_fail\r\n");
										ml307aState = CPIN;
                }
//								osDelay(100);
                break;
						
						case CFUN:
                if (sendCmd_4G_3("AT+CFUN=1\r\n", "OK", "OK", 1, 1)) {
                    printf("CFUN_OK\r\n");
                    ml307aState = TIME;
                } else {
                    printf("CFUN_fail\r\n");
										ml307aState = CEREG; // CFUN CEREG
                }
//								osDelay(100);
                break;
								
						case TIME:
								sendCmd_4G_3("AT+CCLK?\r\n", "OK", "OK", 1, 1);
								epoch_time = parse_cclk_time((char *)receiveBuff4G);
								if (epoch_time != 2) {					
//									printf("unix: %ld\n", epoch_time);
									Set_RTC_Time(epoch_time);  // 设置 RTC
									printCurrentRTCTime();
									ml307aState = MIP_CONNECT; // ml307aState = MIP_CONNECT  MUECONFIG
								}else{
									ml307aState = CFUN;
								}
//								osDelay(100);
								break;
								
						// mqtt		
						case MUECONFIG:
                if (sendCmd_4G_3("AT+MUECONFIG=\"autoconn\",1\r\n", "OK", "OK", 1, 3)) {
                    printf("MUECONFIG_OK\r\n");
                    ml307aState = MDIALUPCFG;
                } else {
                    printf("MUECONFIG_fail\r\n");
										ml307aState = CFUN;
                }
								osDelay(100);
                break;
								
						case MDIALUPCFG:
                if (sendCmd_4G_3("AT+MDIALUPCFG=\"auto\",1\r\n", "OK", "OK", 1, 3)) {
                    printf("MDIALUPCFG_OK\r\n");
                    ml307aState = MQTTCFG_CACHED;// MQTTDISC MQTTCFG_CLEAN MQTTCFG_CACHED
                } else {
										ml307aState = MQTTDISC;
                }
								osDelay(200);
                break;
														
								
						case MQTTCFG_CACHED:
								if (sendCmd_4G_3("AT+MQTTCFG=\"cached\",0,1\r\n", "OK", "OK", 1, 3)) {
                    printf("MQTTCFG_CACHED_OK\r\n");
                    ml307aState = MQTTCONNE;
                } else {
                    printf("MQTTCFG_CACHED_fail\r\n");
										ml307aState = MQTTDISC;
                }
								osDelay(200);
                break;
								
						case MQTTCONNE:
								// 博客测试 106.14.207.159 1883
								// 公司测试 121.199.29.128 7883
								// 阿里平台	47.100.6.214   1883
								if (sendCmd_4G_3("AT+MQTTCONN=0,\"47.100.6.214\",1883,\"BATT|securemode=2,signmethod=hmacsha1,timestamp=1729351701003|\",\"BATT&k1vccLJvsUy\",\"E664F110C5752BDB294C14ADC5594A673C6552B8\"\r\n", "OK", "OK",1, 1)) {// +MQTTURC: \"conn\",0,0
									printf("MQTTCONNE_OK\r\n");
									ml307aState = MQTTSUB;
								}else{
									printf("MQTTCONNE_fail\r\n");
									ml307aState = MQTTDISC;
								}
								osDelay(200);								
								break;
						// sendCmd_4G("AT+MQTTSUB=0,\"/sys/k1vccLJvsUy/BATT/thing/service/property/set\",1\r\n", "OK", 1, 1)
						case MQTTSUB: 
							 if (sendCmd_4G_3("AT+MQTTSUB=0,\"/sys/k1vccLJvsUy/BATT/thing/service/property/set\",1\r\n", "OK", "OK", 1, 1)) { // +MQTTSUB: 0,33243
									printf("MQTTSUB_OK\r\n");
									ml307aState = MQTTSUB1;
								}else{
									printf("MQTTSUB_fail\r\n");
									ml307aState = MQTTDISC;
								}
								osDelay(100);						
								break;
								
						case MQTTSUB1: 
							sprintf(mqtt_sub_topic, "/k1vccLJvsUy/%02X%02X%02X%02X%02X%02X%02X/user/get",
											terminalId[0], terminalId[1], terminalId[2], 
											terminalId[3], terminalId[4], terminalId[5], terminalId[6]);
							sprintf(mqtt_sub_cmd, "AT+MQTTSUB=0,\"%s\",1\r\n", mqtt_sub_topic);
							 if (sendCmd_4G_3(mqtt_sub_cmd, "OK", "OK", 1, 1)) 
								 { 
									printf("MQTTSUB_OK: %s\r\n", mqtt_sub_topic);
									HAL_GPIO_WritePin(V5V_CAN_EN_GPIO_Port, V5V_CAN_EN_Pin, GPIO_PIN_SET); 
									ml307aState = MIP_CONNECT;
								}else{
									printf("MQTTSUB_fail\r\n");
									ml307aState = MQTTDISC;
								}
								osDelay(100);						
								break;
								
					case MQTTDISC:
								if (sendCmd_4G_3("AT+MQTTDISC=0\r\n", "OK", "OK", 1, 3)) {
                    printf("AT+MQTTDISC_OK\r\n");
                    ml307aState = MUECONFIG;
                } else {
                    printf("AT+MQTTDISC_fail\r\n");
										ml307aState = MUECONFIG;
                }
								osDelay(200);
                break;
								
						// tcp										
							case MIP_CONNECT:
								// 私有测试 183.230.40.96 1883
								// 公司测试 121.199.29.128 7342
								// 重庆正式平台 47.109.73.167 10001
								// 重庆测试平台 47.109.73.167 10002
								// TCP模拟  183.230.40.96 1883
							if (sendCmd_4G_3("AT+MIPOPEN=0,\"TCP\",\"47.109.73.167\",10002\r\n", "OK", "+MIPOPEN: 0,0", 5, 2)) {// +MIPOPEN: 0,0
								
//								if (sendCmd_4G_2("AT+MIPOPEN=0,\"TCP\",\"47.109.73.167\",10001,10,2\r\n", "+MIPOPEN: 0,0", "OK",5, 2)) {// +MIPOPEN: 0,0
											printf("MIPOPEN_TCP_IP_OK\r\n");

											ml307aState = MIPCFG; // MIPSEND
								} else {
											printf("MIPOPEN_TCP_IP_fail\r\n");
											if(sendCmd_4G_3("AT+MIPCLOSE=0\r\n", "OK", "OK", 5, 1)){
												printf("MIPOPEN_fail\r\n");
											}											
											ml307aState = MIPCLOSE; // MIP_CONNECT
                }
//								osDelay(100);
                break;
							
							case MIPCFG:
								// 设置命令发送和接收数据格式
								if (sendCmd_4G_3("AT+MIPCFG=\"encoding\",0,1,1\r\n", "OK", "OK", 1, 1)) {
									
											ml307aState = MIP_REGISTER; // MIPSEND
											printf("MIPCFG_OK\r\n");
									
								} else {										
											ml307aState = MIP_CONNECT;
											printf("MIPCFG_fail\r\n");
                }
//								osDelay(100);
                break;
								
							case MIPCLOSE:
								mipclose_count++;
								if (mipclose_count >= 10)
								{
										ml307aState = AT;             // 强制跳转 AT 状态
										
										printf("MIPCLOSE_max_retries,to AT,%d\r\n",mipclose_count);

								}
								if (mipclose_count >= 100)
								{
										mipclose_count = 0;           // 重置次数
										NVIC_SystemReset();
										break;                        // 直接跳出，不再继续执行下面逻辑
								}
								if (sendCmd_4G_3("AT+MIPCLOSE=0,0\r\n", "+MIPCLOSE: 0", "+MIPCLOSE: 0", 2, 1)) {
											ml307aState = MIP_CONNECT; 
											printf("MIPCLOSE_OK\r\n");
								} else {										
											ml307aState = TIME;
											printf("MIPCLOSE_fail\r\n");
                }
//								osDelay(300);
                break;
							
							case MDIALUP:
//								sendCmd_4G("AT+MDIALUP?\r\n", "OK", 1, 1);
								sendCmd_4G_3("AT+CSQ\r\n", "OK", "OK", 1, 1);
								ml307aState = MIPCLOSE; 
//								osDelay(100);
                break;
								
							// 注册 7E0100002d202412040001000100000000000000000000000000000000000000000000000000000000002024000000010000d5e3413939393939757E
							case MIP_REGISTER:
//								printf("MIP_REGISTER\r\n");
								osDelay(3000);
								if(0 == Send_Register()){									
									REGISTER_OK_start_flag = true;
									last_system_level = -1;
									ml307aState = Systemwarninglevel;  // MIP_senddata
									
								}else{
									ml307aState = MDIALUP; // MIPCLOSE
									REGISTER_OK_start_flag = false;
//									printf("MIPCLOSE\r\n");
								}
								
//								osDelay(100);
                break;
								
						// 心跳 7E000200002024120400010001107E
						case Heartbeat:
						{
								gas_start_read_flag = false;
								if( Send_Heartbeat() )
								{
									REGISTER_OK_start_flag = false;
									ml307aState = MIPCLOSE;
								}
								gas_start_read_flag = true;
								uint32_t delay_time = 0;
								while (delay_time < flash_data.heart_upload_frequency * 1000)
								{
										// 检查系统状态，如果不再是 LEVEL_0 立即退出
										if (system_level != SYSTEM_LEVEL_0)
										{	break;}
										osDelay(100);
										delay_time += 100;
								}								
                break;
						}		
						case Systemwarninglevel:
								if(Send_systemlevel())
								{
									REGISTER_OK_start_flag = false;
									ml307aState = MIPCLOSE;
								}
								ml307aState = Remote;
							 break;
						
						case Remote:
									{
											uint32_t start_tick = osKernelGetTickCount();
											uint32_t last_remote_tick = start_tick; // 记录 Send_Remote 发送时间
											uint32_t last_heartbeat_tick = start_tick; // 记录 Send_Heartbeat 发送时间
											uint32_t last_sensorline_tick = start_tick;  // 记录 sensorline 发送时间
											
											while (1)
											{
													uint32_t current_tick = osKernelGetTickCount();
													bool task_executed = false; // 标志是否执行了任务
													if(system_level == SYSTEM_LEVEL_0)
													{
														send_remote_uploadfrequency = flash_data.mainboard_upload_frequency * 30 ;
													}
													if(system_level == SYSTEM_LEVEL_1 || system_level == SYSTEM_LEVEL_2)
													{
														send_remote_uploadfrequency = flash_data.mainboard_upload_frequency;
													}				
													// 发送 Send_Remote()，仅当 controltransmit_flag == 0 且达到发送间隔
													if (flash_data.controltransmit_flag == 0 && 
														 (current_tick - last_remote_tick) >= send_remote_uploadfrequency * 1000)
													{
															HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 4G UART0_DTR低电平唤醒
															Send_Remote();														
															last_remote_tick = current_tick;  // 记录 Remote 发送时间
															task_executed = true; // 记录任务已执行
													}
													
													if ((current_tick - last_heartbeat_tick) >= flash_data.heart_upload_frequency * 1000)
													{
														HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 4G UART0_DTR低电平唤醒
														// 发送心跳
														if (Send_Heartbeat())  
														{
																REGISTER_OK_start_flag = false;
																ml307aState = MIPCLOSE;
																break;  // 退出 while(1)，结束 Remote 状态
														}
														last_heartbeat_tick = current_tick;
														task_executed = true; // 记录任务已执行
													}	
													
													// 发送传感器在线情况，仅当达到 sensoronline_upload_frequency
													if ((current_tick - last_sensorline_tick) >= flash_data.sensoronline_upload_frequency * 1000)
													{
															HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 4G UART0_DTR低电平唤醒
															if (Send_sensorline())
															{
																REGISTER_OK_start_flag = false;
																ml307aState = MIPCLOSE;
																break;  // 退出 while(1)
															}
															last_sensorline_tick = current_tick;  // 记录 sensorline 发送时间
															task_executed = true; // 记录任务已执行
													}
													if(system_level != last_system_level)
													{
														printf("System_Level_Changed: %d\n", system_level);
														check_trigger_source();
														last_system_level = system_level;
														ml307aState = Systemwarninglevel;
														break;
													}
													// **发送完后立即进入 SLEEP**
													if (task_executed)
													{		
															sendCmd_4G_3("AT+MLPMCFG=\"sleepmode\",2,0\r\n", "OK", "OK", 1, 1);
															HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 4G UART0_DTR高电平休眠
															Enter_SleepMode(); // 让 CPU 进入低功耗
															
													}
													osDelay(10); 
											}
											break;
									}					
							case IDLE0:
									
//								if (sendCmd_4G("AT+MGNSSLOC=1\r\n", "OK", 1, 1)) { // AT+MNTP  // AT+CCLK?
////									sendCmd_4G("AT+CCLK?\r\n", "OK", 1, 1);	
//										ml307aState = IDLE0;	
//								} else {										
//											printf("AT+MNTP_fail\r\n");
//                }
							
						
//								if (sendCmd_4G("AT+MGNSS=1\r\n", "OK", 1, 1)) {
//										ml307aState = IDLE1;	
//								} else {										
//											printf("AT+MGNSSLOC=0_fail\r\n");
//									ml307aState = IDLE1;
//                }
								osDelay(100);
                break;
								
						case IDLE:

//								Send_Remote();
						
								if (sendCmd_4G("AT+MGNSSLOC?\r\n", "OK", 1, 1)) {
										ml307aState = IDLE0;	
								} else {										
											printf("AT+MGNSSLOC=0_fail\r\n");
									ml307aState = IDLE0;
                }
								osDelay(300);
                break;
								
						case IDLE1:
//								Send_Remote();						
								if (sendCmd_4G("AT+MGNSSLOC\r\n", "OK", 1, 1)) {
										ml307aState = IDLE0;	
								} else {										
											printf("AT+MGNSSLOC_fail\r\n");
									ml307aState = IDLE0;
                }
								osDelay(300);
                break;
			 
            default:
//								HAL_IWDG_Refresh(&hiwdg);
                ml307aState = AT;
								
                break;
        }
			}
		else if(system_cloud_mode == Cloud_WIFI_MODE)
		{
//			static uint8_t rst_fail_count = 0;  // 记录AT失败次数
			
			switch(wifistate)
			{	
							
				case WIFI_AT:		
				{					
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT\r\n");
							cp_keywords[0] = "OK";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
							if(result == 0)
							printf("WIFI_AT_OK\r\n");
							wifistate = WIFI_CWMODE;						
							break;
				}	
				case WIFI_RESTORE:		
				{					
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+RESTORE\r\n");
							cp_keywords[0] = "+INIT:DONE,0";
							osDelay(500);
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 2000);
							switch (result)
							{
									case 0:
											printf("WIFI_RESTORE_OK\r\n");
											wifistate = WIFI_CWMODE;
											break;
									default:
											osDelay(1000);
											printf("WIFI_RESTORE_UNKNOWN\r\n");
											HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); // 低电平睡眠
											osDelay(1000);
											HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); // 高电平唤醒
											wifistate = WIFI_RESTORE;
											break;
							}							
							break;
				}
				case WIFI_CWMODE:	
				{
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+CWMODE=0\r\n");
							cp_keywords[0] = "OK";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
							switch (result)
							{
									case 0:
											printf("WIFI_CWMODE_OK\r\n");
											wifistate = WIFI_RST; // WIFI_RST  WIFI_DPM
											break;
									default:
											printf("WIFI_CWMODE_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}
				
				case WIFI_RST:
				{
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+RST\r\n");
							cp_keywords[0] = "+INIT:DONE,0";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 2000);	
							switch (result)
							{
									case 0:
											printf("WIFI_RST_OK\r\n");
											wifistate = WIFI_TCPDATAMODE;
											break;
									default:
											printf("WIFI_RST_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}
				case WIFI_TCPDATAMODE:	
				{
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+TCPDATAMODE=0\r\n"); // 0以文本形式发送。1以字符串形式发送
							cp_keywords[0] = "OK";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
							switch (result)
							{
									case 0:
											printf("WIFI_TCPDATAMODE_OK\r\n");
											wifistate = WIFI_CWSTAT;
											break;
									default:
											printf("WIFI_TCPDATAMODE_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}				
				case WIFI_CWSTAT:
				{
							const char* cp_keywords[5];
							int result;
							sendATOnly("AT+CWSTAT\r\n");
							cp_keywords[0] = "wpa_state=COMPLETED";
							cp_keywords[1] = "wpa_state=DISCONNECTED";
							cp_keywords[2] = "wpa_state=SCANNING";
							cp_keywords[3] = "wpa_state=ASSOCIATED";
							cp_keywords[4] = "wpa_state=4WAY_HANDSHAKE";
							result = wait_uart3_multi_response(cp_keywords, 5, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 3000);
							switch (result)
							{
									case 0:
											printf("WIFI_CWSTAT_COMPLETED\r\n");
											wifistate = WIFI_DPM; // WIFI_CIPSTART
											break;
									case 1:
											printf("WIFI_CWSTAT_DISCONNECTED\r\n");
											wifistate = WIFI_CWJAP;
											break;
									case 2:
											printf("WIFI_CWSTAT_SCANNING\r\n");
											wifistate = WIFI_CWJAP;
											break;
									case 3:
											printf("WIFI_CWSTAT_ASSOCIATED\r\n");
											wifistate = WIFI_CIPSTART;
											break;
									case 4:
											printf("WIFI_CWSTAT_4WAY_HANDSHAKE\r\n");
											wifistate = WIFI_CWQAP;
											break;
									
									default:
											printf("WIFI_CWSTAT_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}
				case WIFI_DPM:	
				{
							const char* cp_keywords[1];
							int result = -1;
							int retry = 0;
							for (retry = 0; retry < 3; retry++)
							{
								sendATOnly("AT+DPM=1,0\r\n"); // 睡眠SLEEP3模式
								cp_keywords[0] = "OK";
								result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
								if (result == 0)
								{
										break;
								}
							}
							switch (result)
							{
									case 0:
											printf("WIFI_DPM_OK\r\n");
											wifistate = WIFI_IDLE;
											break;
									default:
											printf("WIFI_DPM_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}
				case WIFI_IDLE:	
				{
							const char* cp_keywords[1];
							int result;
							cp_keywords[0] = "+INIT:DONE,0";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
							switch (result)
							{
									case 0:
											printf("WIFI_RST_OK\r\n");
											wifistate = WIFI_CIPSTART;
											break;
									default:
											printf("WIFI_RST_UNKNOWN\r\n");
											wifistate = WIFI_IDLE;
											break;
							}
							break;
				}
				case WIFI_CWQAP: // 断开AP连接
				{
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+CWQAP\r\n");
							cp_keywords[0] = "OK";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
							switch (result)
							{
									case 0:
											printf("WIFI_CWQAP_OK\r\n");
											wifistate = WIFI_CWJAP;
											break;
									default:
											printf("WIFI_CWQAP_UNKNOWN\r\n");
											wifistate = WIFI_RESTORE;
											break;
							}
							break;
				}					
				case WIFI_CWJAP:
				{	
//printf("WiFi SSID (ASCII): %s\n", wifi_ssid);
//printf("WiFi SSID (HEX): ");
//for (int i = 0; i < strlen((char *)wifi_ssid); i++) {
//		printf("%02X ", wifi_ssid[i]);
//}
//printf("\n");
//printf("WiFi Password (ASCII): %s\n", wifi_password);
//printf("WiFi Password (HEX): ");
//for (int i = 0; i < strlen((char *)wifi_password); i++) {
//		printf("%02X ", wifi_password[i]);
//}
//printf("\n");
								if(dwin_state != DWIN_STATE_AVIATION)
								{
									Load_WIFI_From_Flash();
								}
								printf("WIFI.SSID: %s\n", wifi_config.ssid);
								printf("WIFI.Password: %s\n", wifi_config.password);
								const char* cp_keywords[5];
								int result;
								sendWifiJoinCommand(wifi_config.ssid, wifi_config.password);
								cp_keywords[0] = "+CWJAP:1";
								cp_keywords[1] = "ERROR:-14";
								cp_keywords[2] = "+CWDAP:0,DEAUTH";	// 与已连接的AP断开连接
								cp_keywords[3] = "+CWJAP:0,WRONGPWD";	// WPA 4次握手失败，预共享密钥（密码）可能不正确
								cp_keywords[4] = "+CWJAP:0,TIMEOUT";	// 连续尝试连接后，连接尝试失败。
								result = wait_uart3_multi_response(cp_keywords, 5, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 3000);						
								switch (result)
								{
										case 0:
												printf("WIFI_CWJAP_OK\r\n");
												wifistate = WIFI_DPM; // WIFI_CIPSTART WIFI_DPM
												break;
										case 1:
												printf("WIFI_CWJAP_ERROR:-14\r\n");
												wifistate = WIFI_CWJAP;
												break;
										case 2:
												printf("WIFI_CWJAP_+CWDAP:0,DEAUTH\r\n");
												wifistate = WIFI_CWJAP;
												break;
										case 3:
												printf("WIFI_CWJAP_+CWJAP:0,WRONGPWD\r\n");
												wifistate = WIFI_RESTORE;
												break;
										case 4:
												printf("WIFI_CWJAP_+CWJAP:0,TIMEOUT\r\n");
												wifistate = WIFI_RESTORE;
												break;;
										default:
												printf("WIFI_CWJAP_UNKNOWN\r\n");
												wifistate = WIFI_CWJAP;
												break;
								}
                break;
				}
							
				case WIFI_CIPSTART:	
				{					
							// 47.109.73.167,10001	水陆平台
							// 36.110.15.166,10002	航空平台公网
							// 10.90.0.14,10002			航空平台内网
					
							// 192.168.0.14,8080		测试平台1
							// 192.168.0.41,8080		测试平台2
							// 192.168.0.63,8080		公司测试平台3
							
							control_wifi_wakeup(true);
							sendATOnly("AT+CLRDPMSLPEXT\r\n");
							osDelay(100);
							const char* cp_keywords[3];
							cp_keywords[0] = "+CIPSTART:";
							cp_keywords[1] = "ERROR:-14";
							cp_keywords[2] = "ERROR:-736";
							int result = -1;
							int retry = 0;
							for (retry = 0; retry < 3; retry++)
							{
								sendATOnly("AT+CIPSTART=10.90.0.14,10002,0\r\n");								
								result = wait_uart3_multi_response(cp_keywords, 3, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 3000);						
								if (result == 0)
								{
										break;
								}
							}
							if (result == 0)
							{
								int port_id = extract_cip_port((const char *)receiveBuff4G_MIPURC);
								printf("WIFI_CIPSTART_OK, ID = %d\r\n", port_id);
								g_cip_id = port_id;
								wifistate = WIFI_CIPSEND_Register; // WIFI_CIPSEND_Register WIFI_CIPSNTP
								break;
							}
							else
							{
								switch (result)
								{
										case 1:
												printf("WIFI_CIPSTART_ERROR:-14\r\n");
												wifistate = WIFI_RESTORE;
												break;
										case 2:
												printf("WIFI_CIPSTART_ERROR:-736\r\n");
												wifistate = WIFI_RESTORE;
												break;
										default:
												printf("WIFI_CIPSTART_UNKNOWN\r\n");
												wifistate = WIFI_RESTORE;
												break;
								}
								break;
							}
								
								
				}
				case WIFI_CIPSNTP:	// 航空局域网连不上公网 连不上SNTP
				{
							// ntp.aliyun.com
							// cn.pool.ntp.org
							// ntp.ntsc.ac.cn（中国国家授时中心）
							const char* cp_keywords[2];
							int result;
							sendATOnly("AT+CIPSNTP=1,\"ntp.ntsc.ac.cn\",123\r\n");
							cp_keywords[0] = "OK";
							cp_keywords[1] = "+CWDAP:0,DEAUTH";
							result = wait_uart3_multi_response(cp_keywords, 2, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 2000);
							switch (result)
							{
									case 0:
											printf("WIFI_CIPSNTP_OK\r\n");
											wifistate = WIFI_TZONE;
											break;
									case 2:
											printf("WIFI_CIPSNTP_again\r\n");
											wifistate = WIFI_CIPSNTP;
											break;
									default:
											printf("WIFI_CIPSNTP_UNKNOWN\r\n");
											wifistate = WIFI_TCPDATAMODE;
											break;
							}
							break;
				}
				
				case WIFI_TZONE:	
				{
							const char* cp_keywords[1];
							int result;
							sendATOnly("AT+TZONE=0\r\n"); // 28800为+8时区
							cp_keywords[0] = "OK";
							result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);
							switch (result)
							{
									case 0:
											printf("WIFI_TZONE_OK\r\n");
											wifistate = WIFI_TIME;
											break;
									default:
											printf("WIFI_TZONE_UNKNOWN\r\n");
											wifistate = WIFI_TCPDATAMODE;
											break;
							}
							break;
				}				
				case WIFI_TIME:
				{
						const char* cp_keywords[1];
						int result;
						int retry_count = 0;
						const int max_retry = 6;

						while (retry_count < max_retry) {
								sendATOnly("AT+TIME=?\r\n");
								cp_keywords[0] = "+TIME:";
								result = wait_uart3_multi_response(cp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);

								if (result == 0) {
										epoch_time = Parse_WIFI_Time_To_Epoch((char*)receiveBuff4G_MIPURC);
										if (epoch_time > 1735689600) { // 判定为有效时间（大于2025年）
												printf("WIFI_TIME_OK\r\n");
												Set_RTC_Time(epoch_time);  // 设置 RTC
												printCurrentRTCTime();
												break;
										} else {
												printf("TIME invalid (epoch: %ld), retrying\r\n", epoch_time);
										}
								} else {
										printf("WIFI_TIME_UNKNOWN, retrying\r\n");
								}

								retry_count++;
								vTaskDelay(pdMS_TO_TICKS(1000)); // 等待 1 秒再发
						}

						if (retry_count >= max_retry) {
//								printf("TIME fetch failed, using RTC fallback.\r\n");
								epoch_time = Get_RTC_Time();
								printCurrentRTCTime();
						}

						wifistate = WIFI_CIPSEND_Register;
						break;
				}

				case WIFI_CIPSEND_Register:
				{
						const char* cp_keywords[2];
						cp_keywords[0] = "+TRDTC:";
						cp_keywords[1] = "ERROR:-4"; // tcp 客户端 socket 与服务器断开了
						int result;
						int retry_count = 0;
						bool success = false;
						while (retry_count < 5)
						{
							WIFI_Send_Register(1);	
							osDelay (500);							
							result = wait_uart3_multi_response(cp_keywords, 2, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
							if (result == 0) // 收到 OK
							{
									printf("WIFI_Register_OK\r\n");
									REGISTER_OK_start_flag = true;
									wifistate = WIFI_unixtime;
									success = true;
									break;
							}
							else
							{
								retry_count++;
								printf("WIFI_Register_Retry %d failed\r\n", retry_count);
								osDelay (300);
							}							
						}
							
						if (!success) // 重试 5 次都失败
						{
								if (result == 1) // ERROR:-4
								{
										printf("WIFI_Register_ERROR:-4\r\n");
								}
								else 
								{
										printf("WIFI_Register_UNKNOWN\r\n");
								}

								REGISTER_OK_start_flag = false;
								wifistate = WIFI_RESTORE;
						}
						break;
				}
				case WIFI_unixtime: 
				{
						const char* cp_keywords[2];
						cp_keywords[0] = "+TRDTC:";
						cp_keywords[1] = "ERROR:-4";
						int result;
						int retry_count = 0;
						bool success = false;
						while (retry_count < 5)
						{
							WIFI_Send_unix(1);
							osDelay (500);
							result = wait_uart3_multi_response(cp_keywords, 2, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
							if (unixtime_reply_received) 
							{
									printf("WIFI_unixtime_OK\r\n");
									printCurrentRTCTime();
									REGISTER_OK_start_flag = true;
									unixtime_reply_received = false;
									wifistate = WIFI_Remote;
									success = true;
									break;
							}
							else
							{
								retry_count++;
								printf("WIFI_unixtime_Retry %d failed\r\n", retry_count);
								osDelay (300);
							}
							
						}
							
						if (!success) // 重试 5 次都失败
						{
								if (result == 1) // ERROR:-4
								{
										printf("WIFI_unixtime_ERROR:-4\r\n");
								}
								else 
								{
										printf("WIFI_unixtime_UNKNOWN\r\n");
								}

								REGISTER_OK_start_flag = false;
								wifistate = WIFI_RESTORE;
						}
						break;
				}				
				case WIFI_Remote:
				{
						uint64_t wifi_start_tick = osKernelGetTickCount();
						uint32_t wifi_last_temp_tick = wifi_start_tick; // 记录 WIFI_Send_Temperature_Data 发送时间
						uint32_t wifi_last_pre_tick = wifi_start_tick; // 记录 WIFI_Send_Pressure_CO_H2_Data 发送时间
						uint32_t wifi_last_heartbeat_tick = wifi_start_tick; // 记录 Send_Heartbeat 发送时间
						uint64_t wifi_last_sensorline_tick = wifi_start_tick;  // 记录 sensorline 发送时间
						static int wifi_sensorline_success_count = 0;

						int result;
						const char* cp_keywords[4];					
						cp_keywords[0] = "OK";
						cp_keywords[1] = "ERROR:-4";
						cp_keywords[2] = "ERROR:-1";
						cp_keywords[3] = "+TRXTC:"; 
						const char* heartcp_keywords[1];					
						heartcp_keywords[0] = "+TRXTC:";
						
						while (1)
						{
								
								uint32_t current_tick = osKernelGetTickCount();
								bool task_executed = false; // 标志是否执行了任务
							
								if(system_level == SYSTEM_LEVEL_0)
								{
									send_remote_uploadfrequency = flash_data.mainboard_upload_frequency * 30 ;
								}
								if(system_level == SYSTEM_LEVEL_1 || system_level == SYSTEM_LEVEL_2)
								{
									send_remote_uploadfrequency = flash_data.mainboard_upload_frequency;
								}
								
								// 发送 温度 压力气体数据，仅当 controltransmit_flag == 0 且达到发送间隔
								if (flash_data.controltransmit_flag == 0 && 
									 (current_tick - wifi_last_temp_tick) >= send_remote_uploadfrequency * 1000)
								{
										control_wifi_wakeup(true);
										// 发送 AT+CLRDPMSLPEXT，并等待 OK 响应
										bool clr_ok = false;
										for (int i = 0; i < 3; i++)  // 最多重试 3 次
										{
											sendATOnly("AT+CLRDPMSLPEXT\r\n");
											if (wait_uart3_multi_response(cp_keywords,4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000)==0) 
											{
													clr_ok = true;
													control_wifi_wakeup(false);
													break;
											}
											osDelay(100);
										}
										if (!clr_ok) {
												printf("AT+CLRDPMSLPEXT failed after retries, skip sending\r\n");
												return;
										}
										
										int retry_count = 0;
										while (retry_count < WIFI_MAX_RETRY)
										{	
												epoch_time = Get_RTC_Time(); // 获取 RTC 时间
												WIFI_Send_Temperature_Data(1,&sensor_data_buffer);															
												result = wait_uart3_multi_response(cp_keywords, 4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
												if (result == 0)
												{
														printf("WIFI_Send_Temperature_Data_OK\r\n");
														REGISTER_OK_start_flag = true;
														wifi_last_temp_tick = current_tick;  // 记录 Remote 发送时间
														task_executed = true; // 记录任务已执行
														break;
												}else{
														retry_count++;
														switch (result)
															{																						
																	case 1:
																			printf("WIFI_Send_Temperature_Data_ERROR:-4\r\n");
																			REGISTER_OK_start_flag = false;
																			break;
																	case 2:
																			printf("WIFI_Send_Temperature_Data_ERROR:-1\r\n");
																			REGISTER_OK_start_flag = false;
																			break;
																	default:
																			printf("WIFI_Send_Temperature_Data_UNKNOWN\r\n");
																			REGISTER_OK_start_flag = false;
																			break;
															}																
												}
												osDelay(100);
									}
									if (retry_count >= WIFI_MAX_RETRY)
									{
											printf("WIFI_Send_Temperature_Data FAILED after 3 retries. Goto WIFI_RESTORE\r\n");
											wifistate = WIFI_RESTORE;
											break;
									}	
								}
								
								if (flash_data.controltransmit_flag == 0 && 
									 (current_tick - wifi_last_pre_tick) >= send_remote_uploadfrequency * 1000)
								{		
										control_wifi_wakeup(true);
										// 发送 AT+CLRDPMSLPEXT，并等待 OK 响应
										bool clr_ok = false;
										for (int i = 0; i < 3; i++)  // 最多重试 3 次
										{
											sendATOnly("AT+CLRDPMSLPEXT\r\n");
											if (wait_uart3_multi_response(cp_keywords,4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000)==0) 
											{
													clr_ok = true;
													control_wifi_wakeup(false);
													break;
											}
											osDelay(100);
										}
										if (!clr_ok) {
												printf("AT+CLRDPMSLPEXT failed after retries, skip sending\r\n");
												return;
										}
										
										
										int retry_count = 0;
										while (retry_count < WIFI_MAX_RETRY)
										{
												epoch_time = Get_RTC_Time(); // 获取 RTC 时间
												WIFI_Send_Pressure_CO_H2_Data(1,&sensor_data_buffer);
												result = wait_uart3_multi_response(cp_keywords, 4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
												if (result == 0)
												{
														printf("WIFI_Send_Pressure_CO_H2_Data_OK\r\n");
														REGISTER_OK_start_flag = true;
														osDelay (20);
//																			flash_write_tempprecoh2_data(flash_temp_prc0h2, 512);
//																			Save_W25_Tempaddress_To_Flash();
														wifi_last_pre_tick = current_tick;  // 记录 Remote 发送时间
														task_executed = true; // 记录任务已执行
														break;
												}else{
														retry_count++;
														switch (result)
														{																			
															case 1:
																	printf("WIFI_Send_Pressure_CO_H2_Data_ERROR:-4\r\n");
																	REGISTER_OK_start_flag = false;
																	break;
															case 2:
																	printf("WIFI_Send_Pressure_CO_H2_Data_ERROR:-1\r\n");
																	REGISTER_OK_start_flag = false;
																	break;
															default:
																	printf("WIFI_Send_Pressure_CO_H2_Data_UNKNOWN\r\n");
																	REGISTER_OK_start_flag = false;
																	break;
														}
										
												}
												osDelay(100);
									}
									if (retry_count >= WIFI_MAX_RETRY)
									{
											printf("WIFI_Send_Pressure_CO_H2_Data FAILED after 3 retries. Goto WIFI_RESTORE\r\n");
											wifistate = WIFI_RESTORE;
											break;
									}
								}
								// 心跳
								if ((current_tick - wifi_last_heartbeat_tick) >= flash_data.heart_upload_frequency * 1000)
								{									
										control_wifi_wakeup(true);
										// 发送 AT+CLRDPMSLPEXT，并等待 OK 响应
										bool clr_ok = false;
										for (int i = 0; i < 3; i++)  // 最多重试 3 次
										{
											sendATOnly("AT+CLRDPMSLPEXT\r\n");
											osDelay(300);
											if (wait_uart3_multi_response(cp_keywords,4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000)==0) 
											{
													clr_ok = true;
													control_wifi_wakeup(false);
													break;
											}
											osDelay(300);
										}
										if (!clr_ok) {
												printf("AT+CLRDPMSLPEXT failed after retries, skip sending\r\n");
												return;
										}
										
										int retry_count = 0;
										while (retry_count < WIFI_MAX_RETRY)
										{
											
												WIFI_Send_Heartbeat(1);
												osDelay (300);
												result = wait_uart3_multi_response(heartcp_keywords, 1, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
												osDelay (500);
												if (heartbeat_reply_received)
												{
														printf("WIFI_Send_Heartbeat_OK\r\n");
														REGISTER_OK_start_flag = true;
														wifi_last_heartbeat_tick = current_tick;
													heartbeat_reply_received = false;  // 清除通用应答已接收标志位
														task_executed = true; // 记录任务已执行
														break;
												}else{
														retry_count++;
														printf("WIFI_Send_Heartbeat_Not received\r\n");
												}	
												osDelay(300);
										}
										if (retry_count >= WIFI_MAX_RETRY)
										{
												printf("WIFI_Send_Heartbeat FAILED after 3 retries. Goto WIFI_RESTORE\r\n");
												wifistate = WIFI_RESTORE;
												break;
										}
								}	
								// 发送传感器在线情况，仅当达到 sensoronline_upload_frequency
								if ((current_tick - wifi_last_sensorline_tick) >= flash_data.sensoronline_upload_frequency * 1000)
								{
										control_wifi_wakeup(true);
										// 发送 AT+CLRDPMSLPEXT，并等待 OK 响应
										bool clr_ok = false;
										for (int i = 0; i < 3; i++)  // 最多重试 3 次
										{
											sendATOnly("AT+CLRDPMSLPEXT\r\n");
											if (wait_uart3_multi_response(cp_keywords,4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000)==0) 
											{
													clr_ok = true;
													control_wifi_wakeup(false);
													break;
											}
											osDelay(100);
										}
										if (!clr_ok) {
												printf("AT+CLRDPMSLPEXT failed after retries, skip sending\r\n");
												return;
										}
										
										int retry_count = 0;
										while (retry_count < WIFI_MAX_RETRY)
										{
												epoch_time = Get_RTC_Time(); // 获取 RTC 时间
												WIFI_Send_sensorline(1);
												result = wait_uart3_multi_response(cp_keywords, 4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
												if (result == 0)
												{
														printf("WIFI_Send_sensorline_OK\r\n");
														REGISTER_OK_start_flag = true;
														wifi_last_sensorline_tick = current_tick;  // 记录 sensorline 发送时间
														task_executed = true; // 记录任务已执行
														wifi_sensorline_success_count++;
														break;
												}else{
														retry_count++;
														switch (result)
														{																		
																case 1:
																		printf("WIFI_Send_sensorline_ERROR:-4\r\n");
																		REGISTER_OK_start_flag = false;
																		break;
																case 2:
																		printf("WIFI_Send_sensorline_ERROR:-1\r\n");
																		REGISTER_OK_start_flag = false;
																		break;
																default:
																		printf("WIFI_Send_sensorline_UNKNOWN\r\n");
																		REGISTER_OK_start_flag = false;
																		break;
														}
												}
												osDelay(100);
											}
											if (retry_count >= WIFI_MAX_RETRY)
											{
													printf("WIFI_Send_sensorline FAILED after 3 retries. Goto WIFI_RESTORE\r\n");
													wifistate = WIFI_RESTORE;
													break;
											}
								}
								
								if(system_level != last_system_level)
								{
										control_wifi_wakeup(true);
										// 发送 AT+CLRDPMSLPEXT，并等待 OK 响应
										bool clr_ok = false;
										for (int i = 0; i < 3; i++)  // 最多重试 3 次
										{
											sendATOnly("AT+CLRDPMSLPEXT\r\n");
											if (wait_uart3_multi_response(cp_keywords,4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000)==0) 
											{
													clr_ok = true;
													control_wifi_wakeup(false);
													break;
											}
											osDelay(100);
										}
										if (!clr_ok) {
												printf("AT+CLRDPMSLPEXT failed after retries, skip sending\r\n");
												return;
										}
										
										int retry_count = 0;
										while (retry_count < WIFI_MAX_RETRY)
										{
											
											printf("System_Level_Changed: %d\n", system_level);
											check_trigger_source(); // 检查触发二级的传感器信息
											epoch_time = Get_RTC_Time(); // 获取 RTC 时间
											WIFI_Send_systemlevel(1);
											result = wait_uart3_multi_response(cp_keywords, 4, (char*)receiveBuff4G_MIPURC, sizeof(receiveBuff4G_MIPURC), 1000);						
											if(result == 0)
											{
												printf("WIFI_Send_systemlevel_OK\r\n");
												REGISTER_OK_start_flag = true;
												task_executed = true; // 记录任务已执行
												last_system_level = system_level;
												break;
											}else{
												retry_count++;	
												switch (result)
												{
														case 1:
																printf("WIFI_Send_systemlevel_ERROR:-4\r\n");
																REGISTER_OK_start_flag = false;
																break;
														case 2:
																printf("WIFI_Send_systemlevel_ERROR:-1\r\n");
																REGISTER_OK_start_flag = false;
																break;
														default:
																printf("WIFI_Send_systemlevel_UNKNOWN\r\n");
																REGISTER_OK_start_flag = false;
																break;
												}
											}
																					
											osDelay(100);											
										}
										if (retry_count >= WIFI_MAX_RETRY)
										{
												printf("WIFI_Send_systemlevel FAILED after 3 retries. Goto WIFI_RESTORE\r\n");
												wifistate = WIFI_RESTORE;
												break;
										}
								}
								if (wifi_sensorline_success_count >= 100)
								{
										wifistate = WIFI_unixtime;
										wifi_sensorline_success_count = 0; // 重置计数
										printf("Reached 100 minutes, switching to WIFI_unixtime\r\n");
								}
								// **发送完后立即进入 SLEEP**
								if (task_executed)
								{		
									if(system_level == SYSTEM_LEVEL_0)
									{
										sendATOnly("AT+SETDPMSLPEXT\r\n");	
									}									
									Enter_SleepMode(); // 让 CPU 进入低功耗
								}
								osDelay(10); 
						}
						break;
				}										
								
				default:
								wifistate = WIFI_AT;			
								break;
			}
		}
  }
  /* USER CODE END cloud_Task */
}

/* USER CODE BEGIN Header_SystemStatus_Task */
/**
* @brief Function implementing the SystemStatus thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_SystemStatus_Task */
void SystemStatus_Task(void *argument)
{
  /* USER CODE BEGIN SystemStatus_Task */
  /* Infinite loop */
	uint16_t gass_counter = 0; // 气体开启计数器
	
  for(;;)
  {
//		if(system_level != last_system_level)
//		{
//				printf("System_Level_Changed: %d\n", system_level);
//				check_trigger_source();
//				last_system_level = system_level;
//				if(REGISTER_OK_start_flag)
//				ml307aState = Systemwarninglevel;
				
//		}		
		
		if (system_level == SYSTEM_LEVEL_1) 
		{
				gass_counter++;
//				dwin_warning_state_level = DWIN_WARNING_LEVEL_1_STATE;
				actuator_powered = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_11) == GPIO_PIN_SET;
				if ( actuator_powered ) 
				{
					control_actuator(false); 		// 关闭电推杆供电
//					HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
//					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET);
					
					actuator_powered_state = actuator_closed;
					printf("actuator_power_closed\n");
				}

				gas_powered = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET;
				if ( gas_powered ) 
				{
					control_gas_sensors(true); 	// 打开气体供电
					printf("gas_power_opened\n");
					if(gass_counter >= 400) // 气体上电后等待40秒再开始读数	
					{
						gas_start_read_flag = true;
						printf("gas_start_read\n");
						gass_counter = 0;
					}	
				} else{
					if(gass_counter >= 400) // 气体上电后等待40秒再开始读数	
					{
						gas_start_read_flag = true;
//						printf("gas_start_read\n");
						gass_counter = 0;
					}
				}
				
				
		}

    osDelay(100);
		
  }
  /* USER CODE END SystemStatus_Task */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void sendWifiJoinCommand(uint8_t *ssid, uint8_t *password) 
{
    char at_command[128];
    sprintf(at_command, "AT+CWJAP=%s,4,2,%s\r\n", ssid, password);
    sendATOnly(at_command);
}

void Send_Remote(void)
{
			sendCmd_4G_3("AT+CCLK?\r\n", "OK", "OK", 1, 1);
			epoch_time = parse_cclk_time((char *)receiveBuff4G);
			if (epoch_time != 2) {					
//				printf("unix: %ld\n", epoch_time);
				Set_RTC_Time(epoch_time);  // 设置 RTC
			}	else {
				epoch_time = Get_RTC_Time(); // 获取 RTC 时间
//        printf("RTC unix: %ld\n", epoch_time);
			}	
			gas_start_read_flag = false;
			if(Send_Temperature_Data(&sensor_data_buffer))
			{
				REGISTER_OK_start_flag = false;
				ml307aState = MIPCLOSE;
			}	
//printf("remote\r\n");
			if(Send_Pressure_CO_H2_Data(&sensor_data_buffer))
			{
				REGISTER_OK_start_flag = false;
				ml307aState = MIPCLOSE;
			}
//				gas_start_read_flag = true;		
			flash_write_tempprecoh2_data(flash_temp_prc0h2, 512);
			Save_W25_Tempaddress_To_Flash();
//			Load_W25_Tempaddress_From_Flash();
			
//			printf("\r\n");
//			for (uint32_t i = 0; i < 512; i++)
//			{
//					printf("%02X ", flash_temp_prc0h2[i]);
//					if ((i + 1) % 16 == 0) 
//							printf("\r\n");
//			}
			

}

void InitializeBoardDataProcess(void)
{

		uint8_t i=0;
	
    for (i = 0; i < MAX_TEMP_NODE_NUM; i++)
    {
			g_canTempRaw[i].NodeId = 0;
			g_canTempRaw[i].PacktSeq = 0;
			g_canTempRaw[i].SliceNum = 0;
			g_canTempRaw[i].SliceMask = 0;	
			
			g_prevdata_temp[i].count_ms = 0;
			g_prevdata_temp[i].recv_flag = 0;
			g_prevdata_temp[i].data[0] = 0;
			g_prevdata_temp[i].data[1] = 0;
			g_prevdata_temp[i].data[2] = 0;
			
			
    }
		
		for(i=0; i<MAX_PRESSURE_NODE_NUM; i++){
			g_prevdata_press[i].count_ms = 0;
			g_prevdata_press[i].recv_flag = 0;
			g_prevdata_press[i].data[0] = 0;
			g_prevdata_press[i].data[1] = 0;
			
		}
		
		for(i=0; i<MAX_H2_NODE_NUM; i++){
			g_prevdata_h2[i].count_ms = 0;
			g_prevdata_h2[i].recv_flag = 0;
			g_prevdata_h2[i].data[0] = 0;
			g_prevdata_h2[i].data[1] = 0;
			g_prevdata_h2[i].data[2] = 0;
			g_prevdata_h2[i].data[3] = 0;
			
		}
		
		for(i=0; i<MAX_CO_NODE_NUM; i++){
			g_prevdata_co[i].count_ms = 0;
			g_prevdata_co[i].recv_flag = 0;
			g_prevdata_co[i].data[0] = 0;
			g_prevdata_co[i].data[1] = 0;
			g_prevdata_co[i].data[2] = 0;
			g_prevdata_co[i].data[3] = 0;			
		}
	
}
void ClearSensorDataBuffer(void) 
{
    memset(&sensor_data_buffer, 0, sizeof(sensor_data_buffer));
		memset(&sensor_dwin_data_buffer, 0, sizeof(sensor_dwin_data_buffer));
	
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) 
{
    CAN_RxHeaderTypeDef RX_Header;
		CanRx_msg can_msg;
		BaseType_t xHigherPriorityTaskWoken;	
		xHigherPriorityTaskWoken = pdFALSE;
	
    if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RX_Header, can_msg.data) == HAL_OK) 
		{
		
			can_msg.ExtId = RX_Header.ExtId;

			// 扩展帧ID为 0x00090000 的消息
			if (RX_Header.ExtId == 0x00090000)
			{
					// 更新阈值
					flash_data.temp_first_threshold = can_msg.data[0];  // 修改一级预警温度阈值
					flash_data.temp_second_threshold  = can_msg.data[1]; // 修改二级报警温度阈值
					flash_data.pressure_threshold  = (can_msg.data[2] << 8) | can_msg.data[3]; // 修改压力阈值
					flash_data.h2_threshold = (can_msg.data[4] << 8) | can_msg.data[5]; // 修改氢气浓度阈值
					flash_data.co_threshold  = (can_msg.data[6] << 8) | can_msg.data[7]; // 修改CO浓度阈值
			}
				
			if(prev_extid != RX_Header.ExtId)
			{
				
				prev_extid = RX_Header.ExtId;

				if (pdPASS != xQueueSendToBackFromISR(can_message_queueHandle, &can_msg, &xHigherPriorityTaskWoken)) 
					{
							// 如果队列满了，删除最旧的数据并插入新数据
							CanRx_msg temp_msg;
							if (xQueueReceiveFromISR(can_message_queueHandle, &temp_msg, &xHigherPriorityTaskWoken) == pdPASS) 
							{
									if (xQueueSendToBackFromISR(can_message_queueHandle, &can_msg, &xHigherPriorityTaskWoken) != pdPASS) 
									{
											printf("Failed to overwrite queue with new data.\r\n");
									}
							} 
							else 
							{
									printf("Queue receive failed unexpectedly.\r\n");
							}
					}
            				
			}else{
//				printf("same extid: 0x%x \r\n", RX_Header.ExtId);
			}		
		} 
}



void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // UART 接收完成回调
{
	Uart2Rx_msg uart2_msg;
	memset(temp_buffer, 0, MAX_FRAME_SIZE);
	// 复制有效数据
	memcpy(temp_buffer, dataReceive2, MAX_FRAME_SIZE);
	if (huart->Instance == USART2) 
	{
			BaseType_t xHigherPriorityTaskWoken = pdFALSE;
			memcpy(uart2_msg.data, dataReceive2, MAX_FRAME_SIZE);
			if (xQueueSendToBackFromISR(uart2rxqueueHandle, &uart2_msg, &xHigherPriorityTaskWoken) != pdPASS) 
			{
					uint8_t discard_buffer[MAX_FRAME_SIZE];
					xQueueReceiveFromISR(uart2rxqueueHandle, &discard_buffer, &xHigherPriorityTaskWoken);
					xQueueSendToBackFromISR(uart2rxqueueHandle, &uart2_msg, &xHigherPriorityTaskWoken);
			}
	}
}
void Uart2_ProcessNextMessage(void)
{   
		uint8_t rxBuffer[40];   
		memset(rxBuffer, 0, 40); 
		
    if (xQueueReceive(uart2rxqueueHandle, rxBuffer,  (TickType_t)0) == pdPASS) // portMAX_DELAY   (TickType_t)0
		{
			
			printf("rxBuffer: ");
			for (int i = 0; i < rx_len; i++) {
					printf("%02X ", rxBuffer[i]);
			}
			printf("\n");
			
        if (is_gas_sensor_response(rxBuffer)) {
            process_gas_sensor(rxBuffer);
            return;
        }
				if (is_mode_response(rxBuffer)) {
            process_mode(rxBuffer);
            return;
        }				
        if (is_electric_actuator_response(rxBuffer)) {
            process_electric_actuator(rxBuffer);
            return;
        }
        if (is_threshold_response(rxBuffer)) {
            process_threshold(rxBuffer);
            return;
        }
        if (is_terminal_response(rxBuffer)) {
            process_terminal_data(rxBuffer);
            return;
        }
				if (is_wifi_response(rxBuffer)) {
						process_wifi(rxBuffer);
            return;
        }
				if (is_restart_response(rxBuffer)) {
						NVIC_SystemReset();
            return;
        }

    }
}

bool is_electric_actuator_response(uint8_t *data)  // 判断是否是电推杆的回应
{
    uint8_t header[] = {0x5A, 0xA5, 0x06, 0x83, 0x10, 0x03, 0x01};
    return memcmp(data, header, sizeof(header)) == 0;
}
void process_electric_actuator(uint8_t *data) // 处理电推杆正反转
{
    uint16_t actuator_cmd = (data[7] << 8) | data[8];

    if (actuator_cmd == 2) {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET);
    } else if (actuator_cmd == 1) {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET);
    }
}

bool is_mode_response(uint8_t *data)  // 判断是否是运行模式的更改
{
    uint8_t header[] = {0x5A, 0xA5, 0x06, 0x83, 0x15, 0x00, 0x01};
    return memcmp(data, header, sizeof(header)) == 0;
}
void process_mode(uint8_t *data) // 是否是模式的更改
{
    uint16_t mode_cmd = (data[7] << 8) | data[8];

    if (mode_cmd == 1) { // 实验模式
			
			system_operatingmode = Debug_MODE;
			dwin_state = DWIN_STATE_DEBUG_SWITCH;
			
    } else if (mode_cmd == 2) { // 发布模式
			
			system_operatingmode = WARNING_MODE;
			dwin_state = DWIN_STATE_WARNING_SWITCH;
			
    }else if (mode_cmd == 3) { // 设置模式
			
			system_operatingmode = SET_MODE;
			dwin_state = DWIN_STATE_SET_SWITCH;
			
    }else if (mode_cmd == 4) { // 航空
			
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); // PC7高电平唤醒WIFI
			HAL_GPIO_WritePin(GPIOC, V3_8V_4G_enable_Pin, GPIO_PIN_SET); // 4G电源3.8V高电平断电
			
			system_cloud_mode = Cloud_WIFI_MODE;		
			dwin_state = DWIN_STATE_AVIATION;
			
//			printf("UART2_Rxcallback_Cloud_WIFI_MODE\n");
			
    }else if (mode_cmd == 5) { // 水陆
			
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); // PC7低电平睡眠WIFI
			HAL_GPIO_WritePin(GPIOC, V3_8V_4G_enable_Pin, GPIO_PIN_RESET); // 4G电源3.8V低电平开启
			
			dwin_state = DWIN_STATE_4G;
			system_cloud_mode = Cloud_4G_MODE;
			flash_clear_all_data();
//			printf("UART2_Rxcallback_Cloud_4G_MODE\n");
			wifior4G_flag = 0;
			Save_wifior4G_flag_To_Flash();
    }else if (mode_cmd == 6) { // 开发者

    }else if (mode_cmd == 7) { // 航空wifi名称密码确定
			flash_clear_all_data();
			Save_WIFI_To_Flash(); // 点击确定后再将wifi账密写入flash
			wifior4G_flag = 1;
			Save_wifior4G_flag_To_Flash();
			dwin_state = DWIN_STATE_AVIATION_READ;
			wifistate = WIFI_RESTORE;
			// 重新启动 cloud_Task
			if (cloudHandle != NULL) {
					vTaskDelete(cloudHandle);  // 删除原任务
					vTaskDelay(pdMS_TO_TICKS(10));   // 等待任务真正被清理
			}
			cloudHandle = osThreadNew(cloud_Task, NULL, &cloud_attributes);			
    }
}
bool is_threshold_response(uint8_t *data) // 判断是否为阈值数据响应
{
    uint8_t header[] = {0x5A, 0xA5, 0x06, 0x83, 0x55};
    return memcmp(data, header, sizeof(header)) == 0;
}
void process_threshold(uint8_t *data) // 处理阈值数据
{
//		Dwinthreshold_msg param_msg;
	
    uint16_t address = (data[4] << 8) | data[5];
		uint16_t dwindata = (data[7] << 8) | data[8];
//		printf("ADDR: 0x%04X, DATA: 0x%04X\n", address, dwindata);
		switch (address) {
				case 0x5500: // SENSOR_TEMP_FIRST_THRESHOLD 0x6000
						flash_data.temp_first_threshold = dwindata;
						printf("temp_first_threshold %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5501: // SENSOR_TEMP_SECOND_THRESHOLD 0x6010
						flash_data.temp_second_threshold = dwindata;
				printf("temp_second_threshold %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5502: // MAINBOARD_UPLOAD_FREQUENCY 0x6020
						flash_data.mainboard_upload_frequency = dwindata;
				printf("mainboard_upload_frequency %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5503: // SMALLBOARD_UPLOAD_FREQUENCY 0x6030
						flash_data.smallboard_upload_frequency = dwindata;
				printf("smallboard_upload_frequency %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5504: // OBJECT_EMISSIVITY 0x6040
						flash_data.object_emissivity = dwindata;
				printf("object_emissivity %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5505: // SENSOR_PRESSURE 0x6050
						flash_data.pressure_threshold = dwindata;
				printf("pressure_threshold %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5506: // SENSOR_CO 0x6060
						flash_data.co_threshold = dwindata;
				printf("co_threshold %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5507: // SENSOR_H2 0x6070
						flash_data.h2_threshold = dwindata;
				printf("h2_threshold %d \n",dwindata);
						CAN_Send_Parameter(0x00110000, &flash_data, 8);
						break;
				case 0x5510: // WIFI账号 0x60A0
						
						printf("h2_threshold %d \n",dwindata);
						break;
				case 0x5530: // WIFI密码 0x60C0

						printf("h2_threshold %d \n",dwindata);
						break;
				default:
						printf("Unknown address: 0x%04X\n", address);
						return;
		}		
}
bool is_wifi_response(uint8_t *data) // 判断是否为WIFI账号密码修改
{
		// 忽略data[2]字节数，帧结构中 5A A5 ?? 83 56
    return (data[0] == 0x5A && 
            data[1] == 0xA5 &&
            data[3] == 0x83 && 
            data[4] == 0x56);
}
void process_wifi(uint8_t *data) // 处理WIFI账号密码修改
{
    uint16_t address = (data[4] << 8) | data[5];
		uint8_t *payload = &data[7];   
		uint8_t len = 0;
	
		// 计算 payload 实际有效长度，遇到 0xFF 0xFF 立即停止
    for (int i = 0; i < 40 ; i++) {
        if (payload[i] == 0xFF) {
            len = i;
					printf("uart2_len1: %d\n", len);
            break;
        }
    }

    // 如果没有遇到 0xFFFF，使用报文中提供的长度，但最多不超过20
    if (len == 0) {
        len = data[2] - 6;
        if (len > 40) len = 40;
			printf("uart2_len2: %d\n", len);
    }
//		printf("uart2_SSID: %s\n", wifi_config.ssid);
//		printf("uart2_SSID: %s\n", wifi_config.ssid);
		
		switch (address) {

				case 0x5610: // WIFI账号 0x60A0						
						memset(wifi_config.ssid, 0, 20);
            memcpy(wifi_config.ssid, payload, len);
            printf("uart2_SSID: %s\n", wifi_config.ssid);
						break;
				
				case 0x5630: // WIFI密码 0x60C0
						memset(wifi_config.password, 0, 20);
            memcpy(wifi_config.password, payload, len);
            printf("uart2_Password: %s\n", wifi_config.password);
						break;
				
				default:
						printf("Unknown address: 0x%04X\n", address);
						return;
		}		
}
bool is_terminal_response(uint8_t *data) // 判断是否为终端数据响应
{
    uint8_t header[] = {0x5A, 0xA5, 0x0C, 0x83, 0x55};
    return memcmp(data, header, sizeof(header)) == 0;
}

void process_terminal_data(uint8_t *data) // 处理终端数据
{
		Dwinterminal_msg terminal_msg;
	
    terminal_msg.Sensoraddress = data[5];
    memcpy(terminal_msg.data, &data[7], sizeof(terminal_msg.data));
		if(terminal_msg.Sensoraddress == 0x08)
		{

				unsigned long long decimal_value = 0;  // 用于存储转换后的十进制数

				// 1. 提取6个字节并转换为十进制
				for (int i = 0; i < 6; i++) {
						decimal_value = (decimal_value << 8) | terminal_msg.data[2 + i];
				}
				// 2. 将 decimal_value 转换成字符串 "20240000000300"
				char decimal_str[15]; // 14 位数字 + 1 个结束符
				sprintf(decimal_str, "%llu", decimal_value);				
				// 3. 按两两一组提取并存储到 terminalId 中（高字节在前）
				for (int i = 0; i < 7; i++) {
						terminalId[i] = (decimal_str[i * 2] - '0') * 16 + (decimal_str[i * 2 + 1] - '0');
				}
				DWIN_terminal_SHOW_flag = true;
		}
		if (terminal_msg.Sensoraddress == 0x09) 
		{
			
				unsigned long long decimal_value = 0;  // 用于存储转换后的十进制数

				// 1. 提取5个字节并转换为十进制
				for (int i = 0; i < 5; i++) {
						decimal_value = (decimal_value << 8) | terminal_msg.data[3 + i];
				}
				// 2. 将 decimal_value 转换成字符串 "202412040002"
				char decimal_str[13]; // 12 位数字 + 1 个结束符
				sprintf(decimal_str, "%llu", decimal_value);
				// 3. 按两两一组提取并存储到 g_board_id 中（高字节在前）
				for (int i = 0; i < 6; i++) {
						g_board_id[i] = (decimal_str[i * 2] - '0') * 16 + (decimal_str[i * 2 + 1] - '0');
				}
				DWIN_terminal_SHOW_flag = true;
		}		
}


bool is_gas_sensor_response(uint8_t *data) // 判断是否为气体传感器响应
{
		// 检查前三个字节是否符合要求
    if (!((data[0] == 0x10 || data[0] == 0x11 || data[0] == 0x12 || 
           data[0] == 0x01 || data[0] == 0x02 || data[0] == 0x03) &&
          data[1] == 0x03 && data[2] == 0x04)) 
    {
        return false; // 帧头不匹配，直接返回 false
    }
    uint16_t crc_received = (data[8] << 8) | data[7];
    uint16_t crc_calculated = calculate_crc16(data, 7);
    return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0;
}


void process_gas_sensor(uint8_t *data) // 处理气体传感器数据
{			
		uint8_t id = data[0];

    if (id < 0x0F) {  // 处理 CO 传感器
        process_single_gas_sensor(SENSOR_CO, id - 1, data, 
                                  co_level_buffer, MAX_CO_NODE_NUM, 
                                  flash_data.co_threshold, &co_system_level,
                                  sensor_data_buffer.co_data, sensor_data_buffer.co_valid);
    } 
    else {  // 处理 H2 传感器
        process_single_gas_sensor(SENSOR_H2, id - 16, data, 
                                  h2_level_buffer, MAX_H2_NODE_NUM, 
                                  flash_data.h2_threshold, &h2_system_level,
                                  sensor_data_buffer.h2_data, sensor_data_buffer.h2_valid);
    }
//		printf("CO System Level: %d\n", co_system_level);
//    printf("H2 System Level: %d\n", h2_system_level);

}
static void process_single_gas_sensor(uint8_t sensor_type, uint8_t id, uint8_t *data, 
                                      float *level_buffer, uint8_t max_nodes,
                                      float threshold, volatile uint8_t *system_level,
                                      uint8_t (*sensor_data_buffer)[4], uint8_t *sensor_valid)
{
    if (id >= max_nodes) return;

    // 解析浮点数数据
    float value = parse_modbus_float(&data[3]);
    level_buffer[id] = value;
    // 标记该传感器为有效，并重置其超时计数
    sensor_valid[id] = 1;
//    printf("Sensor %d value: %.1f\n", id + 1, value);
		// 存储数据
    memcpy(sensor_data_buffer[id], &data[3], 4);
	
		// 更新接收到的时间
    uint32_t current_ms = HAL_GetTick();
    if (sensor_type == SENSOR_CO) {
        g_prevdata_co[id].count_ms = current_ms;  // 更新 CO 传感器的接收时间
				g_prevdata_co[id].recv_flag = 1;
				g_prevdata_co[id].offline_flag = 0;
//				printf("usrt2 co %d current_ms %d\n", id, current_ms);
    } else if (sensor_type == SENSOR_H2) {
        g_prevdata_h2[id].count_ms = current_ms;  // 更新 H2 传感器的接收时间
				g_prevdata_h2[id].recv_flag = 1;
				g_prevdata_h2[id].offline_flag = 0;
//				printf("usrt2 h2 %d current_ms %d\n", id, current_ms);
    }
		
    // 计算最大值，默认掉线传感器值为 0
    float max_value = 0.0f;
    uint8_t valid_count = 0;

    for (int i = 0; i < max_nodes; i++) {
        if (sensor_valid[i]) {  // 传感器有数据
            if (level_buffer[i] > max_value) {
                max_value = level_buffer[i];
            }
            valid_count++;
        }
    }

    // 计算预警等级
    if (valid_count > 0) {  // 只要有至少一个传感器在线
        *system_level = (max_value > threshold) ? 2 : 0;
    } else {
        // **所有传感器掉线，默认给 `system_level` 一个特殊值**
        *system_level = 0;  
        printf("Warning: All %s sensors are offline!\n", sensor_type == SENSOR_CO ? "CO" : "H2");
    }
		// **记录第一个触发二级报警的传感器**
    if (*system_level == 2 && trigger_info[0] == 0) {
        trigger_info[0] = (sensor_type == SENSOR_CO) ? 0xF008 : 0xF006;  // 传感器类型
        trigger_info[1] = id + 1;  // 传感器编号
        trigger_info[2] = (uint8_t)value;  // 触发时的值（转换为整数存储）
    }
    
}


bool is_restart_response(uint8_t *data) 
{
    uint8_t header[] = {0x5A, 0xA5, 0x06, 0x83, 0x16, 0x00, 0x01};
    return memcmp(data, header, sizeof(header)) == 0;
}
void CAN_Send_Parameter(uint32_t node_id , FlashData *flash_data , uint8_t len)
{
	CAN_TxHeaderTypeDef Tx_Header;
	uint32_t TxMailBox;	
	uint32_t ret_status = 0;

	uint8_t msg[8] = {0};  

	msg[0] = flash_data->temp_first_threshold & 0xFF;
	msg[1] = flash_data->temp_second_threshold & 0xFF;
	msg[2] = flash_data->smallboard_upload_frequency & 0xFF;  				// 温度上传频率
	msg[3] = 0x5F;            																				// 发射率
	msg[4] = 0x00;    																								// 压力阈值高字节
	msg[5] = flash_data->pressure_threshold & 0xFF;           				// 压力阈值低字节
	msg[6] = 0x01;           																					// 压力上传频率
	msg[7] = 0x00;
	
	Tx_Header.ExtId = node_id;		
	Tx_Header.IDE = CAN_ID_EXT;
	Tx_Header.RTR = CAN_RTR_DATA;
	Tx_Header.DLC = len;
	ret_status = HAL_CAN_AddTxMessage(&hcan1,&Tx_Header,msg,&TxMailBox);	
	
	if(0 != ret_status){
		printf("HAL_CAN_AddTxMessage failed , ret_status:0x%x \r\n", ret_status);
		printf("hcan->ErrorCode: 0x%x \r\n", hcan1.ErrorCode);
	}
}

void ProcessQueues(void) 
{
		CanRx_msg can_msg;

    while (1) 
    {
                
						if (can_message_queueHandle != NULL && 
                xQueueReceive(can_message_queueHandle, &can_msg, (TickType_t)0 ) == pdPASS)  // (TickType_t)0
            {
//								printf("MidProcess_can\n");
                // 处理 CAN队列 数据
								MidProcessData(&can_msg);

						}

				osDelay(1);
    }
}




void MidProcessData(CanRx_msg *can_msg) // 处理接收到的CAN 数据 
{
		if (can_msg == NULL) return;
	
		Dwin_msg dw_msg;
		Remote_msg rt_msg;

		uint8_t data_type = (can_msg->ExtId >> 28) & 0xFF;
		uint8_t nodeId = (can_msg->ExtId >> 20) & 0xFF;
    uint8_t packtSeq = (can_msg->ExtId >> 12) & 0xFF;
    uint8_t sliceNum = (can_msg->ExtId >> 8) & 0x0F;
    uint8_t sliceId = (can_msg->ExtId >> 4) & 0x0F;

//printf("Raw ExtId: 0x%x, data_type: 0x%x, nodeId: 0x%x, packtSeq: 0x%x, sliceNum: 0x%x, sliceId: 0x%x\r\n",
//		can_msg->ExtId, data_type, nodeId, packtSeq, sliceNum, sliceId);
//for (int i = 0; i < SLICE_DATA_SIZE; i++) 
//{
//		printf("can_msg.data[%d]: 0x%x\r\n", i, can_msg->data[i]);
//}
		if(data_type == 0) return;	
	
		if(nodeId >= 16)//温度数据
		{  
																	
			uint8_t sensor_id = nodeId-16;
			dw_msg.SensorType = SENSOR_TEMPERATURE;
			dw_msg.SensorId = sensor_id;
		
			if (sensor_id >= MAX_TEMP_NODE_NUM) return;

			if (sliceId == 0x1)  // 处理 sliceId 为 0x1 的数据
			{
					// 判断 temp_system_level
					uint8_t templevel = can_msg->data[0]; // 获取当前板的等级
					if( templevel > 3 )
					{templevel = 0;}
					temp_level_buffer[sensor_id] = (templevel <= 2) ? templevel : 0;
				
					uint8_t tempmax_level = 0;  // 先设为 0
					for (uint8_t i = 0; i < MAX_TEMP_NODE_NUM; i++) 
					{
							if (temp_level_buffer[i] > tempmax_level) 
							{
									tempmax_level = temp_level_buffer[i];
							}
					}
					// 判断 tempmax_level 是否稳定
//					if (tempmax_level == last_tempmax_level)
//					{
							// 如果 tempmax_level 不变且时间超过 1.5秒
//							if ((HAL_GetTick() - last_change_time) >= STABLE_TIME_MS)
//							{
//									// 如果 tempmax_level 不变且时间超过去抖时间100ms
//									if ((HAL_GetTick() - last_temp_level_change_time) >= TEMP_DEBOUNCE_TIME_MS)
//									{
											// 根据最大等级来设置 temp_system_level
											temp_system_level = (tempmax_level == 0) ? TEMP_LEVEL_0 : 
																					 (tempmax_level == 1) ? TEMP_LEVEL_1 : TEMP_LEVEL_2;
//											printf("Updated temp_system_level to [%d]\n", temp_system_level);
//									}
//							}
//					}
//					else
//					{
//							// 如果 tempmax_level 发生变化，重置计时
//							last_change_time = HAL_GetTick();  // 更新最后变化的时间戳
//					}

					// 更新 last_tempmax_level 为当前的 tempmax_level
//					last_tempmax_level = tempmax_level;
//					last_temp_level_change_time = HAL_GetTick();  // 更新 temp_level 变更的时间
					
//					printf("temp_system_level[%d]\r\n",temp_system_level);
//printf("Sensor ID: %d, Templevel: %d, Tempmax Level: %d, System Level: %d\n", 
//sensor_id, templevel, tempmax_level, temp_system_level);	
//taskENTER_CRITICAL();
//memset(sensor_dwin_data_buffer.temp_data[sensor_id], 0, 3);
//memcpy(sensor_dwin_data_buffer.temp_data[sensor_id], &can_msg->data[1], 3);
//taskEXIT_CRITICAL();
					
					memset(sensor_dwin_data_buffer.temp_data[sensor_id], 0, 3);
					memcpy(sensor_dwin_data_buffer.temp_data[sensor_id], &can_msg->data[1], 3);
					sensor_dwin_data_buffer.temp_valid[sensor_id] = 1;
//printf("sensor_dwin_data_buffer.Temp Data[%d]: %02X %02X %02X\n", 
//			sensor_id, 
//			sensor_dwin_data_buffer.temp_data[sensor_id][0], 
//			sensor_dwin_data_buffer.temp_data[sensor_id][1], 
//			sensor_dwin_data_buffer.temp_data[sensor_id][2]);	
					
					g_prevdata_temp[sensor_id].count_ms = HAL_GetTick();
					g_prevdata_temp[sensor_id].recv_flag =1;
					g_prevdata_temp[sensor_id].offline_flag =0;

					memcpy(dw_msg.data, &can_msg->data[1], 3);
					memset(&dw_msg.data[3], 0, sizeof(dw_msg.data) - 3);
				
//for (int i = 0; i < 8; i++) 
//{
//		printf("_sensor_id[%d]___dw_msg.data[%d]: 0x%x\r\n",sensor_id, i, dw_msg.data[i]);
//}
//for (int sensor_id = 0; sensor_id < 30; sensor_id++) 
//{
//		 printf("sensor_dwin_data_buffer.Temp Data[%d]: %02X %02X %02X\n", 
//            sensor_id, 
//            sensor_dwin_data_buffer.temp_data[sensor_id][0], 
//            sensor_dwin_data_buffer.temp_data[sensor_id][1], 
//            sensor_dwin_data_buffer.temp_data[sensor_id][2]);
//}

					g_canTempRaw[sensor_id].data[0] = can_msg->data[5];  // 第6个字节 横坐标
					g_canTempRaw[sensor_id].data[1] = can_msg->data[6];  // 第7个字节 纵坐标
					g_canTempRaw[sensor_id].data[2] = can_msg->data[7];  // 第8个字节 九宫格第一个值
					Ambient_temperature = can_msg->data[4]; 		 // 第4个字节 环境温度 Ambient_temperature
//					if (dwin_power_state != dwin_power_closed && display_message_queueHandle)
//					{
//							xQueueSendToBack(display_message_queueHandle, &dw_msg, (TickType_t)0);
//					}
			}
			else if (sliceId == 0x2)  // 处理 sliceId 为 0x2 的数据
			{
					if (g_canTempRaw[sensor_id].SliceMask == 0)
					{
							g_canTempRaw[sensor_id].PacktSeq = packtSeq;
							g_canTempRaw[sensor_id].SliceNum = sliceNum;
					}
					else if (g_canTempRaw[sensor_id].PacktSeq != packtSeq)
					{
							// 拼包可能出错，丢掉不完整的数据
							g_canTempRaw[sensor_id].SliceMask = 0;
							g_canTempRaw[sensor_id].PacktSeq = packtSeq;
							g_canTempRaw[sensor_id].SliceNum = sliceNum;
					}

					if (sliceId <= MAX_SLICE_NUM)
					{
							memcpy(g_canTempRaw[sensor_id].data + 3, can_msg->data, SLICE_DATA_SIZE);
							g_canTempRaw[sensor_id].data[11] = Ambient_temperature;
							g_canTempRaw[sensor_id].SliceMask |= (1 << sliceId);
					}

//printf("g_canTempRaw[%d].data: ", sensor_id);
//for (int i = 0; i < 11; i++) 
//{
//    printf("0x%02X ", g_canTempRaw[sensor_id].data[i]);
//}
//printf("\n");

					// 判断数据是否收齐
					uint16_t tmp_mask = 0;
					for (uint8_t i = 0; i < g_canTempRaw[sensor_id].SliceNum; i++)
					{
							tmp_mask |= (1 << i);
					}
					if (tmp_mask + 1 == g_canTempRaw[sensor_id].SliceMask)
					{
							g_canTempRaw[sensor_id].Finished = 1;
					}
					if (g_canTempRaw[sensor_id].Finished == 1)
					{
							memcpy(rt_msg.data, g_canTempRaw[sensor_id].data, SLICE_DATA_SIZE * MAX_SLICE_NUM);
							rt_msg.SensorId = sensor_id;
							rt_msg.SensorType = SENSOR_TEMPERATURE;
						
//printf("yun g_canTempRaw[%d].data: ", sensor_id);
//for (int i = 0; i < 12; i++) 
//{
//    printf("0x%02X ", g_canTempRaw[sensor_id].data[i]);
//}
//printf("\n");

//printf("rt_msg.data: ");
//for (int i = 0; i < SLICE_DATA_SIZE * MAX_SLICE_NUM; i++) 
//{
//    printf("0x%02X ", rt_msg.data[i]);
//}
//printf("\n");															
							if (cloud_message_queueHandle)
							{
									xQueueSendToBack(cloud_message_queueHandle, &rt_msg, (TickType_t)0);
								
									uint8_t temp_data_id = rt_msg.SensorId;
									memcpy(sensor_data_buffer.temp_data[temp_data_id], rt_msg.data, 12);
									sensor_data_buffer.temp_valid[temp_data_id] = 1;
								
//									check_can = false;
							}
							// 清空 g_canTempRaw，准备下一次接收数据
							memset(&g_canTempRaw[sensor_id], 0, sizeof(g_canTempRaw[sensor_id]));
					}
				}
//			osDelay(1);
		}
		else if( nodeId >= 2) //压力数据
		{
			//发送给 迪文屏一份 
			dw_msg.SensorType = SENSOR_PRESSURE; 
			uint8_t pre_SensorId = nodeId - 2; //id 从0 开始 
			dw_msg.SensorId = pre_SensorId;
		
			// 判断 pre_system_level
			uint8_t prelevel = can_msg->data[0];
			pre_level_buffer[pre_SensorId] = (prelevel == 2) ? 2 : 0;
			
			uint8_t premax_level = 0; 
			for(uint8_t i = 0; i < MAX_PRESSURE_NODE_NUM; i++)
			{
				if(pre_level_buffer[i] > premax_level)
				{
					premax_level = temp_level_buffer[i];
				}
			}
			
			// 根据最大等级设置 pre_system_level
			pre_system_level = (premax_level == 0) ? PRE_LEVEL_0 : PRE_LEVEL_2;
			memcpy(dw_msg.data, &can_msg->data[1], 2);
			
			g_prevdata_press[pre_SensorId].count_ms = HAL_GetTick();
			g_prevdata_press[pre_SensorId].recv_flag =1;
			g_prevdata_press[pre_SensorId].offline_flag =0;
			
			uint8_t pressure_data_id = pre_SensorId;
			memcpy(sensor_dwin_data_buffer.pressure_data[pressure_data_id], dw_msg.data, 2);
			sensor_dwin_data_buffer.pressure_valid[pressure_data_id] = 1;
			
//			if (dwin_power_state != dwin_power_closed && display_message_queueHandle)
//			{
//					xQueueSendToBack(display_message_queueHandle, &dw_msg, (TickType_t)0);
//			}
			
			//发送给 4G 一份 
			rt_msg.SensorType = SENSOR_PRESSURE;
			rt_msg.SensorId = dw_msg.SensorId;
			memcpy(rt_msg.data, &can_msg->data[1], 2);
			
			if (cloud_message_queueHandle)
			{
					xQueueSendToBack(cloud_message_queueHandle, &rt_msg, (TickType_t)0);
					
					uint8_t id = rt_msg.SensorId;
					memcpy(sensor_data_buffer.pressure_data[id], rt_msg.data, 2);
					sensor_data_buffer.pressure_valid[id] = 1;
			}
//			osDelay(10);
		}
}



void print_SensorDataBuffer(SensorDataBuffer *buffer)
{
    printf("------ Sensor Data Buffer ------\n");

    // 打印温度数据
    printf("\n[Temperature Data]\n");
    for (uint8_t i = 0; i < MAX_TEMP_NODE_NUM; i++)
    {
//        if (buffer->temp_valid[i])
//        {
            printf("Temp[%d]: ", i);
            for (uint8_t j = 0; j < 11; j++)
            {
                printf("%02X ", buffer->temp_data[i][j]);
            }
            printf("\n");
//        }
    }

    // 打印压力数据
    printf("\n[Pressure Data]\n");
    for (uint8_t i = 0; i < MAX_PRESSURE_NODE_NUM; i++)
    {
        if (buffer->pressure_valid[i])
        {
            printf("Pressure[%d]: %02X %02X\n", i, buffer->pressure_data[i][0], buffer->pressure_data[i][1]);
        }
    }

    // 打印 CO 数据
    printf("\n[CO Data]\n");
    for (uint8_t i = 0; i < MAX_CO_NODE_NUM; i++)
    {
        if (buffer->co_valid[i])
        {
            printf("CO[%d]: %02X %02X %02X %02X\n", i, 
                buffer->co_data[i][0], buffer->co_data[i][1], buffer->co_data[i][2], buffer->co_data[i][3]);
        }
    }

    // 打印 H2 数据
    printf("\n[H2 Data]\n");
    for (uint8_t i = 0; i < MAX_H2_NODE_NUM; i++)
    {
        if (buffer->h2_valid[i])
        {
            printf("H2[%d]: %02X %02X %02X %02X\n", i, 
                buffer->h2_data[i][0], buffer->h2_data[i][1], buffer->h2_data[i][2], buffer->h2_data[i][3]);
        }
    }

    printf("------ End of Sensor Data ------\n");
}


void DWIN_STARTSHOW(void)
{
	if(DWIN_STARTSHOW_flag ==1)
	{
		DWIN_STARTSHOW_count = 1;
		DWIN_stopsend_flag = false;
		printf("DWIN_STARTSHOW_flag =1\n");
		
		DWIN_START_CHECK();
		
		vTaskDelay(pdMS_TO_TICKS(500));
		SendWENBENDWIN(0x2990,"DC2025_T2"); // 屏保界面版本号
//		vTaskDelay(pdMS_TO_TICKS(100));
//		SendASCIIHEXNDWIN(0x4000, versionmessage, versionmessage_length);// 版本: DC2025_T2
//		vTaskDelay(pdMS_TO_TICKS(100));
//		SendASCIIHEXNDWIN(0x4100, upgrademessage, upgrademessage_length);// 最后升级:2025/01/14	
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6030,flash_data.smallboard_upload_frequency);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6040,flash_data.object_emissivity);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6050,flash_data.pressure_threshold);
		vTaskDelay(pdMS_TO_TICKS(100));

		SendDWINThreshold(0x6000,flash_data.temp_first_threshold);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6010,flash_data.temp_second_threshold);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6020,flash_data.mainboard_upload_frequency);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6060,flash_data.co_threshold);
		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINThreshold(0x6070,flash_data.h2_threshold);
		vTaskDelay(pdMS_TO_TICKS(100));
//		SendDWINThreshold(0x60A0,flash_data.pressure_upload_frequency);
//		vTaskDelay(pdMS_TO_TICKS(100));
		SendDWINterminal(0x6080, terminalId);
		vTaskDelay(pdMS_TO_TICKS(200));
		SendDWINterminal(0x6090, g_board_id);	
		vTaskDelay(pdMS_TO_TICKS(200));
		DWIN_SWITCH_PAGES(0x0084, 0x0001) ;
		vTaskDelay(pdMS_TO_TICKS(100));
		previous_dwin_warning_state_level = SYSTEM_LEVEL_0;
		printf("DWIN_STARTSHOW_flag end\n");
		DWIN_STARTSHOW_flag = 2;
		dwin_show_state = dwin_show_opened;
//		check_dwin_gas = false;
		DWIN_stopsend_flag = true;
		
	}
	else{
		check_dwin_gas = false;
	}
}

void DWIN_WARNING_MODE(void) // 预警模式下使用
{
		if(dwin_power_state == dwin_power_closed)
		{
			previous_dwin_warning_state_level = SYSTEM_LEVEL_3 ;
		}
		if((dwin_power_state == dwin_power_opened) && (system_level != previous_dwin_warning_state_level)) // previous_dwin_warning_state_level
		{
				vTaskDelay(pdMS_TO_TICKS(300));
				gas_start_read_flag = false;			
				if (system_level == SYSTEM_LEVEL_2) 
				{	
					vTaskDelay(pdMS_TO_TICKS(50));
					SendHEXNDWIN(0x1001, 0x0002); // 2二级状态					
					vTaskDelay(pdMS_TO_TICKS(50));
					DWIN_PLAY_MUSIC(0X00A0, 0X0301);
											
				}else{
					vTaskDelay(pdMS_TO_TICKS(20));
					SendHEXNDWIN(0x1001, 0x0000); // 0正常状态
					vTaskDelay(pdMS_TO_TICKS(30));
					DWIN_PLAY_MUSIC(0X00A0, 0X0401);
				}
				gas_start_read_flag = true;
				previous_dwin_warning_state_level = system_level;
		}
		if(temp_system_level != TEMP_LEVEL_0)
		{
				if(gas_start_read_flag)
				{
					read_gas();
					check_dwin_gas = false;
					return;
				}
		}
		check_dwin_gas = false;
		return;
}

void ProcessDWINSHOW_gasread(void) 
{
//    while (1){
//        if (check_dwin_gas) 
//        {                  
						if( DWIN_STARTSHOW_flag ==1 ) 
						{
							DWIN_SHOW();
							osDelay(1);								
						}

//        } else {
						if(gas_start_read_flag)
						{
							read_gas();
							osDelay(1);	
						}
//						else
//						{
//							check_dwin_gas = true;
//						}
//        }

//				osDelay(1);
//    }
}
void DWIN_SHOW(void)
{
    while (1)
    {
        switch (dwin_state)
        {
            case DWIN_STATE_DEBUG:
						{
                DWIN_CHECK();
//								read_dwin();
								osDelay(300);
								sprintf(display_str, "%d%%", percent);  // 构造字符串，如 "75%"
								SendWENBENDWIN(0x1200, display_str); 
								osDelay(300);								
								if(system_cloud_mode == Cloud_4G_MODE)
								{
									SendHEXNDWIN(0x1016, 0x0000);  // 显示水陆图标
								}
								else
								{
									SendHEXNDWIN(0x1016, 0x0001);  // 显示航空图标
								}
								osDelay(300);
								if (REGISTER_OK_start_flag)
								{
										SendHEXNDWIN(0x1013, 0x0001);  // 显示联网图标
								}
								else
								{
										SendHEXNDWIN(0x1013, 0x0000);  // 取消联网图标
								}
								osDelay(300);								
								for(uint8_t i = 0; i < MAX_TEMP_NODE_NUM; i++)
								{
//										if (dwin_show_closed == dwin_show_state || DWIN_stopsend_flag == false)
//												break;

										if (sensor_dwin_data_buffer.temp_valid[i]) {
												SendMLXDWIN(0x3000 + (i * 0x10), i + 1,
																		sensor_dwin_data_buffer.temp_data[i][0],
																		sensor_dwin_data_buffer.temp_data[i][1],
																		sensor_dwin_data_buffer.temp_data[i][2]);
												sensor_dwin_data_buffer.temp_valid[i] = 0;
												vTaskDelay(pdMS_TO_TICKS(100));
										}
								}
								if(temp_system_level == TEMP_LEVEL_0)
								{
									SendHEXNDWIN(0x31E0, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x31F0, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3200, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3210, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3220, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3230, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3240, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3250, 0xFFFF); // 文本框清空
									osDelay(100);
									SendHEXNDWIN(0x3260, 0xFFFF); // 文本框清空
									osDelay(100);
								}
								osDelay(100);
								if(temp_system_level != TEMP_LEVEL_0)
								{
										for(uint8_t i = 0; i < MAX_PRESSURE_NODE_NUM; i++)
										{
												if (sensor_dwin_data_buffer.pressure_valid[i]) {
														SendPressureDWIN(0x31E0 + (i * 0x10), i + 1,
																						 (sensor_dwin_data_buffer.pressure_data[i][0] << 8) |
																						 sensor_dwin_data_buffer.pressure_data[i][1]);
														sensor_dwin_data_buffer.pressure_valid[i] = 0;
														vTaskDelay(pdMS_TO_TICKS(60));
												}
										}

										for(uint8_t i = 0; i < MAX_H2_NODE_NUM; i++)
										{
												SendH2DWIN(0x3210 + (i * 0x10), i + 1,
																	 modbus_to_float(sensor_data_buffer.h2_data[i]));
												sensor_data_buffer.h2_valid[i] = 0;
												vTaskDelay(pdMS_TO_TICKS(60));
										}

										for(uint8_t i = 0; i < MAX_CO_NODE_NUM; i++)
										{
												SendCODWIN(0x3240 + (i * 0x10), i + 1,
																	 modbus_to_float(sensor_data_buffer.co_data[i]));
												sensor_data_buffer.co_valid[i] = 0;
												vTaskDelay(pdMS_TO_TICKS(60));
										}
														
										if(gas_start_read_flag) {
												osDelay(500);
												send_modbus_command(0x11);
												osDelay(500);											
												send_modbus_command(0x10);
												osDelay(500);	
												send_modbus_command(0x12);
												osDelay(500);	
												send_modbus_command(0x02);         
												osDelay(500);	
												send_modbus_command(0x01);
												osDelay(500);	
												send_modbus_command(0x03);
												osDelay(500);
										}
								}
								get_current_dwin_state();
                osDelay(1000);
                check_dwin_gas = false;
                break;
						}
						
            case DWIN_STATE_WARNING:
						{
								static TickType_t last_display_tick = 0;
								TickType_t now = xTaskGetTickCount();

								// 每 2 秒更新一次显示
								if ((now - last_display_tick) >= pdMS_TO_TICKS(2000)) {
										last_display_tick = now;
									
//										printf("percent %d \n",percent);
										sprintf(display_str, "%d%%", percent);  // 构造字符串，如 "75%"
										SendWENBENDWIN(0x1200, display_str);
										osDelay(200);
										SendDWINterminal(0x6080, terminalId);	
										osDelay(200);
										if (REGISTER_OK_start_flag)
										{
												SendHEXNDWIN(0x1013, 0x0001);  // 显示联网图标
										}
										else
										{
												SendHEXNDWIN(0x1013, 0x0000);  // 取消联网图标
										}
										osDelay(200);
										if(system_cloud_mode == Cloud_4G_MODE)
										{
											SendHEXNDWIN(0x1016, 0x0000);  // 显示水陆图标
										}
										else
										{
											SendHEXNDWIN(0x1016, 0x0001);  // 显示航空图标
										}
								}
								get_current_dwin_state();
                DWIN_WARNING_MODE();
								
                break;
						}
						
            case DWIN_STATE_SET:
						{
								static TickType_t SETlast_display_tick = 0;
								TickType_t SETnow = xTaskGetTickCount();
							
								if ((SETnow - SETlast_display_tick) >= pdMS_TO_TICKS(5000)) {
									
										SETlast_display_tick = SETnow;
										osDelay(100);
										SendDWINThreshold(0x6000, flash_data.temp_first_threshold); 
										osDelay(100);
										SendDWINThreshold(0x6010, flash_data.temp_second_threshold); 
										osDelay(100);
										SendDWINThreshold(0x6020, flash_data.mainboard_upload_frequency);
										osDelay(100);
										SendDWINThreshold(0x6030, flash_data.smallboard_upload_frequency);
										osDelay(100);									
										SendDWINThreshold(0x6050, flash_data.pressure_threshold);
										osDelay(100);
										SendDWINThreshold(0x6060, flash_data.co_threshold); 
										osDelay(100);
										SendDWINThreshold(0x6070, flash_data.h2_threshold); 
										osDelay(100);
										SendDWINThreshold(0x6040, flash_data.object_emissivity); 
										osDelay(100);
										SendDWINterminal(0x6080, terminalId); 
										osDelay(100);
										SendDWINterminal(0x6090, g_board_id); 
										osDelay(100);
										get_current_dwin_state();
								}		
                break;
						}
						
						case DWIN_STATE_AVIATION:
							{
								static TickType_t AVIATION_last_display_tick = 0;
								TickType_t AVIATION_now = xTaskGetTickCount();
							
								if ((AVIATION_now - AVIATION_last_display_tick) >= pdMS_TO_TICKS(3000)) {									
										AVIATION_last_display_tick = AVIATION_now;
										
										osDelay(100);
										Send_uint8HEX_DWIN(0x60A0, wifi_config.ssid, sizeof(wifi_config.ssid) );
										printf("DWIN.ssid :%s \n",wifi_config.ssid);
										osDelay(100);
										Send_uint8HEX_DWIN(0x60C0, wifi_config.password, sizeof(wifi_config.password) );
										printf("DWIN.password :%s \n",wifi_config.password);
										osDelay(100);
//										ReadHEXNDWIN(0x5610,0x0A);
//										osDelay(400);
//										ReadHEXNDWIN(0x5630,0x0A);
//										osDelay(400);
								}

                break;
						}
							
						case DWIN_STATE_AVIATION_READ:
								osDelay(100);
								SendHEXNDWIN(0x1016, 0x0001);  //航空模式图标
								osDelay(100);
								dwin_state = DWIN_STATE_WARNING_SWITCH;		
                break;
						
						case DWIN_STATE_4G:
								osDelay(100);
								SendHEXNDWIN(0x1016, 0x0000);  //水陆模式图标
								osDelay(100);
								dwin_state = DWIN_STATE_WARNING_SWITCH;		
                break;
						
						case DWIN_STATE_DEBUG_SWITCH:
								osDelay(100);
								DWIN_SWITCH_PAGES(0x0084, 0x0001) ;	
								osDelay(100);
								SendDWINterminal(0x6080, terminalId);	
								osDelay(100);
								dwin_state = DWIN_STATE_DEBUG;
								get_current_dwin_state();
                break;
						
						case DWIN_STATE_WARNING_SWITCH:
								osDelay(100);
								DWIN_SWITCH_PAGES(0x0084, 0x000E) ;
								osDelay(100);
								sprintf(display_str, "%d%%", percent);  
								SendWENBENDWIN(0x1200, display_str);
								osDelay(100);
								SendDWINterminal(0x6080, terminalId);	
								osDelay(100);
								dwin_state = DWIN_STATE_WARNING;
								get_current_dwin_state();
                break;
						
						case DWIN_STATE_SET_SWITCH:
								osDelay(100);
								DWIN_SWITCH_PAGES(0x0084, 0x0006) ;
								osDelay(100);
								dwin_state = DWIN_STATE_SET;
								get_current_dwin_state();
								
                break;
						
            case DWIN_STATE_IDLE:
            default:
                break;
        }

        osDelay(1);
    }
}
DWIN_State_t get_current_dwin_state(void)
{
    switch(dwin_state)
    {
        case DWIN_STATE_DEBUG_SWITCH:
						printf("DWIN_STATE_DEBUG_SWITCH\n");
            return DWIN_STATE_DEBUG_SWITCH;
        case DWIN_STATE_WARNING_SWITCH:
					printf("DWIN_STATE_WARNING_SWITCH\n");
            return DWIN_STATE_WARNING_SWITCH;
        case DWIN_STATE_SET_SWITCH:
					printf("DWIN_STATE_SET_SWITCH\n");
            return DWIN_STATE_SET_SWITCH;
				case DWIN_STATE_DEBUG:
//					printf("DWIN_STATE_DEBUG\n");
            return DWIN_STATE_DEBUG;
				case DWIN_STATE_WARNING:
//					printf("DWIN_STATE_WARNING\n");
            return DWIN_STATE_WARNING;
				case DWIN_STATE_SET:
//					printf("DWIN_STATE_SET\n");
            return DWIN_STATE_SET;
        default:
            return DWIN_STATE_IDLE;
    }
}

void read_gas(void) // 发送读取 H2  CO 数据 // H2 1 - 15 // CO 16 - 31
{	 

	switch (gas_command_index) {
        case 0:
						send_modbus_command(0x11);            
            break;
        case 1:
            send_modbus_command(0x10);
            break;
        case 2:
            send_modbus_command(0x12);
            break;
        case 3:
						send_modbus_command(0x02);         
            break;
        case 4:
            send_modbus_command(0x01);
            break;
        case 5:
            send_modbus_command(0x03);
            break;
        default:
					gas_command_index = 0;
            break;
    }

    gas_command_index = (gas_command_index + 1) % 6;

    vTaskDelay(pdMS_TO_TICKS(490));
}

void read_dwin(void) 
{	 

	switch (dwin_command_index) {
        case 0:
            ReadHEXNDWIN(0x1003, 0x01);
            break;
        case 1:
            ReadHEXNDWIN(0x5500, 0x01);
            break;
        case 2:
            ReadHEXNDWIN(0x5501, 0x01);
            break;
        case 3:
            ReadHEXNDWIN(0x5502, 0x01);
            break;
        case 4:
            ReadHEXNDWIN(0x5503, 0x01);
            break;
        case 5:
            ReadHEXNDWIN(0x5504, 0x01);
            break;
				case 6:
            ReadHEXNDWIN(0x5505, 0x01);
            break;
        case 7:
            ReadHEXNDWIN(0x5506, 0x01);
            break;
        case 8:
            ReadHEXNDWIN(0x5507, 0x01);
            break;
        case 9:
            ReadHEXNDWIN(0x5510, 0x01);
            break;
        case 10:
            ReadHEXNDWIN(0x5508, 0x04);
            break;
				case 11:
            ReadHEXNDWIN(0x5509, 0x04);
            break;
				case 12:
            ReadHEXNDWIN(0x1500, 0x01);
            break;
        default:
					dwin_command_index = 0;
            break;
    }

    dwin_command_index = (dwin_command_index + 1) % 13;

    vTaskDelay(pdMS_TO_TICKS(800));
}
void check_trigger_source(void) 
{
    if (trigger_info[0] == 0) {  // 只记录最早触发的
        if (temp_system_level == TEMP_LEVEL_2) {  // 温度触发
            for (uint8_t i = 0; i < MAX_TEMP_NODE_NUM; i++) {
                if (temp_level_buffer[i] == 2) {  
                    trigger_info[0] = 0xF00A; // 温度类型
                    trigger_info[1] = i + 1;  // 传感器编号
                    trigger_info[2] = sensor_dwin_data_buffer.temp_data[i][0]; // 记录值
                    break;
                }
            }
        }
        if (pre_system_level == PRE_LEVEL_2) {  // 压力触发
            for (uint8_t i = 0; i < MAX_PRESSURE_NODE_NUM; i++) {
                if (pre_level_buffer[i] == 2) {
                    trigger_info[0] = 0xF00C; // 压力类型
                    trigger_info[1] = i + 1;
										if( sensor_dwin_data_buffer.pressure_data[i][0] > 0 )
										{
											sensor_dwin_data_buffer.pressure_data[i][1] = 0xFF;
										}
										printf("sensor_dwin_data_buffer.pressure_data[%d][0][1] %d %d\r\n",i,sensor_dwin_data_buffer.pressure_data[i][0],sensor_dwin_data_buffer.pressure_data[i][1]);											
                    trigger_info[2] = sensor_dwin_data_buffer.pressure_data[i][1];
                    break;
                }
            }
        }
    }
}



#define CHECK_INTERVAL_MS 600000 
//#define vTaskDelay_MS 50
void check_sensor_line(void) 
{  
    if (system_level == SYSTEM_LEVEL_0) 
		{
        check_temp_line();
				S_offline_flag = true;
    } 
		else 
		{
        switch (current_state) 
				{
            case SENSOR_STATE_TEMP:
                check_temp_line();
								S_offline_flag = true;
//						printf("check_temp_line \r\n");
                break;
            case SENSOR_STATE_PRE:
                check_pre_line();
//						printf("check_pre_line \r\n");
                break;
            case SENSOR_STATE_H2:
                check_h2_line();
//						printf("check_h2_line \r\n");
                break;
            case SENSOR_STATE_CO:
                check_co_line();
								S_offline_flag = true;						
//						printf("check_co_line \r\n");
                break;
            default:
                break;
        }				
//				printf("offline_flag %d\n",S_offline_flag);
        // 切换到下一个状态
        current_state = (SensorCheckState)((current_state + 1) % SENSOR_STATE_MAX);
		}
}

void check_temp_line(void)
{
    uint32_t current_ms = HAL_GetTick();		
//    uint8_t start_index = current_temp_group * TEMP_NODE_GROUP_SIZE;
//    uint8_t end_index = start_index + TEMP_NODE_GROUP_SIZE;
//		
//    if (end_index > MAX_TEMP_NODE_NUM) {
//        end_index = MAX_TEMP_NODE_NUM; // 防止越界
//    }
		
		// 连续 多少秒没有收到温度传感器数值，写0到屏幕和平台   
//		for (uint8_t i = start_index; i < end_index; i++)  // 检测当前组的传感器
    for (uint8_t i = 0; i < MAX_TEMP_NODE_NUM; i++)
		{
				// 更新 sensor_status
        uint8_t byte_index = 3 - (i / 8);    // **反向计算所属字节**
        uint8_t bit_index = i % 8;           // **从 bit0 开始顺序排列**
			
        if (current_ms - g_prevdata_temp[i].count_ms >= CHECK_INTERVAL_MS)
        {
						
            g_prevdata_temp[i].recv_flag = 0;
            g_prevdata_temp[i].offline_flag = 1;
//						memset(sensor_dwin_data_buffer.temp_data[i], 0, sizeof(sensor_dwin_data_buffer.temp_data[i]));
//						memset(sensor_data_buffer.temp_data[i], 0, sizeof(sensor_data_buffer.temp_data[i]));
						sensor_status[byte_index] &= ~(1 << bit_index); // **清零（掉线）**						
						g_prevdata_temp[i].count_ms = current_ms;
//						printf("offline_Temp[%d]\r\n", i + 1);
        }
				if (g_prevdata_temp[i].offline_flag == 0)
				{
            sensor_status[byte_index] |= (1 << bit_index); // **置位（在线）**
				} else {          
						sensor_status[byte_index] &= ~(1 << bit_index); // **清零（掉线）**
        }
				
    }

    // 切换到下一组
//    current_temp_group = (current_temp_group + 1) % ((MAX_TEMP_NODE_NUM + TEMP_NODE_GROUP_SIZE - 1) / TEMP_NODE_GROUP_SIZE);
}

void check_pre_line(void)
{
    uint32_t current_ms = HAL_GetTick();
    if (system_level != SYSTEM_LEVEL_0)
    {

        // 连续多少秒没有收到压力传感器数值，写0到屏幕和平台
				uint8_t bit_positions[] = {4, 5, 6};  // 1号传感器对应 bit4，2号对应 bit5，3号对应 bit6
        for (uint8_t i = 0; i < MAX_PRESSURE_NODE_NUM; i++)
        {
            if (current_ms - g_prevdata_press[i].count_ms >= CHECK_INTERVAL_MS)
            {
								
                g_prevdata_press[i].recv_flag = 0;
                g_prevdata_press[i].offline_flag = 1;

								memset(sensor_dwin_data_buffer.pressure_data[i], 0, sizeof(sensor_dwin_data_buffer.pressure_data[i]));
//								memset(sensor_data_buffer.pressure_data[i], 0, sizeof(sensor_data_buffer.pressure_data[i]));
								sensor_status[4] &= ~(1 << bit_positions[i]); // 清零（掉线）**
								g_prevdata_press[i].count_ms = current_ms;
//								printf("offline_pre[%d]\r\n", i+1);						
            }	
						if (g_prevdata_press[i].offline_flag == 0)
						{
							 // 更新 sensor_status[4] 的 bit6~bit4
               sensor_status[4] |= (1 << bit_positions[i]);  // 置位（在线）**
						} else {          
							 sensor_status[4] &= ~(1 << bit_positions[i]); // 清零（掉线）**
						}						
        }
    }
}
void check_co_line(void)
{
	uint32_t current_ms = HAL_GetTick();
	if(system_level != SYSTEM_LEVEL_0)
		{
			char offline_info[10];  // 用于存储所有掉线传感器的编号
			int len = 0;  // 记录当前已存储的字符数
			int printed = 0;  // 用于记录是否打印过掉线信息
			printf("check CO current_ms %d\n", current_ms);
			//连续多少秒 没有收到CO传感器数值， 写0到屏幕和平台
			uint8_t bit_positions[] = {0, 1, 2};  // 1号传感器对应 bit0，2号对应 bit1，3号对应 bit2
			for(uint8_t i=0; i<MAX_CO_NODE_NUM; i++)
			{
				if(current_ms - g_prevdata_co[i].count_ms >= CHECK_INTERVAL_MS)
				{
					uint32_t cu_cou_ms = current_ms - g_prevdata_co[i].count_ms;
					printf("check CO %d current-count_ms %d\n", i, cu_cou_ms);
					g_prevdata_co[i].recv_flag = 0;
					g_prevdata_co[i].offline_flag = 1;
					sensor_data_buffer.co_valid[i] = 0;
					memset(sensor_dwin_data_buffer.co_data[i], 0, sizeof(sensor_dwin_data_buffer.co_data[i]));
					memset(sensor_data_buffer.co_data[i], 0, sizeof(sensor_data_buffer.co_data[i]));

//					g_prevdata_co[i].count_ms = current_ms;					 
					// 如果尚未打印掉线信息
					if (!printed)
					{
						printed = 1; 
					}

					// 将掉线传感器编号追加到 offline_info
					len += snprintf(offline_info + len, sizeof(offline_info) - len, "%d", i + 1);

					// 如果不是最后一个，添加逗号
					if (i < MAX_CO_NODE_NUM - 1)
					{
							len += snprintf(offline_info + len, sizeof(offline_info) - len, ",");
					}
					sensor_status[4] &= ~(1 << bit_positions[i]); // 清零 掉线**
				}	
				if (g_prevdata_co[i].offline_flag == 0)
				{
					// 更新 sensor_status[4] 的 bit2~bit0
					sensor_status[4] |= (1 << bit_positions[i]);  // 置位 在线**
				} else {          
					sensor_status[4] &= ~(1 << bit_positions[i]); // 清零 掉线**
				}				
			}
			// 如果有掉线传感器信息，打印并换行
			if (printed)
			{
//					printf("offline_co[%s]\r\n", offline_info);
			}
		}
}

void check_h2_line(void)
{
		uint32_t current_ms = HAL_GetTick();
		printf("check h2 current_ms %d\n", current_ms);
		if(system_level != SYSTEM_LEVEL_0)
		{
			char offline_info[10];  // 用于存储所有掉线传感器的编号
			int len = 0;  // 记录当前已存储的字符数
			int printed = 0;  // 用于记录是否打印过掉线信息
			
			//连续多少秒 没有收到H2传感器数值， 写0到屏幕和平台
			uint8_t bit_positions[] = {4, 5, 6};  // 1号传感器对应 bit0，2号对应 bit1，3号对应 bit2
			for(uint8_t i=0; i < MAX_H2_NODE_NUM; i++)
			{
				if(current_ms - g_prevdata_h2[i].count_ms >= CHECK_INTERVAL_MS)
				{
					uint32_t cur_cou_ms = current_ms - g_prevdata_h2[i].count_ms;
					printf("check h2 %d current-count_ms %d\n", i, cur_cou_ms);
					g_prevdata_h2[i].recv_flag = 0;
					g_prevdata_h2[i].offline_flag = 1;
					sensor_data_buffer.h2_valid[i] = 0;
					memset(sensor_dwin_data_buffer.h2_data[i], 0, sizeof(sensor_dwin_data_buffer.h2_data[i]));
					memset(sensor_data_buffer.h2_data[i], 0, sizeof(sensor_data_buffer.h2_data[i]));

//					g_prevdata_h2[i].count_ms = current_ms;
					
					// 如果尚未打印掉线信息
					if (!printed)
					{
						printed = 1; 
					}

					// 将掉线传感器编号追加到 offline_info
					len += snprintf(offline_info + len, sizeof(offline_info) - len, "%d", i + 1);

					// 如果不是最后一个，添加逗号
					if (i < MAX_H2_NODE_NUM - 1)
					{
							len += snprintf(offline_info + len, sizeof(offline_info) - len, ",");
					}
					sensor_status[5] &= ~(1 << bit_positions[i]); // 清零 掉线**
				}
				if (g_prevdata_h2[i].offline_flag == 0)
				{
					// 更新 sensor_status[5] 的 bit6~bit4
					sensor_status[5] |= (1 << bit_positions[i]);  // 置位 在线**
				} else {          
					sensor_status[5] &= ~(1 << bit_positions[i]); // 清零 掉线**
				}
				
			}
			// 如果有掉线传感器信息，打印并换行
			if (printed)
			{
//					printf("offline_h2[%s]\r\n", offline_info);
			}
		}
}


void DWIN_CHECK(void)
{
//		if(system_level != previous_dwin_warning_state_level) // previous_dwin_warning_state_level
//		{
//			  DWIN_stopsend_flag = false;
				if (system_level == SYSTEM_LEVEL_1) 
				{
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1002, 0x0001); // 1一级预警
//						vTaskDelay(pdMS_TO_TICKS(100));
//						DWIN_PLAY_MUSIC(0X00A0, 0X0201);
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1004, 0x0001); // 气体供电打开
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1005, 0x0000); // 推杆供电关闭
						vTaskDelay(pdMS_TO_TICKS(100));
//						printf("DWIN send DWIN_WARNING_LEVEL_1_STATE \r\n");
				}
				else if (system_level == SYSTEM_LEVEL_2) 
				{
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1002, 0x0002); // 2二级报警
						vTaskDelay(pdMS_TO_TICKS(20));
						DWIN_PLAY_MUSIC(0X00A0, 0X0301);
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1004, 0x0001); // 气体供电打开
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1005, 0x0001); // 推杆供电打开
						vTaskDelay(pdMS_TO_TICKS(100));
//						printf("DWIN send DWIN_WARNING_LEVEL_2_STATE \r\n");
				}
				else if(system_level == SYSTEM_LEVEL_0)
				{		
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1002, 0x0000); // 0正常状态
//						vTaskDelay(pdMS_TO_TICKS(100));
//						DWIN_PLAY_MUSIC(0X00A0, 0X0401);
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1004, 0x0000); // 气体供电关闭
						vTaskDelay(pdMS_TO_TICKS(100));
						SendHEXNDWIN(0x1005, 0x0000); // 推杆供电关闭
						vTaskDelay(pdMS_TO_TICKS(100));
//						printf("DWIN send DWIN_WARNING_LEVEL_0_STATE \r\n");
				}
//				previous_dwin_warning_state_level = system_level;
////				DWIN_stopsend_flag = true;
//		}
		if (REGISTER_OK_start_flag)
		{
				SendHEXNDWIN(0x1013, 0x0001);  // 显示联网图标
//												printf("REGISTER_OK\n");
		}
		else
		{
				SendHEXNDWIN(0x1013, 0x0000);  // 取消联网图标
//												printf("REGISTER_fail\n");
		}
}

void DWIN_START_CHECK(void)
{
		
		if(previous_dwin_warning_state_level != system_level)
		{
				if (system_level == SYSTEM_LEVEL_1) 
				{
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1002, 0x0001); // 1一级预警
						vTaskDelay(pdMS_TO_TICKS(20));
						DWIN_PLAY_MUSIC(0X00A0, 0X0201);
						vTaskDelay(pdMS_TO_TICKS(20));	
						SendHEXNDWIN(0x1004, 0x0001); // 气体供电打开
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1005, 0x0000); // 推杆供电关闭
						vTaskDelay(pdMS_TO_TICKS(20));					
//						printf("DWIN send DWIN_WARNING_LEVEL_1_STATE \r\n");
				}
				else if (system_level == SYSTEM_LEVEL_2) 
				{
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1002, 0x0002); // 2二级报警
						vTaskDelay(pdMS_TO_TICKS(20));
						DWIN_PLAY_MUSIC(0X00A0, 0X0301);
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1004, 0x0001); // 气体供电打开
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1005, 0x0001); // 推杆供电打开
						vTaskDelay(pdMS_TO_TICKS(20));
//						printf("DWIN send DWIN_WARNING_LEVEL_2_STATE \r\n");
				}
				else if (system_level == SYSTEM_LEVEL_0) 
				{		
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1002, 0x0000); // 0正常状态
						vTaskDelay(pdMS_TO_TICKS(20));
						DWIN_PLAY_MUSIC(0X00A0, 0X0401);
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1004, 0x0000); // 气体供电关闭
						vTaskDelay(pdMS_TO_TICKS(20));
						SendHEXNDWIN(0x1005, 0x0000); // 推杆供电关闭
						vTaskDelay(pdMS_TO_TICKS(20));
//						printf("DWIN send DWIN_WARNING_LEVEL_0_STATE \r\n");
				}
				previous_dwin_warning_state_level = system_level;

		}
		
		
}
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;
}


void send_modbus_command(uint8_t sensor_address) // 发送MODBUS指令读取传感器数据
{
    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高字节

//		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); 
		HAL_UART_Transmit(&huart2, command, 8,1000);
		HAL_UART_Receive_DMA(&huart2, dataReceive2, BUFFER_SIZE2);
//		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 发送完成后拉低接收
}	


static inline float parse_modbus_float(uint8_t *data) // 解析 Modbus 数据并转换为浮点数
{
    return modbus_to_float(data);
}

float modbus_to_float(uint8_t *data)
{
    float value = 0;
    uint8_t float_data[4];
    
    float_data[0] = data[1];  
    float_data[1] = data[0]; 
    float_data[2] = data[3];  
    float_data[3] = data[2];  
    
    memcpy(&value, float_data, sizeof(float));
    return value;
}
void Check_DWIN_Button(void)
{
    static uint8_t key_was_pressed = 0; // 标记是否处理过本次按键
    static uint32_t press_time = 0;     // 记录按下时间

    GPIO_PinState pin_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
    uint32_t current_time = HAL_GetTick();

    if (pin_state == GPIO_PIN_RESET)  // 检测到按下（低电平）
    {
        if (key_was_pressed == 0)  // 第一次按下，开始计时
        {
            press_time = current_time;
            key_was_pressed = 1;
        }

        // 如果按下持续时间超过最大值5000ms，放弃本次
        if ((current_time - press_time) > 5000)
        {
            key_was_pressed = 2;  // 标记为超时，不再处理
            printf("DWIN_Button press timeout！\n");
        }
    }
    else  // 松开（高电平）
    {
        if (key_was_pressed == 1)  // 说明之前处于有效低电平阶段
        {
            uint32_t press_duration = current_time - press_time;

            // 判断持续时间是否在 100ms ~ 5000ms 范围内
            if (press_duration >= 100 && press_duration <= 5000)
            {
                // 满足条件，执行状态切换
                if (dwin_power_state != dwin_power_opened)
                {									
                    dwin_power_state = dwin_power_opened;
										printf("Dwin_power_opened\n");
                }
                else
                {
                    dwin_power_state = dwin_power_closed;
										printf("Dwin_power_closed\n");
                }
            }

            key_was_pressed = 0;  // 重置，等待下一次检测
        }
        else if (key_was_pressed == 2)
        {
            // 之前超时了，松开后也要重置
            key_was_pressed = 0;
        }
    }
}


void control_actuator(bool enable)
{
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, enable ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

void control_gas_sensors(bool enable) 
{
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, enable ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
void control_wifi_wakeup(bool enable) 
{
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, enable ? GPIO_PIN_RESET : GPIO_PIN_SET);
}

/**
  * @breaf 内部flash相关函数
  */
void Read_parameter_From_Flash(void) // 从 Flash 读取 parameter
{
		uint8_t *flash_ptr = (uint8_t *)FLASH_LAST_PAGE_ADDR;
	
		if (flash_ptr[0] == 0xFF ) {
        flash_data.controltransmit_flag = 0;
    }else{
				flash_data.controltransmit_flag = flash_ptr[0]; 
		}
    if (flash_ptr[1] == 0xFF ) {
        flash_data.temp_first_threshold = 60;
    }else{
				flash_data.temp_first_threshold = flash_ptr[1]; 
		}
		if (flash_ptr[2] == 0xFF ) {
        flash_data.temp_second_threshold = 100;
    }else{
				flash_data.temp_second_threshold = flash_ptr[2]; 
		}
		if (flash_ptr[3] == 0xFF ) {
        flash_data.pressure_threshold = 100;
    }else{
				flash_data.pressure_threshold = flash_ptr[3]; 
		}
		if (flash_ptr[4] == 0xFF ) {
        flash_data.co_threshold = 10;
    }else{
				flash_data.co_threshold = flash_ptr[4]; 
		}		
		if (flash_ptr[5] == 0xFF ) {
        flash_data.h2_threshold= 10;
    }else{
				flash_data.h2_threshold = flash_ptr[5]; 
		}
		if (flash_ptr[6] == 0xFF) {
        flash_data.smallboard_upload_frequency = 1;
    }else{
				flash_data.smallboard_upload_frequency = flash_ptr[6]; 
		}
		if (flash_ptr[7] == 0xFF) {
        flash_data.heart_upload_frequency = 30;
    }else{
				flash_data.heart_upload_frequency = flash_ptr[7]; 
		}
		if (flash_ptr[8] == 0xFF) {
        flash_data.mainboard_upload_frequency = 1;
    }else{
				flash_data.mainboard_upload_frequency = flash_ptr[8]; 
		}
		if (flash_ptr[9] == 0xFF) {
        flash_data.sensoronline_upload_frequency = 60;
    }else{
				flash_data.sensoronline_upload_frequency = flash_ptr[9]; 
		}
}

void Read_terminal_From_Flash(void) // 从 Flash 读取 terminal终端ID和手机号
{
		uint8_t *flash_ptr = (uint8_t *)FLASH_SECOND_LAST_PAGE_ADDR;
		uint8_t read_terminalId[7]; // 用于存储从 Flash 读取的 terminalId
    uint8_t read_g_board_id[6]; // 用于存储从 Flash 读取的 g_board_id
		uint8_t read_version; 
	
		memcpy(read_terminalId, flash_ptr, 7);  // 读取前 7 字节为 terminalId
    memcpy(read_g_board_id, flash_ptr + 7, 6);  // 读取接下来的 6 字节为 g_board_id
		memcpy(&read_version, flash_ptr + 13, 1);     // 读取第 13 字节为 version
	
		bool terminalId_valid = true;
    for (int i = 0; i < 7; i++) {
        if (read_terminalId[i] == 0xFF) {
            terminalId_valid = false;
            break;
        }
    }
		if (terminalId_valid) {
        memcpy(terminalId, read_terminalId, sizeof(terminalId));  // 更新 terminalId 终端ID
    } else {
        // 如果未写入，保持默认值
        uint8_t default_terminalId[7] = {0x20, 0x24, 0x00, 0x00, 0x00, 0x15, 0x00};
        memcpy(terminalId, default_terminalId, sizeof(terminalId));
    }
    
		bool g_board_id_valid = true;
    for (int i = 0; i < 6; i++) {
        if (read_g_board_id[i] == 0xFF) {
            g_board_id_valid = false;
            break;
        }
    }

    // 如果 g_board_id 未写入，则保持默认值
    if (g_board_id_valid) {
			memcpy(g_board_id, read_g_board_id, sizeof(g_board_id));  // 更新 g_board_id 手机号
    } else {
        // 如果未写入，保持默认值
        uint8_t default_g_board_id[6] = {0x20, 0x24, 0x12, 0x04, 0x00, 0x15};
        memcpy(g_board_id, default_g_board_id, sizeof(g_board_id));
    }
		
		// 检查 version 是否有效（是否为 0xFF）
    bool version_valid = true;
    if (read_version == 0xFF) {
        version_valid = false;
    }

    // 如果 version 有效，更新 version；否则，保持默认值
    if (version_valid) {
        // 更新 version
        flash_data.version = read_version;
    } else {
        // 如果未写入，保持默认版本号
        flash_data.version = 1;  
    }
}
void Save_parameter_To_Flash(	uint8_t controltransmit_flag ,
															uint8_t temp_first_threshold ,
															uint8_t temp_second_threshold ,
															uint8_t pressure_threshold ,
															uint8_t co_threshold ,
															uint8_t h2_threshold ,
															uint8_t smallboard_upload_frequency ,
															uint8_t heart_upload_frequency ,
															uint8_t mainboard_upload_frequency,	
															uint8_t sensoronline_upload_frequency) // 向 Flash 写入 parameter 
{
    uint8_t parameter[16];
		uint8_t readparameterData[sizeof(parameter)];
		parameter[0] = controltransmit_flag & 0xFF; 	
		parameter[1] = temp_first_threshold & 0xFF;
    parameter[2] = temp_second_threshold & 0xFF;
    parameter[3] = pressure_threshold & 0xFF;       
		parameter[4] = co_threshold & 0xFF;              				
    parameter[5] = h2_threshold & 0xFF;              				
		parameter[6] = smallboard_upload_frequency & 0xFF;
		parameter[7] = heart_upload_frequency & 0xFF;
    parameter[8]= mainboard_upload_frequency & 0xFF; 
		parameter[9] = sensoronline_upload_frequency & 0xFF;
		parameter[10] = 0;
		parameter[11] = 0;
		parameter[12] = 0;
		parameter[13] = 0;
		parameter[14] = 0;
		parameter[15] = 0;
	
    if (Flash_WriteRead(FLASH_LAST_PAGE_ADDR, parameter, sizeof(parameter), readparameterData) != SUCCESS) {
        printf("Failed to save Parameter to flash\n");
    } else {
//        printf("Parameter saved to flash:\n");
//        for (int i = 0; i < sizeof(parameter); i++) {
//            printf("[%d]: 0x%02X\n", i, parameter[i]);
//        }
    }
}
void Save_terminal_To_Flash(uint8_t* terminalId , uint8_t* g_board_id ,uint8_t version) // 向 Flash 写入 terminal 
{
    uint8_t parameter[16];
		uint8_t readparameterData[sizeof(parameter)]; 
		memcpy(parameter,terminalId, 7);
		memcpy(parameter + 7, g_board_id, 6);
		parameter[13] = version;
		memset(parameter + 14, 0, sizeof(parameter) - 14);
    if (Flash_WriteRead(FLASH_SECOND_LAST_PAGE_ADDR, parameter, sizeof(parameter), readparameterData) != SUCCESS) {
        printf("Failed to save Parameter to flash\n");
    } else {

    }
}

void Save_W25_Tempaddress_To_Flash(void) // 存储W25Q128的写入地址
{
    uint32_t temp = W25_Tempaddress;
    Flash_ErasePages(FLASH_THIRD_LAST_PAGE_ADDR, 1);         // 擦除1页
    Flash_Write32(FLASH_THIRD_LAST_PAGE_ADDR, &temp, 1);     // 写入1个32位数据	
}

void Save_version_To_Flash(void)
{
    uint32_t version = 0x25051501;
    Flash_ErasePages(FLASH_FOURTH_LAST_PAGE_ADDR, 1);         // 擦除1页
    Flash_Write32(FLASH_FOURTH_LAST_PAGE_ADDR, &version, 1);  // 写入1个32位数据	
}

void Save_wifior4G_flag_To_Flash(void)
{
		uint32_t wifior4G = wifior4G_flag; // 4G为0，WIFI为1
    Flash_ErasePages(FLASH_FOURTH_LAST_PAGE_ADDR, 1);         // 擦除1页
    Flash_Write32(FLASH_SIXTH_LAST_PAGE_ADDR, &wifior4G, 1);  // 写入1个32位数据	
}

void Save_WIFI_To_Flash(void)
{
		uint8_t wifi[40]; // 40个字节为账号密码
		uint8_t readparameterData[40] = {0};
		memcpy(wifi, wifi_config.ssid, 20);
		memcpy(wifi + 20, wifi_config.password, 20);
		
    if (Flash_WriteRead(FLASH_FIFTH_LAST_PAGE_ADDR, wifi, sizeof(wifi), readparameterData) != SUCCESS) {
        printf("Failed to save wifi to flash\n");
    } else {
				printf("WiFi config saved to flash successfully\n");
    }	
}
void Load_WIFI_From_Flash(void)
{
	uint8_t *flash_ptr = (uint8_t *)FLASH_FIFTH_LAST_PAGE_ADDR;
	uint8_t ssid[20];  // 40个字节，前20个字节为账号
	uint8_t password[20]; // 后20个字节为密码
	
	memcpy(ssid, flash_ptr, 20);  
  memcpy(password, flash_ptr + 20, 20);  
	
	bool ssid_valid = false;
	bool password_valid = false;
	
	for (int i = 0; i < 20; i++) {
        if (ssid[i] != 0xFF) {
            ssid_valid = true;
            break;
        }
    }

    for (int i = 0; i < 20; i++) {
        if (password[i] != 0xFF) {
            password_valid = true;
            break;
        }
    }

    if (ssid_valid) {
        memcpy(wifi_config.ssid, ssid, 20);
    } else {
        memset(wifi_config.ssid, 0, 20);
        strcpy((char *)wifi_config.ssid, "BATSURV"); // jiaLong  Oliver-iphonePM  BATSURV
    }

    if (password_valid) {
        memcpy(wifi_config.password, password, 20);
    } else {
        memset(wifi_config.password, 0, 20);
        strcpy((char *)wifi_config.password, "airlines"); // JL88888888  11111111  airlines
    }
	
}

void Read_Remaining_stack_space(void)
{

 // 读取任务剩余栈空间
		 if (temp_pressureHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(temp_pressureHandle);
            printf("temp_pressureHandle stack remaining: %lu\n", stackLeft);
        }
			if (HighestLevelHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(HighestLevelHandle);
            printf("HighestLevelHandle stack remaining: %lu\n", stackLeft);
        }
			if (CommonHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(CommonHandle);
            printf("CommonHandle stack remaining: %lu\n", stackLeft);
        }
			if (check_sensorHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(check_sensorHandle);
            printf("check_sensorHandle stack remaining: %lu\n", stackLeft);
        }	
			if (displayHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(displayHandle);
            printf("displayHandle stack remaining: %lu\n", stackLeft);
        }
			if (cloudHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(cloudHandle);
            printf("cloudHandle stack remaining: %lu\n", stackLeft);
        }
			if (SystemStatusHandle != NULL)
        {
            UBaseType_t stackLeft = uxTaskGetStackHighWaterMark(SystemStatusHandle);
            printf("SystemStatusHandle stack remaining: %lu\n", stackLeft);
        }	

}
/**
	PA1
  * @brief 读取电池电量
  * @retval 电池电量
  */
uint32_t ReadADCValue(void)
{
    uint32_t adcValue = 0;
    const int numSamples = 10; // 样本数量
    uint32_t totalAdcValue = 0;

    for (int i = 0; i < numSamples; i++)
    {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK)
        {
            totalAdcValue += HAL_ADC_GetValue(&hadc1);
        }
        HAL_ADC_Stop(&hadc1);
    }

    adcValue = totalAdcValue / numSamples;
    return adcValue;
}

uint8_t CalculateBatteryLevel(uint32_t adcValue,uint8_t *voltage)
{
    float batteryVoltage = 0.0f;
    const float ADC_MAX_VALUE = 4095.0f;
    const float VREF = 3.3f; // ADC参考电压
    const float MIN_BATTERY_VOLTAGE = 19.0f; // 电池完全放电电压
    const float MAX_BATTERY_VOLTAGE = 24.2f; // 电池完全充电电压

		// 将ADC值转换为电压值，计算电池电量
		float voltageDividerRatio = 10.0f /(10.0f + 100.0f)  ; // 分压100K/110K  0.909
    batteryVoltage = ((float)adcValue / ADC_MAX_VALUE) * VREF/voltageDividerRatio + 1; 

		*voltage = (uint8_t)(batteryVoltage);
	
		// 将电压转换为百分比
    if (batteryVoltage <= MIN_BATTERY_VOLTAGE)
        return 0; // 电池电量低于或等于完全放电电压时，电量为0%
    else if (batteryVoltage >= MAX_BATTERY_VOLTAGE)
        return 100; // 电池电量高于或等于完全充电电压时，电量为100%
    else        
        return (uint8_t)(((batteryVoltage - MIN_BATTERY_VOLTAGE) / (MAX_BATTERY_VOLTAGE - MIN_BATTERY_VOLTAGE)) * 100);// 计算电池电量百分比

}
/**
  * @breaf 低功耗相关
  */
void Enter_SleepMode(void)
{
//	printf("Enter sleep\n");	
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // 清除 PWR 相关标志
	HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2); // 配置调压器为低功耗模式 	
	HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); // 使能 SLEEP 模式（低功耗模式，CPU 休眠，外设仍然运行）	
}


/* USER CODE END Application */

