From 981dc2b47cd3c6947c8cf0b9df4f5dc013b2f71a Mon Sep 17 00:00:00 2001 From: Wang Beihong Date: Sat, 7 Mar 2026 02:54:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9C=9F=E5=A3=A4?= =?UTF-8?q?=E5=92=8C=E5=85=89=E7=85=A7=E9=98=88=E5=80=BC=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E7=8A=B6=E6=80=81=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++- main/main.c | 135 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 105 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 35fb319..a615c04 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,11 @@ idf.py -p /dev/ttyACM0 flash monitor "lux": "40", "pump": "on", "light": "off", - "mode": "auto" + "mode": "auto", + "soil_on": 35.0, + "soil_off": 45.0, + "light_on": 100.0, + "light_off": 350.0 } ``` @@ -103,6 +107,10 @@ idf.py -p /dev/ttyACM0 flash monitor - `pump`:`on/off` - `light`:`on/off` - `mode`:`auto/manual` +- `soil_on`:土壤湿度低阈值(低于该值自动开泵) +- `soil_off`:土壤湿度高阈值(高于该值自动关泵) +- `light_on`:光照低阈值(低于该值自动开灯) +- `light_off`:光照高阈值(高于该值自动关灯) ### WEX -> ESP32 diff --git a/main/main.c b/main/main.c index 32c3d5a..2e35c04 100755 --- a/main/main.c +++ b/main/main.c @@ -83,6 +83,42 @@ static bool s_light_on = false; // 全局变量:自动控制模式使能(true=自动,false=手动) static bool s_auto_control_enabled = true; +/** + * @brief 发布当前完整状态快照(含阈值)到传感器主题 + */ +static esp_err_t publish_telemetry_snapshot(void) +{ + if (!mqtt_control_is_connected()) + { + return ESP_ERR_INVALID_STATE; + } + + auto_ctrl_thresholds_t thresholds = {0}; + auto_ctrl_thresholds_get(&thresholds); + + char telemetry_payload[256] = {0}; + int len = snprintf(telemetry_payload, + sizeof(telemetry_payload), + "{\"temp\":\"%s\",\"hum\":\"%s\",\"soil\":\"%s\",\"lux\":\"%s\",\"pump\":\"%s\",\"light\":\"%s\",\"mode\":\"%s\",\"soil_on\":%.1f,\"soil_off\":%.1f,\"light_on\":%.1f,\"light_off\":%.1f}", + s_air_temp, + s_air_hum, + s_soil, + s_lux, + s_pump_on ? "on" : "off", + s_light_on ? "on" : "off", + s_auto_control_enabled ? "auto" : "manual", + thresholds.pump_on_soil_below_pct, + thresholds.pump_off_soil_above_pct, + thresholds.light_on_lux_below, + thresholds.light_off_lux_above); + if (len <= 0 || len >= (int)sizeof(telemetry_payload)) + { + return ESP_ERR_INVALID_SIZE; + } + + return mqtt_control_publish_sensor(telemetry_payload, 0, 0); +} + /** * @brief MQTT 控制命令处理函数 * @@ -96,6 +132,8 @@ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, { (void)user_ctx; ESP_RETURN_ON_FALSE(cmd != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd is null"); + esp_err_t final_ret = ESP_OK; + bool has_any_control = cmd->has_mode || cmd->has_thresholds || cmd->has_pump || cmd->has_light; // 处理模式切换命令 if (cmd->has_mode) @@ -107,37 +145,73 @@ static esp_err_t mqtt_control_command_handler(const mqtt_control_command_t *cmd, // 处理阈值更新命令 if (cmd->has_thresholds) { - ESP_RETURN_ON_ERROR(auto_ctrl_thresholds_set_values(cmd->soil_on_pct, - cmd->soil_off_pct, - cmd->light_on_lux, - cmd->light_off_lux), - TAG, - "设置阈值失败"); - ESP_LOGI(TAG, - "MQTT 更新阈值: soil_on=%.1f soil_off=%.1f light_on=%.1f light_off=%.1f", - cmd->soil_on_pct, - cmd->soil_off_pct, - cmd->light_on_lux, - cmd->light_off_lux); + esp_err_t ret = auto_ctrl_thresholds_set_values(cmd->soil_on_pct, + cmd->soil_off_pct, + cmd->light_on_lux, + cmd->light_off_lux); + if (ret == ESP_OK) + { + ESP_LOGI(TAG, + "MQTT 更新阈值: soil_on=%.1f soil_off=%.1f light_on=%.1f light_off=%.1f", + cmd->soil_on_pct, + cmd->soil_off_pct, + cmd->light_on_lux, + cmd->light_off_lux); + } + else + { + ESP_LOGE(TAG, "设置阈值失败: %s", esp_err_to_name(ret)); + final_ret = ret; + } } // 处理水泵控制命令 if (cmd->has_pump) { - ESP_RETURN_ON_ERROR(io_device_control_set_pump(cmd->pump_on), TAG, "MQTT 控制水泵失败"); - s_pump_on = cmd->pump_on; - ESP_LOGI(TAG, "MQTT 控制水泵: %s", cmd->pump_on ? "on" : "off"); + esp_err_t ret = io_device_control_set_pump(cmd->pump_on); + if (ret == ESP_OK) + { + s_pump_on = cmd->pump_on; + ESP_LOGI(TAG, "MQTT 控制水泵: %s", cmd->pump_on ? "on" : "off"); + } + else + { + ESP_LOGE(TAG, "MQTT 控制水泵失败: %s", esp_err_to_name(ret)); + final_ret = ret; + } } // 处理补光灯控制命令 if (cmd->has_light) { - ESP_RETURN_ON_ERROR(io_device_control_set_light(cmd->light_on), TAG, "MQTT 控制补光灯失败"); - s_light_on = cmd->light_on; - ESP_LOGI(TAG, "MQTT 控制补光灯: %s", cmd->light_on ? "on" : "off"); + esp_err_t ret = io_device_control_set_light(cmd->light_on); + if (ret == ESP_OK) + { + s_light_on = cmd->light_on; + ESP_LOGI(TAG, "MQTT 控制补光灯: %s", cmd->light_on ? "on" : "off"); + } + else + { + ESP_LOGE(TAG, "MQTT 控制补光灯失败: %s", esp_err_to_name(ret)); + final_ret = ret; + } } - return ESP_OK; + // 任何控制指令处理后都立即上报最新状态(含阈值)作为回复。 + if (has_any_control) + { + esp_err_t pub_ret = publish_telemetry_snapshot(); + if (pub_ret != ESP_OK) + { + ESP_LOGW(TAG, "控制后立即上报失败: %s", esp_err_to_name(pub_ret)); + if (final_ret == ESP_OK) + { + final_ret = pub_ret; + } + } + } + + return final_ret; } /** @@ -542,27 +616,10 @@ void app_main(void) if (telemetry_elapsed_ms >= BOTANY_MQTT_TELEMETRY_PERIOD_MS) { telemetry_elapsed_ms = 0; - if (mqtt_control_is_connected()) + esp_err_t pub_ret = publish_telemetry_snapshot(); + if (pub_ret != ESP_OK && pub_ret != ESP_ERR_INVALID_STATE) { - char telemetry_payload[128] = {0}; - int len = snprintf(telemetry_payload, - sizeof(telemetry_payload), - "{\"temp\":\"%s\",\"hum\":\"%s\",\"soil\":\"%s\",\"lux\":\"%s\",\"pump\":\"%s\",\"light\":\"%s\",\"mode\":\"%s\"}", - s_air_temp, - s_air_hum, - s_soil, - s_lux, - s_pump_on ? "on" : "off", - s_light_on ? "on" : "off", - s_auto_control_enabled ? "auto" : "manual"); - if (len > 0 && len < (int)sizeof(telemetry_payload)) - { - esp_err_t pub_ret = mqtt_control_publish_sensor(telemetry_payload, 0, 0); - if (pub_ret != ESP_OK) - { - ESP_LOGW(TAG, "传感器上报失败: %s", esp_err_to_name(pub_ret)); - } - } + ESP_LOGW(TAG, "周期状态上报失败: %s", esp_err_to_name(pub_ret)); } }