添加 MQTT 命令处理功能,支持远程控制模式与阈值配置
This commit is contained in:
178
README.md
178
README.md
@@ -61,3 +61,181 @@
|
|||||||
set_var_fan_status("开");
|
set_var_fan_status("开");
|
||||||
set_var_light_status("开");
|
set_var_light_status("开");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MQTT 协议说明(上位机对接)
|
||||||
|
|
||||||
|
本项目通过 MQTT 实现数据上报与远程控制。上位机可直接按以下协议开发。
|
||||||
|
|
||||||
|
### 1. 连接参数与默认配置
|
||||||
|
|
||||||
|
参数来自 menuconfig:
|
||||||
|
|
||||||
|
| 配置项 | 说明 | 默认值 |
|
||||||
|
| ------ | ---- | ------ |
|
||||||
|
| AGRI_ENV_MQTT_BROKER_URI | MQTT 服务器地址 | 空 |
|
||||||
|
| AGRI_ENV_MQTT_USERNAME | MQTT 用户名 | 空 |
|
||||||
|
| AGRI_ENV_MQTT_PASSWORD | MQTT 密码 | 空 |
|
||||||
|
| AGRI_ENV_MQTT_CLIENT_ID | 客户端 ID | agri-env-monitor |
|
||||||
|
| AGRI_ENV_MQTT_PUBLISH_TOPIC | 设备上报主题 | agri/env/data |
|
||||||
|
| AGRI_ENV_MQTT_SUBSCRIBE_TOPIC | 设备订阅主题 | agri/env/cmd |
|
||||||
|
|
||||||
|
协议与连接行为:
|
||||||
|
|
||||||
|
- MQTT 协议版本:MQTT v3.1
|
||||||
|
- 如果 Broker URI 未写协议头,会自动补成 mqtt:// 并默认端口 1883
|
||||||
|
- 连接成功后设备自动订阅 AGRI_ENV_MQTT_SUBSCRIBE_TOPIC
|
||||||
|
|
||||||
|
### 2. 主题定义
|
||||||
|
|
||||||
|
| 方向 | 主题 | 用途 |
|
||||||
|
| ---- | ---- | ---- |
|
||||||
|
| 设备 -> 上位机 | agri/env/data | 周期上报环境数据、设备状态、阈值配置 |
|
||||||
|
| 上位机 -> 设备 | agri/env/cmd | 下发模式切换、阈值修改、手动控制命令 |
|
||||||
|
|
||||||
|
发布参数(当前固件实现):
|
||||||
|
|
||||||
|
- 上报周期:1 秒 1 次
|
||||||
|
- QoS:0
|
||||||
|
- Retain:0
|
||||||
|
|
||||||
|
### 3. 上报数据 JSON(agri/env/data)
|
||||||
|
|
||||||
|
#### 3.1 完整字段
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 单位/取值 | 说明 |
|
||||||
|
| ------ | ---- | --------- | ---- |
|
||||||
|
| time | string | YYYY-MM-DD HH:MM:SS | 设备本地时间 |
|
||||||
|
| lux | number | lux | 光照强度 |
|
||||||
|
| temp | number | 摄氏度 | 温度 |
|
||||||
|
| humidity | number | %RH | 湿度 |
|
||||||
|
| gas_percent | number | % | MQ-2 气体浓度百分比 |
|
||||||
|
| tvoc | number | 传感器原始单位 | TVOC(JW01) |
|
||||||
|
| hcho | number | 传感器原始单位 | 甲醛(JW01) |
|
||||||
|
| co2 | number | ppm | 二氧化碳(JW01) |
|
||||||
|
| ice_weight | number | g | HX711 重量值 |
|
||||||
|
| fire_percent | number | % | 火焰传感器百分比 |
|
||||||
|
| fire_danger | boolean | true/false | 火焰危险判定 |
|
||||||
|
| human_present | boolean | true/false | 人体存在状态 |
|
||||||
|
| door_closed | boolean | true/false | 门磁状态(true=关门) |
|
||||||
|
| fan_on | boolean | true/false | 风扇继电器状态 |
|
||||||
|
| light_on | boolean | true/false | 照明继电器状态 |
|
||||||
|
| cool_on | boolean | true/false | 制冷继电器状态 |
|
||||||
|
| hot_on | boolean | true/false | 制热继电器状态 |
|
||||||
|
| su03t_last_msgno | number | 0-255 | SU-03T 最近消息号 |
|
||||||
|
| su03t_rx_count | number | >=0 | SU-03T 累计收包次数 |
|
||||||
|
| mode | string | auto/manual | 当前控制模式 |
|
||||||
|
| th_temp_h | number | 摄氏度 | 制冷阈值(temp >= th_temp_h 触发制冷) |
|
||||||
|
| th_temp_l | number | 摄氏度 | 制热阈值(temp <= th_temp_l 触发制热) |
|
||||||
|
| th_hum_h | number | %RH | 湿度阈值(humidity >= th_hum_h 触发风扇) |
|
||||||
|
| th_gas_h | number | % | 气体阈值(gas_percent >= th_gas_h 触发风扇) |
|
||||||
|
| ip_address | string | IPv4 字符串 | 当前联网 IP |
|
||||||
|
| food_status | string | good/spoilage | 粮食状态(依据 co2 判定) |
|
||||||
|
| uptime_s | number | s | 设备运行时长 |
|
||||||
|
| free_heap_kb | number | KB | 剩余堆内存 |
|
||||||
|
|
||||||
|
#### 3.2 上报示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"time": "2026-04-22 16:24:39",
|
||||||
|
"lux": 5,
|
||||||
|
"temp": 30.8,
|
||||||
|
"humidity": 65.4,
|
||||||
|
"gas_percent": 9.7,
|
||||||
|
"tvoc": 0,
|
||||||
|
"hcho": 0,
|
||||||
|
"co2": 350,
|
||||||
|
"ice_weight": 0,
|
||||||
|
"fire_percent": 0,
|
||||||
|
"fire_danger": false,
|
||||||
|
"human_present": false,
|
||||||
|
"door_closed": false,
|
||||||
|
"fan_on": false,
|
||||||
|
"light_on": false,
|
||||||
|
"cool_on": false,
|
||||||
|
"hot_on": false,
|
||||||
|
"su03t_last_msgno": 0,
|
||||||
|
"su03t_rx_count": 0,
|
||||||
|
"mode": "manual",
|
||||||
|
"th_temp_h": 35,
|
||||||
|
"th_temp_l": 15,
|
||||||
|
"th_hum_h": 70,
|
||||||
|
"th_gas_h": 20,
|
||||||
|
"ip_address": "192.168.1.12",
|
||||||
|
"food_status": "good",
|
||||||
|
"uptime_s": 1234,
|
||||||
|
"free_heap_kb": 182
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 下发命令 JSON(agri/env/cmd)
|
||||||
|
|
||||||
|
下发命令为 JSON。字段可按需携带,未携带字段保持原值。
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
| ------ | ---- | ---- |
|
||||||
|
| mode | string | auto 或 manual |
|
||||||
|
| th_temp_h | number | 更新制冷阈值 |
|
||||||
|
| th_temp_l | number | 更新制热阈值 |
|
||||||
|
| th_hum_h | number | 更新湿度阈值 |
|
||||||
|
| th_gas_h | number | 更新气体阈值 |
|
||||||
|
| fan | boolean | 手动控制风扇继电器(1号) |
|
||||||
|
| light | boolean | 手动控制照明继电器(2号) |
|
||||||
|
| cool | boolean | 手动控制制冷继电器(3号) |
|
||||||
|
| hot | boolean | 手动控制制热继电器(4号) |
|
||||||
|
|
||||||
|
### 5. 控制逻辑规则
|
||||||
|
|
||||||
|
#### 5.1 手动模式(mode=manual)
|
||||||
|
|
||||||
|
- 支持 fan/light/cool/hot 四个布尔量直接控制继电器
|
||||||
|
- 自动联动逻辑不接管继电器
|
||||||
|
|
||||||
|
#### 5.2 自动模式(mode=auto)
|
||||||
|
|
||||||
|
- 制冷:temp >= th_temp_h 时开启,否则关闭
|
||||||
|
- 制热:temp <= th_temp_l 时开启,否则关闭
|
||||||
|
- 风扇:humidity >= th_hum_h 或 gas_percent >= th_gas_h 时开启,否则关闭
|
||||||
|
- 照明:当前自动逻辑不控制照明继电器
|
||||||
|
|
||||||
|
### 6. 上电默认值
|
||||||
|
|
||||||
|
设备上电后的默认模式与阈值:
|
||||||
|
|
||||||
|
- mode = manual
|
||||||
|
- th_temp_h = 35.0
|
||||||
|
- th_temp_l = 15.0
|
||||||
|
- th_hum_h = 70.0
|
||||||
|
- th_gas_h = 20.0
|
||||||
|
|
||||||
|
### 7. 下发示例
|
||||||
|
|
||||||
|
#### 7.1 切到自动并设置阈值
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "auto",
|
||||||
|
"th_temp_h": 28.5,
|
||||||
|
"th_temp_l": 16.0,
|
||||||
|
"th_hum_h": 65.0,
|
||||||
|
"th_gas_h": 18.0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7.2 切到手动并开风扇、开制冷
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "manual",
|
||||||
|
"fan": true,
|
||||||
|
"cool": true,
|
||||||
|
"hot": false,
|
||||||
|
"light": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. 上位机实现建议
|
||||||
|
|
||||||
|
- 命令下发后,以上报主题 agri/env/data 的最新数据作为状态确认
|
||||||
|
- 建议上位机做字段容错:新增字段应忽略,缺失字段使用默认显示
|
||||||
|
- 当前固件未提供独立 ACK 主题,建议在上位机侧做超时重发策略
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ typedef struct {
|
|||||||
} agri_env_ctx_t;
|
} agri_env_ctx_t;
|
||||||
|
|
||||||
static agri_env_ctx_t s_ctx;
|
static agri_env_ctx_t s_ctx;
|
||||||
|
static agri_env_mqtt_cmd_cb_t s_mqtt_cmd_cb = NULL;
|
||||||
|
|
||||||
|
void agri_env_set_mqtt_cmd_cb(agri_env_mqtt_cmd_cb_t cb)
|
||||||
|
{
|
||||||
|
s_mqtt_cmd_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 规范化 MQTT 代理 URI
|
* @brief 规范化 MQTT 代理 URI
|
||||||
@@ -132,6 +138,9 @@ static void agri_env_mqtt_event_handler(void *handler_args, esp_event_base_t bas
|
|||||||
event->topic,
|
event->topic,
|
||||||
event->data_len,
|
event->data_len,
|
||||||
event->data);
|
event->data);
|
||||||
|
if (s_mqtt_cmd_cb != NULL) {
|
||||||
|
s_mqtt_cmd_cb(event->topic, event->data, event->data_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ esp_err_t agri_env_mqtt_publish(const char *topic, const char *payload, int qos,
|
|||||||
/* 发布固定 MQTT-only 心跳载荷到指定主题。 */
|
/* 发布固定 MQTT-only 心跳载荷到指定主题。 */
|
||||||
esp_err_t agri_env_mqtt_publish_latest(const char *topic, int qos, int retain);
|
esp_err_t agri_env_mqtt_publish_latest(const char *topic, int qos, int retain);
|
||||||
|
|
||||||
|
typedef void (*agri_env_mqtt_cmd_cb_t)(const char *topic, const char *payload, int len);
|
||||||
|
void agri_env_set_mqtt_cmd_cb(agri_env_mqtt_cmd_cb_t cb);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
122
main/main.cpp
122
main/main.cpp
@@ -81,12 +81,85 @@ typedef struct
|
|||||||
bool hot_on;
|
bool hot_on;
|
||||||
uint8_t su03t_last_msgno;
|
uint8_t su03t_last_msgno;
|
||||||
uint32_t su03t_rx_count;
|
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;
|
} env_data_t;
|
||||||
|
|
||||||
static env_data_t s_env_data;
|
static env_data_t s_env_data;
|
||||||
static SemaphoreHandle_t s_env_data_lock = NULL;
|
static SemaphoreHandle_t s_env_data_lock = NULL;
|
||||||
static volatile bool s_ui_ready = false;
|
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
|
/* 函数: 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_last_msgno", local_data.su03t_last_msgno);
|
||||||
cJSON_AddNumberToObject(root, "su03t_rx_count", local_data.su03t_rx_count);
|
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, "ip_address", wifi_connect_get_ip());
|
||||||
cJSON_AddStringToObject(root, "food_status", local_data.co2 >= CO2_SPOILAGE_THRESHOLD_PPM ? "spoilage" : "good");
|
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秒发布一次
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,6 +613,13 @@ extern "C" void app_main(void)
|
|||||||
ESP_LOGI(TAG, "--- APP STARTING ---");
|
ESP_LOGI(TAG, "--- APP STARTING ---");
|
||||||
s_env_data_lock = xSemaphoreCreateMutex();
|
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
|
// 1. 初始化 Wi-Fi
|
||||||
ESP_ERROR_CHECK(wifi_connect_init());
|
ESP_ERROR_CHECK(wifi_connect_init());
|
||||||
|
|
||||||
@@ -554,6 +641,8 @@ extern "C" void app_main(void)
|
|||||||
{
|
{
|
||||||
set_var_system_ip(wifi_connect_get_ip());
|
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();
|
esp_err_t err = agri_env_mqtt_start();
|
||||||
if (err != ESP_OK)
|
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) {
|
if (s_env_data_lock) {
|
||||||
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
|
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.tvoc_valid) s_env_data.tvoc = jw01.tvoc;
|
||||||
if (jw01.hcho_valid) s_env_data.hcho = jw01.hcho;
|
if (jw01.hcho_valid) s_env_data.hcho = jw01.hcho;
|
||||||
if (jw01.co2_valid) s_env_data.co2 = jw01.co2;
|
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);
|
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));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
} }, "sensor_task", 4096 * 3, (void *)aht30_dev, 6, NULL);
|
} }, "sensor_task", 4096 * 3, (void *)aht30_dev, 6, NULL);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user