From 403770e1c86f6e17d67ba09499c049d9b2563867 Mon Sep 17 00:00:00 2001 From: wangfq Date: Mon, 13 Jul 2026 10:57:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(iot=5Fmqtt):=20=E4=BC=A0=E6=84=9F=E5=99=A8?= =?UTF-8?q?MQTT=E4=B8=BB=E5=8A=A8=E4=B8=8A=E6=8A=A5=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=8F=8C=E9=80=9F=E7=8E=87=E9=97=B4=E9=9A=94=E4=B8=8A=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增传感器数据缓存(_cached_sr), 0xC0帧到达时更新缓存, 不上报 - 根据各通道 variation 决定上报间隔: 空闲态(diff < 10): 使用 g_report_cfg.interval 秒 变化态(diff >= 10): 固定 300ms 快速上报 - interval=0 时自动退化为最小 1s 空闲间隔 - 断线时清缓存+复位计时, 重连后等新帧首发 - 消除对 g_pkg_uart_2.flag 的硬依赖, 从缓存自主定时上报 新增常量: IOT_MQTT_FAST_INTERVAL_MS 300 IOT_MQTT_VARIATION_THRESHOLD 10 IOT_MQTT_IDLE_INTERVAL_MIN_MS 1000 --- .../APP/iot_mqtt_srv.c | 100 +++++++++++++----- 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index dc18169..ba73153 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -42,6 +42,17 @@ static uint32_t _iot_reconnect_deadline = 0; static uint32_t _iot_reconnect_backoff = 0; static uint32_t _iot_connect_start = 0; // TCP connect 开始时刻 +/*=========================================================================== + * 传感器数据缓存 & 上报间隔控制 + *===========================================================================*/ +#define IOT_MQTT_FAST_INTERVAL_MS 300 // 变化态快速上报间隔 (ms) +#define IOT_MQTT_VARIATION_THRESHOLD 10 // diff 阈值: >= 此值进入快速上报 +#define IOT_MQTT_IDLE_INTERVAL_MIN_MS 1000 // 空闲间隔最小 1s (防 interval=0 死锁) + +static LUP_SensorReport _cached_sr; // 最新传感器数据缓存 +static uint8_t _cached_sr_valid; // 缓存有效标志 +static uint32_t _last_publish_ms; // 上次上报时刻 (ms) + /*=========================================================================== * Buffers *===========================================================================*/ @@ -363,29 +374,71 @@ static void iot_process_recv(void) { } /*=========================================================================== - * 传感器数据上报 + * 传感器数据上报 (双速率: 空闲态按 interval 上报, 变化态 300ms 快速上报) + * + * Step 1 — 消费 Loop MCU 新帧 → 更新缓存 + * Step 2 — 对所有通道检测 variation, 决定上报间隔 + * Step 3 — 间隔门控: 时间到了才从缓存发布 *===========================================================================*/ void iot_mqtt_publish_sensor(void) { if (g_iot_state != IOT_STATE_READY) return; if (!g_report_cfg.enable) return; - /* Reuse g_pkg_uart_2 sensor frame from Loop MCU */ - if (g_pkg_uart_2.flag == 0) return; - if (g_pkg_uart_2.pkg[0] != 0x7F) return; - if (g_pkg_uart_2.pkg[3] != 0xC0) return; + /*--- Step 1: 消费 0xC0 帧 → 更新缓存 ---*/ + if (g_pkg_uart_2.flag != 0 + && g_pkg_uart_2.pkg[0] == 0x7F + && g_pkg_uart_2.pkg[3] == 0xC0) { - LUP_SensorReport sr; - memset(&sr, 0, sizeof(sr)); - int ret = lup_parse_sensor_report(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &sr); - if (ret != 0) { - PRINT("IOT: sensor parse failed (%d)\n", ret); - InitPkgUart(&g_pkg_uart_2); - return; + LUP_SensorReport sr; + memset(&sr, 0, sizeof(sr)); + int ret = lup_parse_sensor_report(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &sr); + InitPkgUart(&g_pkg_uart_2); // 读完即清, 不持有 + + if (ret == 0) { + memcpy(&_cached_sr, &sr, sizeof(sr)); + _cached_sr_valid = 1; + } else { + PRINT("IOT: sensor parse failed (%d)\n", ret); + } } - /* 全通道一次性上报,字段按 DLD960_IoT_MQTT协议.md §5.2 V1.02: - ch, level, iscar, loop_ok, freq, diff, sens, cndtn, misc.{type,value} - 注意: mqttBuf 需 ≥ 1024 才能容纳 4 通道全字段封包 (~800 字节) */ + /* 尚无缓存数据 → 不发 */ + if (!_cached_sr_valid) return; + + /*--- Step 2: 判断是否进入变化态 (任一通道 diff >= 10) ---*/ + uint32_t interval_ms; + uint8_t fast_mode = 0; + + { + uint8_t i; + for (i = 0; i < _cached_sr.coil_count; i++) { + if (_cached_sr.coils[i].variation >= IOT_MQTT_VARIATION_THRESHOLD) { + fast_mode = 1; + break; + } + } + } + + if (fast_mode) { + interval_ms = IOT_MQTT_FAST_INTERVAL_MS; // 300ms + } else { + /* 空闲态: 使用配置的 interval (秒→毫秒), 最小 1s */ + uint32_t cfg_ms = (uint32_t)g_report_cfg.interval * 1000; + interval_ms = (cfg_ms >= IOT_MQTT_IDLE_INTERVAL_MIN_MS) + ? cfg_ms : IOT_MQTT_IDLE_INTERVAL_MIN_MS; + } + + /*--- Step 3: 间隔门控 ---*/ + { + uint32_t now = mstick(); + if (_last_publish_ms != 0 + && (now - _last_publish_ms) < interval_ms) { + return; // 未到间隔 + } + _last_publish_ms = now; + } + + /*--- Step 4: 构建 JSON → 发布 (字段与 V1.02 协议一致) ---*/ static char data_json[1024]; static char payload[1400]; char *p = data_json; @@ -395,16 +448,16 @@ void iot_mqtt_publish_sensor(void) { uint8_t i; written = snprintf(p, remaining, "{\"channels\":["); - if (written < 0 || written >= remaining) goto done; + if (written < 0 || written >= remaining) return; p += written; remaining -= written; - for (i = 0; i < sr.coil_count; i++) { - const LUP_CoilSensor *cs = &sr.coils[i]; + for (i = 0; i < _cached_sr.coil_count; i++) { + const LUP_CoilSensor *cs = &_cached_sr.coils[i]; const char *misc_type_str = "time"; uint32_t misc_val = 0; - if (cs->misc_type == 0) { misc_type_str = "time"; misc_val = cs->misc.passtime_ms; } - else if (cs->misc_type == 1) { misc_type_str = "cut_count"; misc_val = cs->misc.cut_amount; } + if (cs->misc_type == 0) { misc_type_str = "time"; misc_val = cs->misc.passtime_ms; } + else if (cs->misc_type == 1) { misc_type_str = "cut_count"; misc_val = cs->misc.cut_amount; } else if (cs->misc_type == 2) { misc_type_str = "flow_count"; misc_val = cs->misc.flow_amount; } else if (cs->misc_type == 3) { misc_type_str = "relay_count"; misc_val = cs->misc.relay_count; } @@ -421,7 +474,7 @@ void iot_mqtt_publish_sensor(void) { cs->freq, cs->variation, cs->sensitivity, cs->condition, misc_type_str, misc_val); - if (written < 0 || written >= remaining) goto done; + if (written < 0 || written >= remaining) return; p += written; remaining -= written; } @@ -437,9 +490,6 @@ void iot_mqtt_publish_sensor(void) { snprintf(topic, sizeof(topic), "dld960/%s/dev", g_iot_dev_serial); mqtt_publish(topic, payload, 0); } - -done: - InitPkgUart(&g_pkg_uart_2); } /*=========================================================================== @@ -519,6 +569,8 @@ void iot_mqtt_handle_sock_int(uint8_t socketid, uint8_t intstat) { g_iot_state = IOT_STATE_DISCONNECTED; g_iot_socket = 0xFF; _iot_recv_len = 0; + _cached_sr_valid = 0; // 清缓存: 重连后等新帧 + _last_publish_ms = 0; // 复位: 重连后立即首发 _iot_reconnect_backoff = IOT_MQTT_RECONNECT_MIN_MS; _iot_reconnect_deadline = mstick() + _iot_reconnect_backoff; }