From 2bf49c14ac1a51d22f31b8105652a82526a705ab Mon Sep 17 00:00:00 2001 From: Vitali Date: Tue, 21 Jul 2026 08:48:25 +0700 Subject: [PATCH] revert: restore pre-4b59b89 web server (drop chunked API + low-memory auto-reboot) The chunked API handlers and the maxblock<6000 auto-restart from 4b59b89 broke the web UI on-device; restore the working String-based handlers and plain loop while keeping the scrollable forecast log. Co-Authored-By: Claude Opus 4.8 --- WeatherPredictor/WeatherPredictor.ino | 9 ------ WeatherPredictor/web_server.cpp | 41 +++++++++++++-------------- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/WeatherPredictor/WeatherPredictor.ino b/WeatherPredictor/WeatherPredictor.ino index b24e6f3..72715c6 100644 --- a/WeatherPredictor/WeatherPredictor.ino +++ b/WeatherPredictor/WeatherPredictor.ino @@ -88,15 +88,6 @@ void loop() { tSample = now; sampleNow(); displayRender(g_state); - Serial.printf("heap=%u maxblock=%u\n", ESP.getFreeHeap(), ESP.getMaxFreeBlockSize()); - // Safety net: if the largest contiguous block gets too small, the TCP stack - // can no longer send responses. Persist and reboot to defragment. - if (ESP.getMaxFreeBlockSize() < 6000) { - Serial.println(F("Low memory -> saving history and restarting")); - historySave(); - delay(50); - ESP.restart(); - } } if (now - tHistory >= HISTORY_INTERVAL_MS) { diff --git a/WeatherPredictor/web_server.cpp b/WeatherPredictor/web_server.cpp index f583948..f5447d8 100644 --- a/WeatherPredictor/web_server.cpp +++ b/WeatherPredictor/web_server.cpp @@ -27,44 +27,41 @@ static void handleCurrent() { doc["haveTrend"] = g_state.haveTrend; doc["forecast"] = g_state.haveTrend ? g_state.forecast.text : "Collecting data..."; doc["category"] = g_state.haveTrend ? categoryShort(g_state.forecast.category) : "..."; - doc["heap"] = ESP.getFreeHeap(); // for monitoring memory health String out; serializeJson(doc, out); server.send(200, "application/json", out); } -// Streamed (chunked) so we never build a large String/JsonDocument on the heap. static void handleHistory() { - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - server.send(200, "application/json", ""); - server.sendContent("["); - char buf[80]; + JsonDocument doc; + JsonArray arr = doc.to(); int n = historyCount(); for (int i = 0; i < n; i++) { Sample s = historyGet(i); - snprintf(buf, sizeof(buf), "%s{\"t\":%lu,\"msl\":%.1f,\"temp\":%.1f}", - i ? "," : "", (unsigned long)s.epoch, s.mslHpa, s.tempC); - server.sendContent(buf); + JsonObject o = arr.add(); + o["t"] = s.epoch; + o["msl"] = s.mslHpa; + o["temp"] = s.tempC; } - server.sendContent("]"); + String out; + serializeJson(doc, out); + server.send(200, "application/json", out); } -// Streamed (chunked). Forecast phrases contain no quotes/backslashes, so they -// are safe to embed directly in JSON. static void handleForecasts() { - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - server.send(200, "application/json", ""); - server.sendContent("["); - char buf[128]; + JsonDocument doc; + JsonArray arr = doc.to(); int n = flogCount(); - for (int i = n - 1, first = 1; i >= 0; i--, first = 0) { // newest first + for (int i = n - 1; i >= 0; i--) { // newest first FcastEntry e = flogGet(i); - snprintf(buf, sizeof(buf), "%s{\"t\":%lu,\"cat\":\"%s\",\"text\":\"%s\"}", - first ? "" : ",", (unsigned long)e.epoch, - categoryShort((WxCategory)e.cat), forecastTextForLetter(e.letter)); - server.sendContent(buf); + JsonObject o = arr.add(); + o["t"] = e.epoch; + o["cat"] = categoryShort((WxCategory)e.cat); + o["text"] = forecastTextForLetter(e.letter); } - server.sendContent("]"); + String out; + serializeJson(doc, out); + server.send(200, "application/json", out); } static void handleGetSettings() {