Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8294d4aed | ||
|
|
4b59b8936b |
@@ -88,6 +88,15 @@ void loop() {
|
|||||||
tSample = now;
|
tSample = now;
|
||||||
sampleNow();
|
sampleNow();
|
||||||
displayRender(g_state);
|
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) {
|
if (now - tHistory >= HISTORY_INTERVAL_MS) {
|
||||||
|
|||||||
@@ -103,7 +103,11 @@ static const char INDEX_HTML[] PROGMEM = R"HTML(
|
|||||||
.cap{color:var(--muted); font-size:.74rem; letter-spacing:.06em}
|
.cap{color:var(--muted); font-size:.74rem; letter-spacing:.06em}
|
||||||
|
|
||||||
/* Forecast log */
|
/* Forecast log */
|
||||||
.log{list-style:none; margin:2px 0 0; padding:0}
|
.log{list-style:none; margin:2px 0 0; padding:0 8px 0 0; max-height:216px; overflow-y:auto;
|
||||||
|
scrollbar-width:thin; scrollbar-color:var(--line) transparent}
|
||||||
|
.log::-webkit-scrollbar{width:8px}
|
||||||
|
.log::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px}
|
||||||
|
.log::-webkit-scrollbar-track{background:transparent}
|
||||||
.log li{display:flex; align-items:center; gap:13px; padding:12px 0; border-top:1px solid var(--line)}
|
.log li{display:flex; align-items:center; gap:13px; padding:12px 0; border-top:1px solid var(--line)}
|
||||||
.log li:first-child{border-top:0}
|
.log li:first-child{border-top:0}
|
||||||
.log .dot{width:9px; height:9px; border-radius:50%; flex:0 0 auto}
|
.log .dot{width:9px; height:9px; border-radius:50%; flex:0 0 auto}
|
||||||
|
|||||||
@@ -27,41 +27,44 @@ static void handleCurrent() {
|
|||||||
doc["haveTrend"] = g_state.haveTrend;
|
doc["haveTrend"] = g_state.haveTrend;
|
||||||
doc["forecast"] = g_state.haveTrend ? g_state.forecast.text : "Collecting data...";
|
doc["forecast"] = g_state.haveTrend ? g_state.forecast.text : "Collecting data...";
|
||||||
doc["category"] = g_state.haveTrend ? categoryShort(g_state.forecast.category) : "...";
|
doc["category"] = g_state.haveTrend ? categoryShort(g_state.forecast.category) : "...";
|
||||||
|
doc["heap"] = ESP.getFreeHeap(); // for monitoring memory health
|
||||||
String out;
|
String out;
|
||||||
serializeJson(doc, out);
|
serializeJson(doc, out);
|
||||||
server.send(200, "application/json", out);
|
server.send(200, "application/json", out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Streamed (chunked) so we never build a large String/JsonDocument on the heap.
|
||||||
static void handleHistory() {
|
static void handleHistory() {
|
||||||
JsonDocument doc;
|
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||||
JsonArray arr = doc.to<JsonArray>();
|
server.send(200, "application/json", "");
|
||||||
|
server.sendContent("[");
|
||||||
|
char buf[80];
|
||||||
int n = historyCount();
|
int n = historyCount();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
Sample s = historyGet(i);
|
Sample s = historyGet(i);
|
||||||
JsonObject o = arr.add<JsonObject>();
|
snprintf(buf, sizeof(buf), "%s{\"t\":%lu,\"msl\":%.1f,\"temp\":%.1f}",
|
||||||
o["t"] = s.epoch;
|
i ? "," : "", (unsigned long)s.epoch, s.mslHpa, s.tempC);
|
||||||
o["msl"] = s.mslHpa;
|
server.sendContent(buf);
|
||||||
o["temp"] = s.tempC;
|
|
||||||
}
|
}
|
||||||
String out;
|
server.sendContent("]");
|
||||||
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() {
|
static void handleForecasts() {
|
||||||
JsonDocument doc;
|
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||||
JsonArray arr = doc.to<JsonArray>();
|
server.send(200, "application/json", "");
|
||||||
|
server.sendContent("[");
|
||||||
|
char buf[128];
|
||||||
int n = flogCount();
|
int n = flogCount();
|
||||||
for (int i = n - 1; i >= 0; i--) { // newest first
|
for (int i = n - 1, first = 1; i >= 0; i--, first = 0) { // newest first
|
||||||
FcastEntry e = flogGet(i);
|
FcastEntry e = flogGet(i);
|
||||||
JsonObject o = arr.add<JsonObject>();
|
snprintf(buf, sizeof(buf), "%s{\"t\":%lu,\"cat\":\"%s\",\"text\":\"%s\"}",
|
||||||
o["t"] = e.epoch;
|
first ? "" : ",", (unsigned long)e.epoch,
|
||||||
o["cat"] = categoryShort((WxCategory)e.cat);
|
categoryShort((WxCategory)e.cat), forecastTextForLetter(e.letter));
|
||||||
o["text"] = forecastTextForLetter(e.letter);
|
server.sendContent(buf);
|
||||||
}
|
}
|
||||||
String out;
|
server.sendContent("]");
|
||||||
serializeJson(doc, out);
|
|
||||||
server.send(200, "application/json", out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleGetSettings() {
|
static void handleGetSettings() {
|
||||||
|
|||||||
Reference in New Issue
Block a user