diff --git a/main/main.c b/main/main.c index 1c1b219..32c3d5a 100755 --- a/main/main.c +++ b/main/main.c @@ -19,60 +19,92 @@ #include "auto_alerts.h" #include "mqtt_control.h" // MQTT 控制接口 - - +// 配置宏定义:BH1750 光照传感器是否启用(默认禁用) #ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE #define CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE 0 #endif +// 配置宏定义:AHT30 温湿度传感器是否启用(默认禁用) #ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE #define CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE 0 #endif +// 配置宏定义:BH1750 读取周期(毫秒,默认500ms) #ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS #define CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS 500 #endif +// 配置宏定义:AHT30 读取周期(毫秒,默认2000ms) #ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS #define CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS 2000 #endif +// 配置宏定义:I2C 是否启用内部上拉电阻(默认启用) #ifndef CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP #define CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP 1 #endif +// I2C 端口配置 #define BOTANY_I2C_PORT I2C_NUM_0 +// I2C SCL 引脚 #define BOTANY_I2C_SCL_GPIO GPIO_NUM_5 +// I2C SDA 引脚 #define BOTANY_I2C_SDA_GPIO GPIO_NUM_4 +// BH1750 使能标志 #define BOTANY_BH1750_ENABLE CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE +// AHT30 使能标志 #define BOTANY_AHT30_ENABLE CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE +// BH1750 读取周期 #define BOTANY_BH1750_PERIOD_MS CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS +// AHT30 读取周期 #define BOTANY_AHT30_PERIOD_MS CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS +// I2C 内部上拉使能 #define BOTANY_I2C_INTERNAL_PULLUP CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP +// MQTT 告警主题 #define BOTANY_MQTT_ALERT_TOPIC "topic/alert/esp32_iothome_001" +// MQTT 遥测数据上报周期(毫秒) #define BOTANY_MQTT_TELEMETRY_PERIOD_MS 5000 +// 日志标签 static const char *TAG = "main"; +// 全局变量:存储空气温度字符串 static char s_air_temp[16]; +// 全局变量:存储空气湿度字符串 static char s_air_hum[16]; +// 全局变量:存储土壤湿度字符串 static char s_soil[16]; +// 全局变量:存储光照强度字符串 static char s_lux[16]; +// 全局变量:水泵状态(true=开启,false=关闭) static bool s_pump_on = false; +// 全局变量:补光灯状态(true=开启,false=关闭) static bool s_light_on = false; +// 全局变量:自动控制模式使能(true=自动,false=手动) static bool s_auto_control_enabled = true; +/** + * @brief MQTT 控制命令处理函数 + * + * 处理来自 MQTT 的控制命令,包括模式切换、阈值更新、水泵和补光灯控制。 + * + * @param cmd 指向 MQTT 控制命令结构体的指针 + * @param user_ctx 用户上下文(未使用) + * @return esp_err_t 处理结果 + */ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, void *user_ctx) { (void)user_ctx; ESP_RETURN_ON_FALSE(cmd != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd is null"); + // 处理模式切换命令 if (cmd->has_mode) { s_auto_control_enabled = cmd->auto_mode; ESP_LOGI(TAG, "MQTT 控制模式切换: %s", s_auto_control_enabled ? "auto" : "manual"); } + // 处理阈值更新命令 if (cmd->has_thresholds) { ESP_RETURN_ON_ERROR(auto_ctrl_thresholds_set_values(cmd->soil_on_pct, @@ -89,6 +121,7 @@ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, cmd->light_off_lux); } + // 处理水泵控制命令 if (cmd->has_pump) { ESP_RETURN_ON_ERROR(io_device_control_set_pump(cmd->pump_on), TAG, "MQTT 控制水泵失败"); @@ -96,6 +129,7 @@ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, ESP_LOGI(TAG, "MQTT 控制水泵: %s", cmd->pump_on ? "on" : "off"); } + // 处理补光灯控制命令 if (cmd->has_light) { ESP_RETURN_ON_ERROR(io_device_control_set_light(cmd->light_on), TAG, "MQTT 控制补光灯失败"); @@ -106,6 +140,12 @@ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, return ESP_OK; } +/** + * @brief 将告警指标类型转换为字符串 + * + * @param metric 告警指标类型 + * @return const char* 对应的字符串表示 + */ static const char *alert_metric_text(auto_alert_metric_t metric) { switch (metric) @@ -119,6 +159,12 @@ static const char *alert_metric_text(auto_alert_metric_t metric) } } +/** + * @brief 将告警状态转换为字符串 + * + * @param state 告警状态 + * @return const char* 对应的字符串表示 + */ static const char *alert_state_text(auto_alert_state_t state) { switch (state) @@ -132,6 +178,14 @@ static const char *alert_state_text(auto_alert_state_t state) } } +/** + * @brief 自动告警 MQTT 回调函数 + * + * 当自动告警模块触发事件时,通过此函数将告警信息以 JSON 格式发布到 MQTT。 + * + * @param event 指向告警事件结构体的指针 + * @param user_ctx 用户上下文(未使用) + */ static void auto_alert_mqtt_callback(const auto_alert_event_t *event, void *user_ctx) { (void)user_ctx; @@ -164,6 +218,19 @@ static void auto_alert_mqtt_callback(const auto_alert_event_t *event, void *user } } +/** + * @brief 自动控制逻辑更新函数 + * + * 根据当前传感器数据和阈值,决定是否需要开启或关闭水泵和补光灯。 + * + * @param soil_valid 土壤湿度数据是否有效 + * @param soil_moisture_pct 当前土壤湿度百分比 + * @param light_valid 光照数据是否有效 + * @param light_lux 当前光照强度(lux) + * @param thresholds 指向阈值配置结构体的指针 + * @param pump_on 指向当前水泵状态的指针(输入/输出) + * @param light_on 指向当前补光灯状态的指针(输入/输出) + */ static void auto_control_update(bool soil_valid, float soil_moisture_pct, bool light_valid, @@ -175,6 +242,7 @@ static void auto_control_update(bool soil_valid, bool desired_pump = *pump_on; bool desired_light = *light_on; + // 根据土壤湿度决定水泵状态 if (soil_valid) { if (!desired_pump && soil_moisture_pct < thresholds->pump_on_soil_below_pct) @@ -187,6 +255,7 @@ static void auto_control_update(bool soil_valid, } } + // 根据光照强度决定补光灯状态 if (light_valid) { if (!desired_light && light_lux < thresholds->light_on_lux_below) @@ -199,6 +268,7 @@ static void auto_control_update(bool soil_valid, } } + // 如果水泵状态需要改变,则执行控制 if (desired_pump != *pump_on) { esp_err_t ret = io_device_control_set_pump(desired_pump); @@ -216,6 +286,7 @@ static void auto_control_update(bool soil_valid, } } + // 如果补光灯状态需要改变,则执行控制 if (desired_light != *light_on) { esp_err_t ret = io_device_control_set_light(desired_light); @@ -234,6 +305,13 @@ static void auto_control_update(bool soil_valid, } } +/** + * @brief UI 任务函数 + * + * 负责定期切换显示页面(每3秒切换一次)。 + * + * @param arg 任务参数(未使用) + */ static void ui_task(void *arg) { (void)arg; @@ -266,6 +344,11 @@ static void ui_task(void *arg) } } +/** + * @brief 等待 Wi-Fi 连接成功 + * + * 在初始化 console 之前,确保 Wi-Fi 已连接成功,最多等待120秒。 + */ static void wait_for_wifi_connected(void) { const uint32_t timeout_s = 120; @@ -293,6 +376,11 @@ static void wait_for_wifi_connected(void) ESP_LOGI(TAG, "Wi-Fi 已连接,开始初始化 console"); } +/** + * @brief 主函数 + * + * 系统启动入口,初始化所有组件并进入主循环。 + */ void app_main(void) { // 初始化 Wi-Fi 配网组件,支持长按按键进入配网 @@ -480,4 +568,4 @@ void app_main(void) vTaskDelay(pdMS_TO_TICKS(1000)); } -} +} \ No newline at end of file