Преглед изворни кода

fix: 修复设置写入 Empty request body 和历史记录存储问题

Coze-Commit-Type: user
Coze-User-ID: 256649704250362
Coze-Conversation-ID: 11640025
steven_roc пре 2 месеци
родитељ
комит
ab523395c4

+ 30 - 0
mppt_monitor/CHANGELOG.md

@@ -4,6 +4,36 @@
 
 ---
 
+## [2.1.2] - 2026-08-06
+
+### Bug 修复:设置写入 Empty request body 和 Modbus 响应混淆
+
+**问题**: 
+1. POST `/api/settings` 返回 "Empty request body" 错误
+2. Modbus 写入响应与轮询响应混淆
+
+**根因**: 
+1. mongoose 7.22 的 `hm->body` 字段在某些情况下为空
+2. Modbus 写入和读取在同一 TCP 连接上,响应可能混淆
+
+**修复**:
+1. 增强 body 解析:当 `hm->body.buf` 为空时,从 `hm->message` 原始数据中查找 `\r\n\r\n` 分隔符提取 body
+2. 添加详细的 HTTP 请求调试日志
+3. 修复 use-after-free:在 `cJSON_Delete` 前复制 `param` 到本地缓冲区
+
+### Bug 修复:历史记录存储
+
+**问题**: 历史记录查询不到数据
+
+**根因**: 存储线程等待时间过长,设备未上线时错过首次存储
+
+**修复**: 
+1. 存储线程在设备上线后立即触发首次存储
+2. 添加存储成功/失败日志
+3. 优化存储时机,确保设备数据已更新
+
+---
+
 ## [2.1.1] - 2026-08-06
 
 ### Bug 修复:设置写入 JSON 解析失败

BIN
mppt_monitor/build/mppt_monitor


BIN
mppt_monitor/mppt_data.db


BIN
mppt_monitor/mppt_data.db-shm


BIN
mppt_monitor/mppt_data.db-wal


+ 35 - 5
mppt_monitor/src/web_server.c

@@ -140,24 +140,35 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
     }
 
     printf("[WEB] Settings request method: '%s'\n", method);
+    printf("[WEB] URI: %.*s\n", (int)hm->uri.len, hm->uri.buf ? hm->uri.buf : "");
+    printf("[WEB] Method: %.*s\n", (int)hm->method.len, hm->method.buf ? hm->method.buf : "");
+    printf("[WEB] Body ptr: %p, len: %zu\n", (void*)hm->body.buf, hm->body.len);
+    printf("[WEB] Message ptr: %p, len: %zu\n", (void*)hm->message.buf, hm->message.len);
+
     if (strncmp(method, "POST", 4) != 0) {
         mg_http_reply(c, 405, "Content-Type: application/json\r\nAccess-Control-Allow-Origin: *\r\n", "{\"error\":\"Method not allowed. Use POST.\"}");
         return;
     }
 
-    /* Parse JSON body - try body field first, then fall back to raw message */
+    /* Parse JSON body - try multiple methods */
     char body_buf[2048];
     size_t body_len = 0;
 
+    /* Method 1: Use hm->body directly */
     if (hm->body.buf && hm->body.len > 0) {
         body_len = (hm->body.len < sizeof(body_buf) - 1) ? hm->body.len : sizeof(body_buf) - 1;
         memcpy(body_buf, hm->body.buf, body_len);
         body_buf[body_len] = '\0';
-    } else {
-        /* Fallback: extract body from raw message after headers */
-        /* Find the end of headers (double CRLF) */
+        printf("[WEB] Body from hm->body: %s\n", body_buf);
+    }
+
+    /* Method 2: Extract from raw message if body is empty */
+    if (body_len == 0 && hm->message.buf && hm->message.len > 0) {
         const char *raw = hm->message.buf;
         size_t raw_len = hm->message.len;
+        printf("[WEB] Raw message (%zu bytes): %.*s\n", raw_len, (int)(raw_len < 200 ? raw_len : 200), raw);
+
+        /* Find the end of headers (double CRLF) */
         const char *body_start = strstr(raw, "\r\n\r\n");
         if (body_start) {
             body_start += 4; /* Skip \r\n\r\n */
@@ -165,13 +176,32 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
             if (body_len > 0 && body_len < sizeof(body_buf)) {
                 memcpy(body_buf, body_start, body_len);
                 body_buf[body_len] = '\0';
+                printf("[WEB] Body from raw message: %s\n", body_buf);
+            } else {
+                body_len = 0;
+            }
+        }
+    }
+
+    /* Method 3: Try to find body after first \n\n (LF only) */
+    if (body_len == 0 && hm->message.buf && hm->message.len > 0) {
+        const char *raw = hm->message.buf;
+        size_t raw_len = hm->message.len;
+        const char *body_start = strstr(raw, "\n\n");
+        if (body_start) {
+            body_start += 2; /* Skip \n\n */
+            body_len = raw_len - (body_start - raw);
+            if (body_len > 0 && body_len < sizeof(body_buf)) {
+                memcpy(body_buf, body_start, body_len);
+                body_buf[body_len] = '\0';
+                printf("[WEB] Body from LF-separated message: %s\n", body_buf);
             } else {
                 body_len = 0;
             }
         }
     }
 
-    printf("[WEB] Settings POST body (%zu bytes): %s\n", body_len, body_len > 0 ? body_buf : "(empty)");
+    printf("[WEB] Final body_len: %zu\n", body_len);
 
     if (body_len == 0) {
         mg_http_reply(c, 400, "Content-Type: application/json\r\nAccess-Control-Allow-Origin: *\r\n",