fix(vd960DBN): 消灭 data_json[1024] 中间缓冲, 防 BSS 重叠致 MQTT 上报 _raw 异常
- root cause: data_json[1024] + payload[1400] BSS 合计 2424B, 叠加 iot_mqtt_srv.c 其他缓冲 (~9KB total), 在 48KB RAM 上 与 mqttBuf[1024] 重叠, event_report 的 MQTT 二进制 泄漏到 loop_data payload - fix: 直接在 payload 构建完整 JSON, 省 1024B BSS - defense: coil_count > 4 硬限, 防 0xC0 坏帧溢出 - JSON 输出格式不变 - also: set_response_tran_to_notify 加返回值 - also: uart_srv BLE 通知逻辑重构
This commit is contained in:
@@ -308,6 +308,7 @@ uint8_t set_response_tran_to_notify(uint8_t *dat_ori, uint8_t dat_len, BLE_Notif
|
|||||||
}
|
}
|
||||||
notify_dst->len = dat_len;
|
notify_dst->len = dat_len;
|
||||||
notify_dst->flag = 1;
|
notify_dst->flag = 1;
|
||||||
|
return notify_dst->flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -685,20 +685,28 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--- Step 4: 构建 JSON → 发布 (字段与 V1.02 协议一致) ---*/
|
/*--- Step 4: 构建 JSON → 发布 (字段与 V1.02 协议一致) ---
|
||||||
static char data_json[1024];
|
直接构建到 payload, 省掉 data_json[1024] 中间缓冲:
|
||||||
|
- 消除 BSS 压力 (省 1024B), 降低与 mqttBuf 重叠风险
|
||||||
|
- 消除 %s 拷贝尾部二进制残留的路径 (2026-07-23 _raw 事故)
|
||||||
|
- coil_count 边界硬限, 防 0xC0 坏帧致溢出 */
|
||||||
static char payload[1400];
|
static char payload[1400];
|
||||||
char *p = data_json;
|
char *p = payload;
|
||||||
int remaining = sizeof(data_json);
|
int remaining = sizeof(payload);
|
||||||
int written;
|
int written;
|
||||||
const char *freq_level_names[] = {"high", "mid_high", "mid_low", "low"};
|
const char *freq_level_names[] = {"high", "mid_high", "mid_low", "low"};
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
uint8_t coil_n = _cached_sr.coil_count;
|
||||||
|
if (coil_n > 4) coil_n = 4; /* 硬限: 防坏帧致 snprintf 循环溢出 */
|
||||||
|
|
||||||
written = snprintf(p, remaining, "{\"channels\":[");
|
/* 先写外层包装头 (msg_id/cmd/ts/data) */
|
||||||
|
written = snprintf(p, remaining,
|
||||||
|
"{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":{\"channels\":[",
|
||||||
|
++g_iot_msg_id, dev_time_now());
|
||||||
if (written < 0 || written >= remaining) return;
|
if (written < 0 || written >= remaining) return;
|
||||||
p += written; remaining -= written;
|
p += written; remaining -= written;
|
||||||
|
|
||||||
for (i = 0; i < _cached_sr.coil_count; i++) {
|
for (i = 0; i < coil_n; i++) {
|
||||||
const LUP_CoilSensor *cs = &_cached_sr.coils[i];
|
const LUP_CoilSensor *cs = &_cached_sr.coils[i];
|
||||||
const char *misc_type_str = "time";
|
const char *misc_type_str = "time";
|
||||||
uint32_t misc_val = 0;
|
uint32_t misc_val = 0;
|
||||||
@@ -725,12 +733,7 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
p += written; remaining -= written;
|
p += written; remaining -= written;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(p, remaining, "]}");
|
snprintf(p, remaining, "]}}");
|
||||||
|
|
||||||
/* Wrap and publish — V1.01 双主题模型: dld960/{sn}/dev */
|
|
||||||
snprintf(payload, sizeof(payload),
|
|
||||||
"{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":%s}",
|
|
||||||
++g_iot_msg_id, dev_time_now(), data_json);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
char topic[IOT_MQTT_TOPIC_MAX_LEN];
|
char topic[IOT_MQTT_TOPIC_MAX_LEN];
|
||||||
|
|||||||
@@ -172,10 +172,16 @@ void uart_srv(void)
|
|||||||
if(g_dbn_ble_state_acs_enable.flag != 0){
|
if(g_dbn_ble_state_acs_enable.flag != 0){
|
||||||
// BLE ACS 已连接 → 改 Magic 为 0x8F 发给 BLE
|
// BLE ACS 已连接 → 改 Magic 为 0x8F 发给 BLE
|
||||||
g_pkg_uart_2.pkg[0] = 0x8F;
|
g_pkg_uart_2.pkg[0] = 0x8F;
|
||||||
_report_flag = 1; // 保留给 BLE
|
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp); // 保留给 BLE
|
||||||
}
|
}
|
||||||
// else: 回调已推送 TCP,直接清理
|
// else: 回调已推送 TCP,直接清理
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if(g_flag_bt_state){
|
||||||
|
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp);
|
||||||
|
InitPkgUart(&g_pkg_uart_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 调试打印
|
// 调试打印
|
||||||
for(i = 0; i < g_pkg_uart_2.offset; i++){
|
for(i = 0; i < g_pkg_uart_2.offset; i++){
|
||||||
@@ -183,10 +189,6 @@ void uart_srv(void)
|
|||||||
}
|
}
|
||||||
PRINT("\n");
|
PRINT("\n");
|
||||||
|
|
||||||
if(_report_flag){
|
|
||||||
// 传感器帧保留在 pkg 中供上层 (tcp_json_srv) 处理
|
|
||||||
// 不 InitPkgUart — 由 tcp_json_push_sensor 消费后清理
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 非 0x7F 魔法字节
|
// 非 0x7F 魔法字节
|
||||||
@@ -199,16 +201,11 @@ void uart_srv(void)
|
|||||||
|
|
||||||
|
|
||||||
if(g_flag_bt_state){
|
if(g_flag_bt_state){
|
||||||
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
g_dbn_ble_state_acs_enable.flag = 0;
|
g_dbn_ble_state_acs_enable.flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只有非 _report_flag 时才立即清空
|
|
||||||
// _report_flag 的帧由 tcp_json_push_sensor 消费后清理
|
|
||||||
if (!_report_flag) {
|
|
||||||
InitPkgUart(&g_pkg_uart_2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,9 +485,43 @@ uint16_t pkt_id = (req_qos > 0) ? ++s_mqtt_pkt_id : 0;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-07-23 — loop_data JSON 构建优化: 消灭 data_json 中间缓冲 + coil_count 硬限
|
||||||
|
|
||||||
|
### 背景 / 问题
|
||||||
|
|
||||||
|
现场 DC045A49718F 出现 MQTT 上报异常: 平台收到 `_raw` 消息, hex 解码后发现
|
||||||
|
loop_data JSON 中间嵌入了完整的 MQTT PUBLISH 二进制帧 (event_report 的封包)。
|
||||||
|
|
||||||
|
**根因**: `iot_mqtt_publish_sensor()` 的 `static char data_json[1024]` 和
|
||||||
|
`static char payload[1400]` 合计 2424B BSS, 叠加同文件其他大缓冲 (~9KB total),
|
||||||
|
在 CH32V208 48KB RAM 中可能导致链接器将 `data_json`/`payload` 与 `mqttBuf[1024]`
|
||||||
|
分配到重叠地址。
|
||||||
|
|
||||||
|
**污染路径**:
|
||||||
|
1. `iot_evt_process()` → `mqtt_publish()` → `MQTTSerialize_publish(mqttBuf,...)` 写入 MQTT 二进制到 mqttBuf
|
||||||
|
2. 因 BSS 重叠, `data_json` 也被写入相同内容
|
||||||
|
3. `snprintf(data_json, ...)` 覆写前 ~427B 为通道 JSON, 尾部残留 MQTT 二进制
|
||||||
|
4. `snprintf(payload, ..., "%s", data_json)` → `%s` 将残留二进制也拷进 payload
|
||||||
|
5. `mqtt_publish(topic, payload, 0)` → 发出污染后的 payload
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
|
||||||
|
| 改动 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 消灭 `data_json[1024]` | 直接在 `payload[1400]` 构建完整 JSON, 省 1024B BSS |
|
||||||
|
| 消除 `%s` 拷贝 | 不再从中间缓冲格式化到 payload, 杜绝尾部二进制残留路径 |
|
||||||
|
| `coil_count` 硬限 | `if (coil_n > 4) coil_n = 4` — 防 0xC0 坏帧致 snprintf 循环溢出 |
|
||||||
|
| JSON 构建顺序调整 | 先写包装头 `{"msg_id":...,"data":{"channels":[`, 再追加通道, 最后 `]}}` |
|
||||||
|
|
||||||
|
**BSS 节省**: 1024 bytes
|
||||||
|
**协议兼容**: JSON 输出格式不变 (`{"msg_id":N,"cmd":"loop_data","ts":T,"data":{"channels":[...]}}`)
|
||||||
|
|
||||||
## 修订记录
|
## 修订记录
|
||||||
|
|
||||||
| 版本 | 时间 | 说明 |
|
| 版本 | 时间 | 说明 |
|
||||||
|
| V3.3 | 2026-07-23 | loop_data: 消灭 data_json[1024] BSS 缓冲 + coil_count 硬限, 防 mqttBuf 重叠致 _raw 异常 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| V3.2 | 2026-07-10 | 双主题发布统一 + initialize 数据格式对齐 V1.03 + mqtt_publish packet_id=0 断连修复 |
|
| V3.2 | 2026-07-10 | 双主题发布统一 + initialize 数据格式对齐 V1.03 + mqtt_publish packet_id=0 断连修复 |
|
||||||
| V3.1 | 2026-07-09 | V1.03: 订阅后发 initialize 上线消息; iot_mqtt_srv 订阅改双主题 |
|
| V3.1 | 2026-07-09 | V1.03: 订阅后发 initialize 上线消息; iot_mqtt_srv 订阅改双主题 |
|
||||||
|
|||||||
Reference in New Issue
Block a user