添加 MQTT 命令处理功能,支持远程控制模式与阈值配置
This commit is contained in:
122
main/main.cpp
122
main/main.cpp
@@ -81,12 +81,85 @@ typedef struct
|
||||
bool hot_on;
|
||||
uint8_t su03t_last_msgno;
|
||||
uint32_t su03t_rx_count;
|
||||
|
||||
// ======== 新增:阈值与模式配置 ========
|
||||
bool auto_mode; // 自动/手动模式:true=自动,false=手动
|
||||
float th_temp_h; // 制冷阈值(温度高于此值开启制冷)
|
||||
float th_temp_l; // 制热阈值(温度低于此值开启制热)
|
||||
float th_hum_h; // 湿度排风阈值
|
||||
float th_gas_h; // 烟雾/有害气体排风阈值
|
||||
} env_data_t;
|
||||
|
||||
static env_data_t s_env_data;
|
||||
static SemaphoreHandle_t s_env_data_lock = NULL;
|
||||
static volatile bool s_ui_ready = false;
|
||||
|
||||
/* 函数: app_mqtt_cmd_handler
|
||||
* 作用: 解析并处理远端下发的 MQTT 配置项和手动控制指令
|
||||
*/
|
||||
static void app_mqtt_cmd_handler(const char *topic, const char *payload, int len)
|
||||
{
|
||||
// 如果不是下发的命令主题则忽略(可根据需要支持通配符判断,这里简单处理)
|
||||
// 将 payload 拷贝并追加 \0 变为合法字符串
|
||||
char *json_str = (char*)malloc(len + 1);
|
||||
if (!json_str) return;
|
||||
memcpy(json_str, payload, len);
|
||||
json_str[len] = '\0';
|
||||
|
||||
cJSON *root = cJSON_Parse(json_str);
|
||||
if (root)
|
||||
{
|
||||
bool auto_mode = false; // 默认手动
|
||||
if (s_env_data_lock)
|
||||
{
|
||||
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
|
||||
|
||||
// 1. 解析模式
|
||||
cJSON *item = cJSON_GetObjectItem(root, "mode");
|
||||
if (item && cJSON_IsString(item)) {
|
||||
if (strcmp(item->valuestring, "auto") == 0) s_env_data.auto_mode = true;
|
||||
else if (strcmp(item->valuestring, "manual") == 0) s_env_data.auto_mode = false;
|
||||
}
|
||||
|
||||
// 2. 解析阈值配置
|
||||
item = cJSON_GetObjectItem(root, "th_temp_h");
|
||||
if (item && cJSON_IsNumber(item)) s_env_data.th_temp_h = item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "th_temp_l");
|
||||
if (item && cJSON_IsNumber(item)) s_env_data.th_temp_l = item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "th_hum_h");
|
||||
if (item && cJSON_IsNumber(item)) s_env_data.th_hum_h = item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "th_gas_h");
|
||||
if (item && cJSON_IsNumber(item)) s_env_data.th_gas_h = item->valuedouble;
|
||||
|
||||
auto_mode = s_env_data.auto_mode;
|
||||
|
||||
xSemaphoreGive(s_env_data_lock);
|
||||
}
|
||||
|
||||
// 3. 在手动模式下响应远程控制
|
||||
if (!auto_mode)
|
||||
{
|
||||
cJSON *item = cJSON_GetObjectItem(root, "fan");
|
||||
if (item && cJSON_IsBool(item)) relay_ctrl_set(RELAY_CTRL_ID_1, cJSON_IsTrue(item));
|
||||
|
||||
item = cJSON_GetObjectItem(root, "light");
|
||||
if (item && cJSON_IsBool(item)) relay_ctrl_set(RELAY_CTRL_ID_2, cJSON_IsTrue(item));
|
||||
|
||||
item = cJSON_GetObjectItem(root, "cool");
|
||||
if (item && cJSON_IsBool(item)) relay_ctrl_set(RELAY_CTRL_ID_3, cJSON_IsTrue(item));
|
||||
|
||||
item = cJSON_GetObjectItem(root, "hot");
|
||||
if (item && cJSON_IsBool(item)) relay_ctrl_set(RELAY_CTRL_ID_4, cJSON_IsTrue(item));
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
free(json_str);
|
||||
}
|
||||
|
||||
/* 函数: reconfigure_twdt
|
||||
* 作用: 执行模块内与函数名对应的业务逻辑。
|
||||
* 重点: 关注输入合法性、返回码与并发安全。
|
||||
@@ -503,6 +576,13 @@ static void mqtt_publish_task(void *arg)
|
||||
cJSON_AddNumberToObject(root, "su03t_last_msgno", local_data.su03t_last_msgno);
|
||||
cJSON_AddNumberToObject(root, "su03t_rx_count", local_data.su03t_rx_count);
|
||||
|
||||
// ======== 新增:系统模式与阈值 ========
|
||||
cJSON_AddStringToObject(root, "mode", local_data.auto_mode ? "auto" : "manual");
|
||||
cJSON_AddNumberToObject(root, "th_temp_h", local_data.th_temp_h);
|
||||
cJSON_AddNumberToObject(root, "th_temp_l", local_data.th_temp_l);
|
||||
cJSON_AddNumberToObject(root, "th_hum_h", local_data.th_hum_h);
|
||||
cJSON_AddNumberToObject(root, "th_gas_h", local_data.th_gas_h);
|
||||
|
||||
// 补充系统及其他分析状态数据
|
||||
cJSON_AddStringToObject(root, "ip_address", wifi_connect_get_ip());
|
||||
cJSON_AddStringToObject(root, "food_status", local_data.co2 >= CO2_SPOILAGE_THRESHOLD_PPM ? "spoilage" : "good");
|
||||
@@ -519,7 +599,7 @@ static void mqtt_publish_task(void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(5000)); // 每5秒发布一次
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // 每1秒发布一次
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,6 +612,13 @@ extern "C" void app_main(void)
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_LOGI(TAG, "--- APP STARTING ---");
|
||||
s_env_data_lock = xSemaphoreCreateMutex();
|
||||
|
||||
// 初始化默认配置与阈值
|
||||
s_env_data.auto_mode = false; // 默认手动模式
|
||||
s_env_data.th_temp_h = 35.0f; // 超过 35度 制冷
|
||||
s_env_data.th_temp_l = 15.0f; // 低于 15度 制热
|
||||
s_env_data.th_hum_h = 70.0f; // 湿度高于 70% 通风
|
||||
s_env_data.th_gas_h = 20.0f; // 气体浓度高于 20% 通风
|
||||
|
||||
// 1. 初始化 Wi-Fi
|
||||
ESP_ERROR_CHECK(wifi_connect_init());
|
||||
@@ -554,6 +641,8 @@ extern "C" void app_main(void)
|
||||
{
|
||||
set_var_system_ip(wifi_connect_get_ip());
|
||||
|
||||
// 注册 MQTT 数据接收回调
|
||||
agri_env_set_mqtt_cmd_cb(app_mqtt_cmd_handler);
|
||||
esp_err_t err = agri_env_mqtt_start();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
@@ -672,6 +761,13 @@ extern "C" void app_main(void)
|
||||
}
|
||||
|
||||
|
||||
// 提取自动化逻辑所需参数
|
||||
bool auto_mode = false; // 默认手动
|
||||
float th_temp_h = 35.0f;
|
||||
float th_temp_l = 15.0f;
|
||||
float th_hum_h = 70.0f;
|
||||
float th_gas_h = 20.0f;
|
||||
|
||||
// 数据存入共享结构体
|
||||
if (s_env_data_lock) {
|
||||
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
|
||||
@@ -684,8 +780,32 @@ extern "C" void app_main(void)
|
||||
if (jw01.tvoc_valid) s_env_data.tvoc = jw01.tvoc;
|
||||
if (jw01.hcho_valid) s_env_data.hcho = jw01.hcho;
|
||||
if (jw01.co2_valid) s_env_data.co2 = jw01.co2;
|
||||
|
||||
auto_mode = s_env_data.auto_mode;
|
||||
th_temp_h = s_env_data.th_temp_h;
|
||||
th_temp_l = s_env_data.th_temp_l;
|
||||
th_hum_h = s_env_data.th_hum_h;
|
||||
th_gas_h = s_env_data.th_gas_h;
|
||||
|
||||
xSemaphoreGive(s_env_data_lock);
|
||||
}
|
||||
|
||||
// ======== 新增:自动联动逻辑 ========
|
||||
if (auto_mode)
|
||||
{
|
||||
// 制冷控制(温度高于上限)
|
||||
if (temp >= th_temp_h) relay_ctrl_set(RELAY_CTRL_ID_3, true);
|
||||
else relay_ctrl_set(RELAY_CTRL_ID_3, false);
|
||||
|
||||
// 制热控制(温度低于下限)
|
||||
if (temp <= th_temp_l) relay_ctrl_set(RELAY_CTRL_ID_4, true);
|
||||
else relay_ctrl_set(RELAY_CTRL_ID_4, false);
|
||||
|
||||
// 风扇控制(湿度或有害气体超标)
|
||||
if (hum >= th_hum_h || gas_percent >= th_gas_h) relay_ctrl_set(RELAY_CTRL_ID_1, true);
|
||||
else relay_ctrl_set(RELAY_CTRL_ID_1, false);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
} }, "sensor_task", 4096 * 3, (void *)aht30_dev, 6, NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user