添加农业环境模块,集成 MQTT 客户端功能,支持配置参数和数据发布

This commit is contained in:
Wang Beihong
2026-04-22 01:21:26 +08:00
parent ffdb7065e3
commit 811b47d274
8 changed files with 425 additions and 38 deletions

View File

@@ -37,6 +37,7 @@
#include "fire_sensor.h"
#include "hx711.hpp"
#include "su-03t.h"
#include "agri_env.h"
#define TAG "MAIN"
#define CO2_SPOILAGE_THRESHOLD_PPM 1500.0f
@@ -97,7 +98,8 @@ static void reconfigure_twdt(uint32_t timeout_ms, uint32_t idle_core_mask)
};
esp_err_t ret = esp_task_wdt_reconfigure(&twdt_cfg);
if (ret != ESP_OK) {
if (ret != ESP_OK)
{
ESP_LOGW(TAG, "TWDT reconfigure failed: %s", esp_err_to_name(ret));
}
}
@@ -227,33 +229,41 @@ static void relay_status_task(void *arg)
{
bool relay_on = false;
if (relay_ctrl_get(RELAY_CTRL_ID_1, &relay_on) == ESP_OK) {
if (relay_ctrl_get(RELAY_CTRL_ID_1, &relay_on) == ESP_OK)
{
set_var_fan_status(relay_status_text(relay_on));
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.fan_on = relay_on;
xSemaphoreGive(s_env_data_lock);
}
}
if (relay_ctrl_get(RELAY_CTRL_ID_2, &relay_on) == ESP_OK) {
if (relay_ctrl_get(RELAY_CTRL_ID_2, &relay_on) == ESP_OK)
{
set_var_light_status(relay_status_text(relay_on));
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.light_on = relay_on;
xSemaphoreGive(s_env_data_lock);
}
}
if (relay_ctrl_get(RELAY_CTRL_ID_3, &relay_on) == ESP_OK) {
if (relay_ctrl_get(RELAY_CTRL_ID_3, &relay_on) == ESP_OK)
{
set_var_cool_status(relay_status_text(relay_on));
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.cool_on = relay_on;
xSemaphoreGive(s_env_data_lock);
}
}
if (relay_ctrl_get(RELAY_CTRL_ID_4, &relay_on) == ESP_OK) {
if (relay_ctrl_get(RELAY_CTRL_ID_4, &relay_on) == ESP_OK)
{
set_var_hot_status(relay_status_text(relay_on));
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.hot_on = relay_on;
xSemaphoreGive(s_env_data_lock);
@@ -272,9 +282,11 @@ static void sntp_task(void *arg)
{
(void)arg;
if (wait_for_wifi_connected(pdMS_TO_TICKS(15000))) {
if (wait_for_wifi_connected(pdMS_TO_TICKS(15000)))
{
esp_err_t sntp_ret = sntp_timp_sync_time(10000);
if (sntp_ret != ESP_OK) {
if (sntp_ret != ESP_OK)
{
ESP_LOGW(TAG, "SNTP sync failed: %s", esp_err_to_name(sntp_ret));
}
}
@@ -289,20 +301,24 @@ static void sntp_task(void *arg)
static void su03t_rx_callback(const su03t_frame_t *frame, void *user_ctx)
{
(void)user_ctx;
if (frame == NULL) {
if (frame == NULL)
{
return;
}
char hex_buf[256];
size_t pos = 0;
for (size_t i = 0; i < frame->params_len && pos + 4 < sizeof(hex_buf); ++i) {
for (size_t i = 0; i < frame->params_len && pos + 4 < sizeof(hex_buf); ++i)
{
int n = snprintf(&hex_buf[pos], sizeof(hex_buf) - pos, "%02X ", frame->params[i]);
if (n <= 0) {
if (n <= 0)
{
break;
}
pos += (size_t)n;
}
if (pos == 0) {
if (pos == 0)
{
snprintf(hex_buf, sizeof(hex_buf), "(no params)");
}
@@ -311,7 +327,8 @@ static void su03t_rx_callback(const su03t_frame_t *frame, void *user_ctx)
(unsigned)frame->params_len,
hex_buf);
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.su03t_last_msgno = frame->msgno;
s_env_data.su03t_rx_count++;
@@ -332,9 +349,11 @@ static void hx711_task(void *arg)
int tare_ok_count = 0;
// 上电空载自动去皮:当前重量作为 0g 基准
for (int i = 0; i < HX711_TARE_SAMPLES; ++i) {
for (int i = 0; i < HX711_TARE_SAMPLES; ++i)
{
int32_t raw = hx711.Read(pdMS_TO_TICKS(HX711_READ_TIMEOUT_MS));
if (raw != HX711::kUndefined) {
if (raw != HX711::kUndefined)
{
tare_sum += raw;
tare_ok_count++;
}
@@ -342,10 +361,13 @@ static void hx711_task(void *arg)
}
int32_t tare_offset = 0;
if (tare_ok_count > 0) {
if (tare_ok_count > 0)
{
tare_offset = (int32_t)(tare_sum / tare_ok_count);
ESP_LOGI(TAG, "HX711 tare done: raw0=%ld, samples=%d", (long)tare_offset, tare_ok_count);
} else {
}
else
{
ESP_LOGW(TAG, "HX711 tare failed, use 0 as offset");
}
@@ -355,14 +377,18 @@ static void hx711_task(void *arg)
bool display_locked = false;
uint32_t stable_count = 0;
uint32_t err_cnt = 0;
for (;;) {
for (;;)
{
int32_t value = hx711.Read(pdMS_TO_TICKS(HX711_READ_TIMEOUT_MS));
if (value != HX711::kUndefined) {
if (value != HX711::kUndefined)
{
float weight_g = ((float)(value - tare_offset)) / HX711_COUNTS_PER_GRAM;
if (fabsf(weight_g) < HX711_ZERO_DEADBAND_G) {
if (fabsf(weight_g) < HX711_ZERO_DEADBAND_G)
{
weight_g = 0.0f;
}
if (weight_g < 0.0f) {
if (weight_g < 0.0f)
{
weight_g = 0.0f;
}
@@ -370,7 +396,8 @@ static void hx711_task(void *arg)
filtered_weight_g = filtered_weight_g * (1.0f - HX711_FILTER_ALPHA) + weight_g * HX711_FILTER_ALPHA;
float rounded_weight_g = roundf(filtered_weight_g * 100.0f) / 100.0f;
if (!display_initialized) {
if (!display_initialized)
{
display_weight_g = rounded_weight_g;
display_initialized = true;
}
@@ -378,40 +405,53 @@ static void hx711_task(void *arg)
float diff_from_display = fabsf(rounded_weight_g - display_weight_g);
// 稳定后锁定显示,重量明显变化时再解锁并继续更新
if (display_locked) {
if (diff_from_display >= HX711_UNLOCK_DELTA_G) {
if (display_locked)
{
if (diff_from_display >= HX711_UNLOCK_DELTA_G)
{
display_locked = false;
stable_count = 0;
}
}
if (!display_locked) {
if (diff_from_display <= HX711_STABLE_BAND_G) {
if (stable_count < HX711_STABLE_SAMPLES) {
if (!display_locked)
{
if (diff_from_display <= HX711_STABLE_BAND_G)
{
if (stable_count < HX711_STABLE_SAMPLES)
{
stable_count++;
}
if (stable_count >= HX711_STABLE_SAMPLES) {
if (stable_count >= HX711_STABLE_SAMPLES)
{
display_locked = true;
}
} else {
}
else
{
stable_count = 0;
}
if (diff_from_display >= HX711_UPDATE_MIN_STEP_G) {
if (diff_from_display >= HX711_UPDATE_MIN_STEP_G)
{
display_weight_g = rounded_weight_g;
}
}
set_var_ice_weight(display_weight_g);
if (s_env_data_lock) {
if (s_env_data_lock)
{
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
s_env_data.ice_weight = display_weight_g;
xSemaphoreGive(s_env_data_lock);
}
err_cnt = 0;
} else {
if ((++err_cnt % 20) == 0) {
}
else
{
if ((++err_cnt % 20) == 0)
{
ESP_LOGW(TAG, "HX711 read timeout, check DOUT/SCK wiring and power");
}
}
@@ -449,6 +489,12 @@ extern "C" void app_main(void)
if (wait_for_wifi_connected(pdMS_TO_TICKS(15000)))
{
set_var_system_ip(wifi_connect_get_ip());
esp_err_t err = agri_env_mqtt_start();
if (err != ESP_OK)
{
ESP_LOGW(TAG, "MQTT 启动失败: %s", esp_err_to_name(err));
}
}
// 4. 独立 SNTP 对时任务