From 466ce00680f67374350410db72cef394aa8d3258 Mon Sep 17 00:00:00 2001 From: wangfq Date: Wed, 8 Jul 2026 17:21:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(iot=5Fmqtt):=20=E6=81=A2=E5=A4=8D=20loop?= =?UTF-8?q?=5Fdata=20=E5=AE=8C=E6=95=B4=E5=AD=97=E6=AE=B5=20+=20=E5=88=86?= =?UTF-8?q?=E6=89=B9=E5=8F=91=E9=80=81(2=E9=80=9A=E9=81=93/=E5=8C=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按 DLD960_TCP_JSON协议.md §5.1 恢复完整字段: - ch, freq_level, has_car, loop_ok, freq_current, freq_diff, sensitivity, condition, misc.type, misc.value 每包发 2 个通道,确保 JSON < 450 字节 (mqttBuf 512 安全范围内)。 4 通道设备每次 SensorReport 发 2 条 loop_data 消息。 --- .../APP/iot_mqtt_srv.c | 100 ++++++++++-------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index 6b14f3d..f6bc36d 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -372,7 +372,7 @@ void iot_mqtt_publish_sensor(void) { if (g_iot_state != IOT_STATE_READY) return; if (!g_report_cfg.enable) return; - /* 复用 g_pkg_uart_2 中的传感器帧 */ + /* 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; @@ -386,67 +386,75 @@ void iot_mqtt_publish_sensor(void) { return; } - /* 构建 loop_data JSON */ - static char data_json[IOT_MQTT_SEND_BUF_LEN]; // static: 避免栈溢出 - char *p = data_json; - int remaining = sizeof(data_json); - int written; + /* Batch-publish: 2 channels per message to keep each under 512 bytes. + Full-field JSON (freq_current, freq_diff, condition, misc) per the protocol doc. */ + static char data_json[1024]; // single buffer for 2-channel JSON + static char payload[1024]; + char *pub_topic = (char *)g_iot_topic.topic_pub; + uint8_t batch_start = 0; uint8_t i; - written = snprintf(p, remaining, - "{\"channels\":["); - if (written < 0 || written >= remaining) goto done; - p += written; remaining -= written; - - for (i = 0; i < sr.coil_count; i++) { - const LUP_CoilSensor *cs = &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; } - 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; } - - const char *freq_level_names[] = {"high", "mid_high", "mid_low", "low"}; + while (batch_start < sr.coil_count) { + char *p = data_json; + int remaining = sizeof(data_json); + int written; + uint8_t batch_end = batch_start + 2; + if (batch_end > sr.coil_count) batch_end = sr.coil_count; written = snprintf(p, remaining, - "%s{\"ch\":%d,\"fl\":\"%s\",\"car\":%s," - "\"ok\":%s,\"sens\":%d,\"mt\":\"%s\",\"mv\":%lu}", - (i > 0) ? "," : "", - i + 1, - freq_level_names[cs->freq_level], - cs->car_state ? "true" : "false", - cs->loop_state ? "false" : "true", - cs->sensitivity, - misc_type_str, misc_val); + "{\"channels\":["); if (written < 0 || written >= remaining) goto done; p += written; remaining -= written; - } - snprintf(p, remaining, "]}"); + for (i = batch_start; i < batch_end; i++) { + const LUP_CoilSensor *cs = &sr.coils[i]; + const char *misc_type_str = "time"; + uint32_t misc_val = 0; - /* 包装为通用消息格式 */ - static char payload[IOT_MQTT_SEND_BUF_LEN]; // static: 避免 2KB 栈溢出 - snprintf(payload, sizeof(payload), - "{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":%s}", - ++g_iot_msg_id, mstick() / 1000, data_json); + 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; } - { - uint16_t plen = (uint16_t)strlen(payload); - if (plen > 450) { - PRINT("IOT: payload too large (%u bytes), skipping\n", plen); - } else { - /* V1.01: publish to g_iot_topic.topic_pub = dld960/{sn}/dev */ - char *pub_topic = (char *)g_iot_topic.topic_pub; - mqtt_publish(pub_topic, payload, 0); + const char *freq_level_names[] = {"high", "mid_high", "mid_low", "low"}; + + written = snprintf(p, remaining, + "%s{\"ch\":%d,\"freq_level\":\"%s\",\"has_car\":%s," + "\"loop_ok\":%s,\"freq_current\":%lu,\"freq_diff\":%d," + "\"sensitivity\":%d,\"condition\":%d," + "\"misc\":{\"type\":\"%s\",\"value\":%lu}}", + (i > batch_start) ? "," : "", + i + 1, + freq_level_names[cs->freq_level], + cs->car_state ? "true" : "false", + cs->loop_state ? "false" : "true", + cs->freq, cs->variation, + cs->sensitivity, cs->condition, + misc_type_str, misc_val); + if (written < 0 || written >= remaining) goto done; + p += written; remaining -= written; } + + snprintf(p, remaining, "]}"); + + /* Wrap in outer message and publish */ + snprintf(payload, sizeof(payload), + "{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":%s}", + ++g_iot_msg_id, mstick() / 1000, data_json); + + uint16_t plen = (uint16_t)strlen(payload); + mqtt_publish(pub_topic, payload, 0); + + batch_start = batch_end; } done: InitPkgUart(&g_pkg_uart_2); } + InitPkgUart(&g_pkg_uart_2); +} + /*=========================================================================== * 心跳上报 *===========================================================================*/