feat: 添加土壤和光照阈值控制,优化状态上报逻辑

This commit is contained in:
Wang Beihong
2026-03-07 02:54:45 +08:00
parent 7accf1279e
commit 981dc2b47c
2 changed files with 105 additions and 40 deletions

View File

@@ -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));
}
}