mirror of
https://git.beihong.wang/wangbeihong/iot-bedroom-environment-controller.git
synced 2026-04-23 15:13:05 +08:00
refactor(display): migrate from ST7735S to ST7789 driver
- Rename component directory from lvgl_st7735s_use to lvgl_st7789_use - Update CMakeLists.txt to register new source files - Add comprehensive README documentation for ST7789 configuration - Add time_alarm module with SNTP synchronization and alarm management - Add sensors header for sensor abstraction layer
This commit is contained in:
593
main/main.cpp
Normal file
593
main/main.cpp
Normal file
@@ -0,0 +1,593 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_sntp.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#include "mqtt_client.h"
|
||||
#include "cJSON.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sensors.h"
|
||||
#include "mqtt_manager.h"
|
||||
#include "wifi_manager.h"
|
||||
#include "peripherals.h"
|
||||
|
||||
#include "lvgl_st7789_use.h"
|
||||
#include "iot_servo.h"
|
||||
#include "time_alarm.h"
|
||||
#include "wifi-connect.h"
|
||||
#include "serial_mcu.h"
|
||||
#include "app_state.h"
|
||||
|
||||
#include "ui.h" // 使用EEZStudio提供的ui组件,便于后续扩展
|
||||
#include "esp_lvgl_port.h"
|
||||
#include "vars.h" // 定义全局变量接口
|
||||
|
||||
// 添加 extern "C" 包裹 C 头文件声明
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// C 函数声明
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
static void mqtt_app_start(void);
|
||||
static void time_period_check_task(void *pvParameters);
|
||||
static void cooling_mode_task(void *pvParameters);
|
||||
|
||||
static const char *TAG = "main";
|
||||
/* 其他子模块在各自文件中定义 TAG,避免在 main 中重复定义未使用的 TAG */
|
||||
|
||||
/* 共享应用状态由 main/app_state.c 提供定义,使用 app_state.h 中的 extern 访问 */
|
||||
|
||||
/* 校准常量已迁移到 peripherals 模块 */
|
||||
|
||||
/* 简单遥测上报封装(暂为适配层) */
|
||||
static void update_telemetry_and_report(void)
|
||||
{
|
||||
mqtt_manager_publish_feedback();
|
||||
}
|
||||
|
||||
#define I2C_MASTER_SCL_IO 5 // GPIO number for I2C master clock
|
||||
#define I2C_MASTER_SDA_IO 4 // GPIO number for I2C master data
|
||||
#define I2C_MASTER_NUM I2C_NUM_0 // I2C port number for master dev
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C master clock frequency
|
||||
|
||||
// SERVO_GPIO defined in peripherals.h
|
||||
|
||||
// ========================= MQTT配置 =========================
|
||||
#define MQTT_BROKER_URL "mqtt://beihong.wang:1883" // MQTT代理URL,从menuconfig配置获取
|
||||
#define MQTT_USERNAME "esp_mqtt_client" // MQTT用户名
|
||||
#define MQTT_CLIENT_ID "esp_mqtt_client" // MQTT客户端ID
|
||||
#define MQTT_PASSWORD "664hd78gas97" // MQTT密码
|
||||
|
||||
// MQTT主题配置
|
||||
#define MQTT_PUBLISH_TOPIC_QOS0 "topic/sensor/esp32_iothome_001" // QoS0发布的主题
|
||||
#define MQTT_NOTIFY_TOPIC "topic/control/esp32_iothome_001" // 上层通知主题
|
||||
#define MQTT_UNSUBSCRIBE_TOPIC "topic/control/esp32_iothome_001" // 取消订阅的主题
|
||||
|
||||
// mqtt_publish_task moved to mqtt_manager.c
|
||||
|
||||
void mqtt_publish_feedback(void)
|
||||
{
|
||||
mqtt_manager_publish_feedback();
|
||||
}
|
||||
|
||||
// mqtt_event_handler moved to mqtt_manager.c
|
||||
|
||||
// mqtt_app_start now delegates to mqtt_manager_start
|
||||
static void mqtt_app_start(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "mqtt_app_start: delegating to mqtt_manager_start");
|
||||
esp_err_t err = mqtt_manager_start();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "mqtt_manager_start failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
// ========================= HTTP服务器相关函数 =========================
|
||||
|
||||
// I2C句柄已在前面声明
|
||||
extern i2c_master_bus_handle_t bus_handle;
|
||||
extern i2c_master_dev_handle_t dev_handle;
|
||||
|
||||
// 舵机初始化函数
|
||||
// 舵机与外设控制由 peripherals 模块提供
|
||||
|
||||
static void rx_task(void *arg)
|
||||
{
|
||||
static const char *RX_TASK_TAG = "RX_TASK";
|
||||
esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
|
||||
uint8_t *data = (uint8_t *)malloc(1024 + 1);
|
||||
static uint8_t frame_buffer[256]; // 帧缓冲区
|
||||
static int frame_index = 0; // 帧索引
|
||||
|
||||
while (1)
|
||||
{
|
||||
const int rxBytes = uart_read_bytes(UART_NUM_1, data, 1024, 1000 / portTICK_PERIOD_MS);
|
||||
if (rxBytes > 0)
|
||||
{
|
||||
// 处理接收到的数据
|
||||
for (int i = 0; i < rxBytes; i++)
|
||||
{
|
||||
// 查找帧头 AA
|
||||
if (frame_index == 0 && data[i] == 0xAA)
|
||||
{
|
||||
frame_buffer[frame_index++] = data[i];
|
||||
}
|
||||
// 检查数据部分是否在01到06范围内
|
||||
else if (frame_index == 1 && data[i] >= 0x01 && data[i] <= 0x06)
|
||||
{
|
||||
frame_buffer[frame_index++] = data[i];
|
||||
}
|
||||
// 检查帧尾 55
|
||||
else if (frame_index == 2 && data[i] == 0x55)
|
||||
{
|
||||
frame_buffer[frame_index++] = data[i];
|
||||
|
||||
// 接收到完整帧 AA [01-06] 55
|
||||
ESP_LOGI(RX_TASK_TAG, "Valid frame received: AA 0x%02X 55", frame_buffer[1]);
|
||||
|
||||
// 解析按键状态
|
||||
uint8_t data_value = frame_buffer[1];
|
||||
|
||||
// 根据数据值解析按键状态
|
||||
switch (data_value)
|
||||
{
|
||||
case 0x01:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 1 pressed - LED toggle");
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
light_source_control_flag = !light_source_control_flag;
|
||||
led_brightness_value = light_source_control_flag ? 100 : 0;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(RX_TASK_TAG, "LED light: %s (brightness=%d)",
|
||||
light_source_control_flag ? "ON" : "OFF", led_brightness_value);
|
||||
mqtt_manager_publish_feedback();
|
||||
break;
|
||||
case 0x02:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 2 pressed - Fan toggle");
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
fan_control_flag = !fan_control_flag;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(RX_TASK_TAG, "Fan: %s", fan_control_flag ? "ON" : "OFF");
|
||||
mqtt_manager_publish_feedback();
|
||||
break;
|
||||
case 0x03:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 3 pressed - Curtain toggle");
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
servo_control_flag = !servo_control_flag;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(RX_TASK_TAG, "Curtain: %s", servo_control_flag ? "OPEN" : "CLOSE");
|
||||
mqtt_manager_publish_feedback();
|
||||
break;
|
||||
case 0x04:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 4 pressed - Buzzer toggle");
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
buzzer_control_flag = !buzzer_control_flag;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(RX_TASK_TAG, "Buzzer: %s", buzzer_control_flag ? "ON" : "OFF");
|
||||
mqtt_manager_publish_feedback();
|
||||
break;
|
||||
case 0x05:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 5 pressed - Backlight toggle");
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
led_backlight_on = !led_backlight_on;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(RX_TASK_TAG, "LCD Backlight: %s", led_backlight_on ? "ON" : "OFF");
|
||||
mqtt_manager_publish_feedback();
|
||||
break;
|
||||
case 0x06:
|
||||
ESP_LOGI(RX_TASK_TAG, "Key 6 pressed");
|
||||
// ui_toggle_page(); // 翻页
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(RX_TASK_TAG, "Unknown key value: 0x%02X", data_value);
|
||||
break;
|
||||
}
|
||||
|
||||
frame_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_index = 0;
|
||||
if (data[i] == 0xAA)
|
||||
{
|
||||
frame_buffer[frame_index++] = data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
// void initialize_nvs()
|
||||
// {
|
||||
// esp_err_t ret = nvs_flash_init(); // 初始化NVS, 并检查是否需要擦除NVS
|
||||
// if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
// {
|
||||
// ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
// ret = nvs_flash_init();
|
||||
// }
|
||||
// ESP_ERROR_CHECK(ret);
|
||||
// }
|
||||
/**
|
||||
* @brief UI 任务函数
|
||||
*
|
||||
* 负责定期驱动 UI 刷新。
|
||||
*
|
||||
* @param arg 任务参数(未使用)
|
||||
*/
|
||||
static void ui_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
lvgl_port_lock(0);
|
||||
ui_tick();
|
||||
|
||||
lvgl_port_unlock();
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
}
|
||||
|
||||
/* 外设控制逻辑已迁移到 peripherals 模块(main/peripherals.c),
|
||||
在此文件中不再实现 `peripheral_control_task` 与 `init_gpio_output`。
|
||||
main.c 通过包含 peripherals.h 并在 app_main 中调用 `peripherals_init()`
|
||||
与 `xTaskCreate(peripheral_control_task, ...)` 来使用该任务。 */
|
||||
|
||||
/* 闹钟逻辑已迁移到 time_alarm 模块 (main/time_alarm.c) */
|
||||
|
||||
// 添加 extern "C" 包裹 app_main 函数
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// esp_log_level_set("*", ESP_LOG_INFO);
|
||||
// esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("transport", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("outbox", ESP_LOG_VERBOSE);
|
||||
// esp_log_level_set("dhcps", ESP_LOG_DEBUG);
|
||||
// esp_log_level_set("esp_netif", ESP_LOG_DEBUG);
|
||||
// esp_log_level_set("esp_netif_lwip", ESP_LOG_DEBUG);
|
||||
// esp_log_level_set("wifi", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("mqtt_manager", ESP_LOG_DEBUG);
|
||||
|
||||
// 设置时区为北京时间 (CST-8)
|
||||
setenv("TZ", "CST-8", 1);
|
||||
tzset();
|
||||
|
||||
// 初始化 Wi-Fi 配网组件,支持长按按键进入配网
|
||||
ESP_ERROR_CHECK(wifi_connect_init());
|
||||
printf("设备启动完成:进入配网模式,手机连接 ESP32-* 后访问 http://192.168.4.1\n");
|
||||
|
||||
// 初始化模块骨架(stub),保持与现有流程兼容
|
||||
ESP_ERROR_CHECK(wifi_manager_init());
|
||||
// mqtt_manager_init 为骨架占位,实际 MQTT 启动仍由原有 mqtt_app_start
|
||||
ESP_ERROR_CHECK(mqtt_manager_init());
|
||||
|
||||
// 启动 LVGL 演示程序,显示简单的界面
|
||||
ESP_ERROR_CHECK(start_lvgl_demo());
|
||||
|
||||
// 初始化 UI 组件(需在 LVGL 锁内进行对象创建)
|
||||
lvgl_port_lock(0);
|
||||
ui_init();
|
||||
lvgl_port_unlock();
|
||||
|
||||
BaseType_t ui_task_ok = xTaskCreate(ui_task, "ui_task", 4096, NULL, 5, NULL);
|
||||
ESP_ERROR_CHECK(ui_task_ok == pdPASS ? ESP_OK : ESP_FAIL);
|
||||
// 连接WIFI
|
||||
// ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
// // Print out Access Point Information
|
||||
// wifi_ap_record_t ap_info;
|
||||
// ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(&ap_info));
|
||||
// ESP_LOGI(TAG, "--- Access Point Information ---");
|
||||
// ESP_LOG_BUFFER_HEX("MAC Address", ap_info.bssid, sizeof(ap_info.bssid));
|
||||
// ESP_LOG_BUFFER_CHAR("SSID", ap_info.ssid, sizeof(ap_info.ssid));
|
||||
// ESP_LOGI(TAG, "Primary Channel: %d", ap_info.primary);
|
||||
// ESP_LOGI(TAG, "RSSI: %d", ap_info.rssi);
|
||||
|
||||
// 初始化I2C总线
|
||||
ESP_ERROR_CHECK(i2c_master_init());
|
||||
|
||||
// 创建互斥锁
|
||||
xSensorDataMutex = xSemaphoreCreateMutex();
|
||||
if (xSensorDataMutex == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "创建传感器数据互斥锁失败");
|
||||
}
|
||||
|
||||
// 添加MQTT消息互斥锁
|
||||
xMqttMessageMutex = xSemaphoreCreateMutex();
|
||||
if (xMqttMessageMutex == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "创建MQTT消息互斥锁失败");
|
||||
}
|
||||
|
||||
// 创建时间段配置互斥锁
|
||||
xTimePeriodMutex = xSemaphoreCreateMutex();
|
||||
if (xTimePeriodMutex == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "创建时间段配置互斥锁失败");
|
||||
}
|
||||
|
||||
// 创建控制标志互斥锁
|
||||
xControlFlagMutex = xSemaphoreCreateMutex();
|
||||
if (xControlFlagMutex == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "创建控制标志互斥锁失败");
|
||||
}
|
||||
|
||||
// 初始化外设与模块(stub),sensor 需在 I2C 与互斥锁初始化后进行
|
||||
ESP_ERROR_CHECK(peripherals_init());
|
||||
ESP_ERROR_CHECK(sensors_init());
|
||||
ESP_ERROR_CHECK(time_alarm_init());
|
||||
|
||||
// 初始化舵机
|
||||
servo_init();
|
||||
|
||||
// GPIO输出初始化(风扇控制)
|
||||
init_gpio_output();
|
||||
|
||||
// MCU间的串口通信初始化
|
||||
serial_mcu_init();
|
||||
|
||||
mqtt_app_start(); // 启动 MQTT 客户端
|
||||
ESP_ERROR_CHECK(time_alarm_start());
|
||||
// 创建时间段检查任务
|
||||
xTaskCreate(time_period_check_task, "time_period_task", 4096, NULL, 5, NULL);
|
||||
// 创建降温模式任务
|
||||
xTaskCreate(cooling_mode_task, "cooling_mode_task", 4096, NULL, 5, NULL);
|
||||
// 自动通风与 MQ135 相关任务已移除
|
||||
// xTaskCreate(ventilation_mode_task, "ventilation_mode_task", 4096, NULL, 5, NULL);
|
||||
// xTaskCreate(mq135_task, "mq135_task", 4096, NULL, 5, NULL);
|
||||
// 创建外设控制任务
|
||||
xTaskCreate(peripheral_control_task, "peripheral_control_task", 4096, NULL, 5, NULL);
|
||||
|
||||
// 传感器任务由 sensors_init() 启动
|
||||
// 创建接收任务
|
||||
xTaskCreate(rx_task, "uart_rx_task", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// 定期打印传感器数据
|
||||
print_sensor_data();
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 降温模式任务
|
||||
* 监测温度,当温度超过阈值时自动开启风扇
|
||||
* 当温度超过35°C时触发高温提醒
|
||||
*/
|
||||
static void cooling_mode_task(void *pvParameters)
|
||||
{
|
||||
ESP_LOGI(TAG, "Cooling mode task started");
|
||||
|
||||
// 从NVS加载配置
|
||||
cooling_mode_load_from_nvs();
|
||||
|
||||
// 高温阈值
|
||||
const float HIGH_TEMP_THRESHOLD = 48.0f;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (g_cooling_mode_enabled)
|
||||
{
|
||||
float current_temp = 0;
|
||||
bool temp_valid = false;
|
||||
|
||||
// 获取当前温度
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
current_temp = g_sensor_data.temperature;
|
||||
temp_valid = g_sensor_data.ahtxx_valid;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
|
||||
if (temp_valid)
|
||||
{
|
||||
// 降温模式:温度超过阈值,开启风扇
|
||||
if (current_temp > g_temperature_threshold)
|
||||
{
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
if (!fan_control_flag)
|
||||
{
|
||||
fan_control_flag = true;
|
||||
ESP_LOGI(TAG, "Temperature %.1f°C > %.1f°C, cooling mode: Fan ON",
|
||||
current_temp, g_temperature_threshold);
|
||||
update_telemetry_and_report();
|
||||
}
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
}
|
||||
// 温度恢复到阈值以下,关闭风扇
|
||||
else if (current_temp < (g_temperature_threshold - 1.0f)) // 添加1°C的滞后,防止频繁切换
|
||||
{
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
if (fan_control_flag)
|
||||
{
|
||||
fan_control_flag = false;
|
||||
ESP_LOGI(TAG, "Temperature %.1f°C < %.1f°C, cooling mode: Fan OFF",
|
||||
current_temp, g_temperature_threshold - 1.0f);
|
||||
update_telemetry_and_report();
|
||||
}
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
}
|
||||
|
||||
// 高温提醒:温度超过35°C
|
||||
if (current_temp > HIGH_TEMP_THRESHOLD)
|
||||
{
|
||||
if (!g_high_temp_alerted)
|
||||
{
|
||||
g_high_temp_alerted = true;
|
||||
|
||||
// 蜂鸣器发出高温提示音
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
buzzer_control_flag = true;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "High temperature alert: %.1f°C (>40°C)", current_temp);
|
||||
|
||||
// 发送MQTT提醒消息
|
||||
if (g_mqtt_client != NULL)
|
||||
{
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(root, "type", "device_message");
|
||||
cJSON_AddStringToObject(root, "device_id", g_device_message.device_id);
|
||||
cJSON_AddStringToObject(root, "device_type", g_device_message.device_type);
|
||||
cJSON_AddStringToObject(root, "message_type", "high_temp_alert");
|
||||
|
||||
cJSON *data_obj = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(data_obj, "alert", "温度过高请注意通风");
|
||||
cJSON_AddNumberToObject(data_obj, "temperature", roundf(current_temp * 10) / 10);
|
||||
cJSON_AddItemToObject(root, "data", data_obj);
|
||||
|
||||
char *json_message = cJSON_Print(root);
|
||||
if (json_message)
|
||||
{
|
||||
esp_mqtt_client_publish(g_mqtt_client, MQTT_PUBLISH_TOPIC_QOS0, json_message, 0, 0, 0);
|
||||
ESP_LOGI(TAG, "High temp alert sent: %s", json_message);
|
||||
free(json_message);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
update_telemetry_and_report();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 温度恢复正常,重置高温提醒标志
|
||||
if (g_high_temp_alerted)
|
||||
{
|
||||
g_high_temp_alerted = false;
|
||||
// 关闭高温提醒蜂鸣器
|
||||
if (xControlFlagMutex != NULL && xSemaphoreTake(xControlFlagMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
buzzer_control_flag = false;
|
||||
xSemaphoreGive(xControlFlagMutex);
|
||||
}
|
||||
ESP_LOGI(TAG, "Temperature normalized: %.1f°C, reset high temp alert", current_temp);
|
||||
update_telemetry_and_report();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 每5秒检查一次
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 自动通风控制模式任务
|
||||
* 监测空气质量,当空气质量大于50时自动开启风扇并发送提醒
|
||||
*/
|
||||
/* ventilation_mode_task 已移除,保留 README 文档说明,不再在代码中保留未使用的静态函数 */
|
||||
|
||||
// MQ135 task removed; provide a short stub to avoid undefined references
|
||||
void mq135_task(void *pvParameters)
|
||||
{
|
||||
ESP_LOGI("mq135_task", "mq135 task removed");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// Remaining MQ135 implementation removed
|
||||
|
||||
/* ----------------- 时间段与降温模式的最小存根实现 ----------------- */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void cooling_mode_save_to_nvs(void)
|
||||
{
|
||||
// TODO: 实现 NVS 存储,目前为最小存根
|
||||
}
|
||||
|
||||
void cooling_mode_load_from_nvs(void)
|
||||
{
|
||||
// TODO: 从 NVS 加载设置。目前使用默认值
|
||||
g_cooling_mode_enabled = false;
|
||||
g_temperature_threshold = 28.0f;
|
||||
}
|
||||
|
||||
void time_period_set(time_period_type_t period_type, uint8_t start_hour, uint8_t start_minute,
|
||||
uint8_t end_hour, uint8_t end_minute)
|
||||
{
|
||||
// TODO: 保存时间段设置或通知其他模块。当前为占位实现。
|
||||
(void)period_type;
|
||||
(void)start_hour;
|
||||
(void)start_minute;
|
||||
(void)end_hour;
|
||||
(void)end_minute;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static void time_period_check_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
while (1)
|
||||
{
|
||||
// 占位:以后在此检查时间段并执行对应操作
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user