feat: 添加传感器配置和MQTT控制功能,优化自动控制逻辑

This commit is contained in:
Wang Beihong
2026-03-07 02:48:58 +08:00
parent 5980e171c4
commit 7accf1279e

View File

@@ -19,60 +19,92 @@
#include "auto_alerts.h" #include "auto_alerts.h"
#include "mqtt_control.h" // MQTT 控制接口 #include "mqtt_control.h" // MQTT 控制接口
// 配置宏定义BH1750 光照传感器是否启用(默认禁用)
#ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE #ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE
#define CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE 0 #define CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE 0
#endif #endif
// 配置宏定义AHT30 温湿度传感器是否启用(默认禁用)
#ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE #ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE
#define CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE 0 #define CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE 0
#endif #endif
// 配置宏定义BH1750 读取周期毫秒默认500ms
#ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS #ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS
#define CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS 500 #define CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS 500
#endif #endif
// 配置宏定义AHT30 读取周期毫秒默认2000ms
#ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS #ifndef CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS
#define CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS 2000 #define CONFIG_I2C_MASTER_MESSAGER_AHT30_READ_PERIOD_MS 2000
#endif #endif
// 配置宏定义I2C 是否启用内部上拉电阻(默认启用)
#ifndef CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP #ifndef CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP
#define CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP 1 #define CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP 1
#endif #endif
// I2C 端口配置
#define BOTANY_I2C_PORT I2C_NUM_0 #define BOTANY_I2C_PORT I2C_NUM_0
// I2C SCL 引脚
#define BOTANY_I2C_SCL_GPIO GPIO_NUM_5 #define BOTANY_I2C_SCL_GPIO GPIO_NUM_5
// I2C SDA 引脚
#define BOTANY_I2C_SDA_GPIO GPIO_NUM_4 #define BOTANY_I2C_SDA_GPIO GPIO_NUM_4
// BH1750 使能标志
#define BOTANY_BH1750_ENABLE CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE #define BOTANY_BH1750_ENABLE CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE
// AHT30 使能标志
#define BOTANY_AHT30_ENABLE CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE #define BOTANY_AHT30_ENABLE CONFIG_I2C_MASTER_MESSAGER_AHT30_ENABLE
// BH1750 读取周期
#define BOTANY_BH1750_PERIOD_MS CONFIG_I2C_MASTER_MESSAGER_BH1750_READ_PERIOD_MS #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 #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 #define BOTANY_I2C_INTERNAL_PULLUP CONFIG_I2C_MASTER_MESSAGER_ENABLE_INTERNAL_PULLUP
// MQTT 告警主题
#define BOTANY_MQTT_ALERT_TOPIC "topic/alert/esp32_iothome_001" #define BOTANY_MQTT_ALERT_TOPIC "topic/alert/esp32_iothome_001"
// MQTT 遥测数据上报周期(毫秒)
#define BOTANY_MQTT_TELEMETRY_PERIOD_MS 5000 #define BOTANY_MQTT_TELEMETRY_PERIOD_MS 5000
// 日志标签
static const char *TAG = "main"; static const char *TAG = "main";
// 全局变量:存储空气温度字符串
static char s_air_temp[16]; static char s_air_temp[16];
// 全局变量:存储空气湿度字符串
static char s_air_hum[16]; static char s_air_hum[16];
// 全局变量:存储土壤湿度字符串
static char s_soil[16]; static char s_soil[16];
// 全局变量:存储光照强度字符串
static char s_lux[16]; static char s_lux[16];
// 全局变量水泵状态true=开启false=关闭)
static bool s_pump_on = false; static bool s_pump_on = false;
// 全局变量补光灯状态true=开启false=关闭)
static bool s_light_on = false; static bool s_light_on = false;
// 全局变量自动控制模式使能true=自动false=手动)
static bool s_auto_control_enabled = true; 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) static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, void *user_ctx)
{ {
(void)user_ctx; (void)user_ctx;
ESP_RETURN_ON_FALSE(cmd != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd is null"); ESP_RETURN_ON_FALSE(cmd != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd is null");
// 处理模式切换命令
if (cmd->has_mode) if (cmd->has_mode)
{ {
s_auto_control_enabled = cmd->auto_mode; s_auto_control_enabled = cmd->auto_mode;
ESP_LOGI(TAG, "MQTT 控制模式切换: %s", s_auto_control_enabled ? "auto" : "manual"); ESP_LOGI(TAG, "MQTT 控制模式切换: %s", s_auto_control_enabled ? "auto" : "manual");
} }
// 处理阈值更新命令
if (cmd->has_thresholds) if (cmd->has_thresholds)
{ {
ESP_RETURN_ON_ERROR(auto_ctrl_thresholds_set_values(cmd->soil_on_pct, 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); cmd->light_off_lux);
} }
// 处理水泵控制命令
if (cmd->has_pump) if (cmd->has_pump)
{ {
ESP_RETURN_ON_ERROR(io_device_control_set_pump(cmd->pump_on), TAG, "MQTT 控制水泵失败"); 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"); ESP_LOGI(TAG, "MQTT 控制水泵: %s", cmd->pump_on ? "on" : "off");
} }
// 处理补光灯控制命令
if (cmd->has_light) if (cmd->has_light)
{ {
ESP_RETURN_ON_ERROR(io_device_control_set_light(cmd->light_on), TAG, "MQTT 控制补光灯失败"); 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; return ESP_OK;
} }
/**
* @brief 将告警指标类型转换为字符串
*
* @param metric 告警指标类型
* @return const char* 对应的字符串表示
*/
static const char *alert_metric_text(auto_alert_metric_t metric) static const char *alert_metric_text(auto_alert_metric_t metric)
{ {
switch (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) static const char *alert_state_text(auto_alert_state_t state)
{ {
switch (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) static void auto_alert_mqtt_callback(const auto_alert_event_t *event, void *user_ctx)
{ {
(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, static void auto_control_update(bool soil_valid,
float soil_moisture_pct, float soil_moisture_pct,
bool light_valid, bool light_valid,
@@ -175,6 +242,7 @@ static void auto_control_update(bool soil_valid,
bool desired_pump = *pump_on; bool desired_pump = *pump_on;
bool desired_light = *light_on; bool desired_light = *light_on;
// 根据土壤湿度决定水泵状态
if (soil_valid) if (soil_valid)
{ {
if (!desired_pump && soil_moisture_pct < thresholds->pump_on_soil_below_pct) 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 (light_valid)
{ {
if (!desired_light && light_lux < thresholds->light_on_lux_below) 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) if (desired_pump != *pump_on)
{ {
esp_err_t ret = io_device_control_set_pump(desired_pump); 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) if (desired_light != *light_on)
{ {
esp_err_t ret = io_device_control_set_light(desired_light); 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) static void ui_task(void *arg)
{ {
(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) static void wait_for_wifi_connected(void)
{ {
const uint32_t timeout_s = 120; const uint32_t timeout_s = 120;
@@ -293,6 +376,11 @@ static void wait_for_wifi_connected(void)
ESP_LOGI(TAG, "Wi-Fi 已连接,开始初始化 console"); ESP_LOGI(TAG, "Wi-Fi 已连接,开始初始化 console");
} }
/**
* @brief 主函数
*
* 系统启动入口,初始化所有组件并进入主循环。
*/
void app_main(void) void app_main(void)
{ {
// 初始化 Wi-Fi 配网组件,支持长按按键进入配网 // 初始化 Wi-Fi 配网组件,支持长按按键进入配网
@@ -480,4 +568,4 @@ void app_main(void)
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1000));
} }
} }