ESP32: add reset reason to boot event, CLI, and web panel
Implement getResetReason() and getResetReasonString() for ESP32Board, covering all esp_reset_reason_t values: power-on, external reset, software reset, panic/exception, interrupt watchdog, task watchdog, generic watchdog, deep sleep wake, brownout, and SDIO reset. Extend the pwrmgt.bootreason CLI command to support ESP32 alongside NRF52. On ESP32 only the reset reason is reported (no shutdown reason). Pass the reset reason as the value field when recording the HISTORY_EVENT_BOOT stats event so the reason is stored in the in-memory ring buffer and persisted to the archive events log. Add bootReasonLabel() to the web panel and update renderEventsSection() to annotate boot events with the human-readable reset reason string, e.g. "boot (panic/exception)", when a non-null value is present.
Este commit está contenido en:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1627,6 +1627,14 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
${renderMetricList(metrics, "metric-grid-4")}
|
||||
</section>`;
|
||||
}
|
||||
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 `<section class="hud-card">
|
||||
@@ -1634,10 +1642,15 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
<div class="events-empty">No recent events</div>
|
||||
</section>`;
|
||||
}
|
||||
const rows = events.map((event) => `<tr>
|
||||
<td>${escapeHtml(event.type || "event")}</td>
|
||||
<td>${escapeHtml(formatDuration(event.t || 0))}</td>
|
||||
</tr>`).join("");
|
||||
const rows = events.map((event) => {
|
||||
const label = event.type === "boot" && event.value != null
|
||||
? `boot (${bootReasonLabel(event.value)})`
|
||||
: (event.type || "event");
|
||||
return `<tr>
|
||||
<td>${escapeHtml(label)}</td>
|
||||
<td>${escapeHtml(formatDuration(event.t || 0))}</td>
|
||||
</tr>`;
|
||||
}).join("");
|
||||
return `<section class="hud-card">
|
||||
<h3>Events</h3>
|
||||
<div class="events-table-wrap">
|
||||
|
||||
Referencia en una nueva incidencia
Block a user