diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index d0b4d3c8..234d471e 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -1331,7 +1331,7 @@ void MyMesh::begin(FILESYSTEM *fs, ArchiveStorage* archive) { next_archive_neighbours_flush_ms = millis() + kArchiveNeighboursFlushIntervalMs; } if (web.isWebStatsEnabled()) { - recordStatsEvent(HISTORY_EVENT_BOOT); + recordStatsEvent(HISTORY_EVENT_BOOT, board.getResetReason()); if (_archive != nullptr) { recordStatsEvent(_archive->isMounted() ? HISTORY_EVENT_ARCHIVE_MOUNTED : HISTORY_EVENT_ARCHIVE_UNAVAILABLE); } diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index e7b8a5a0..84e8e06c 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -898,10 +898,13 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep strcpy(reply, "ERROR: Power management not supported"); #endif } else if (memcmp(config, "pwrmgt.bootreason", 17) == 0) { -#ifdef NRF52_POWER_MANAGEMENT +#if defined(NRF52_POWER_MANAGEMENT) sprintf(reply, "> Reset: %s; Shutdown: %s", _board->getResetReasonString(_board->getResetReason()), _board->getShutdownReasonString(_board->getShutdownReason())); +#elif defined(ESP_PLATFORM) + sprintf(reply, "> Reset: %s", + _board->getResetReasonString(_board->getResetReason())); #else strcpy(reply, "ERROR: Power management not supported"); #endif diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index ba906f55..f7643d6f 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -84,6 +84,26 @@ public: uint8_t getStartupReason() const override { return startup_reason; } + uint32_t getResetReason() const override { + return (uint32_t)esp_reset_reason(); + } + + const char* getResetReasonString(uint32_t reason) override { + switch ((esp_reset_reason_t)reason) { + case ESP_RST_POWERON: return "Power On"; + case ESP_RST_EXT: return "External Reset"; + case ESP_RST_SW: return "Software Reset"; + case ESP_RST_PANIC: return "Panic/Exception"; + case ESP_RST_INT_WDT: return "Interrupt Watchdog"; + case ESP_RST_TASK_WDT: return "Task Watchdog"; + case ESP_RST_WDT: return "Watchdog"; + case ESP_RST_DEEPSLEEP: return "Deep Sleep Wake"; + case ESP_RST_BROWNOUT: return "Brownout"; + case ESP_RST_SDIO: return "SDIO Reset"; + default: return "Unknown"; + } + } + #if defined(P_LORA_TX_LED) void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on diff --git a/src/helpers/web/WebPanelServer.cpp b/src/helpers/web/WebPanelServer.cpp index 961c8206..b0b5085d 100644 --- a/src/helpers/web/WebPanelServer.cpp +++ b/src/helpers/web/WebPanelServer.cpp @@ -1627,6 +1627,14 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( ${renderMetricList(metrics, "metric-grid-4")} `; } + function bootReasonLabel(value) { + const ESP_RESET_REASONS = { + 1: "power on", 2: "external reset", 3: "software reset", + 4: "panic/exception", 5: "interrupt watchdog", 6: "task watchdog", + 7: "watchdog", 8: "deep sleep wake", 9: "brownout", 10: "SDIO reset" + }; + return ESP_RESET_REASONS[value] || ("reason " + value); + } function renderEventsSection(events) { if (!Array.isArray(events) || !events.length) { return `
@@ -1634,10 +1642,15 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
No recent events
`; } - const rows = events.map((event) => ` - ${escapeHtml(event.type || "event")} - ${escapeHtml(formatDuration(event.t || 0))} - `).join(""); + const rows = events.map((event) => { + const label = event.type === "boot" && event.value != null + ? `boot (${bootReasonLabel(event.value)})` + : (event.type || "event"); + return ` + ${escapeHtml(label)} + ${escapeHtml(formatDuration(event.t || 0))} + `; + }).join(""); return `

Events