feat: 添加传感器配置和MQTT控制功能,优化自动控制逻辑
This commit is contained in:
94
main/main.c
94
main/main.c
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user