Keep ESP32 OTA reachable whatever the firmware does

- Rollback: override verifyRollbackLater() so a new OTA image stays
  pending until it ran 60 s with WiFi; any earlier restart rolls back
  (the Arduino core marked every image valid at boot before)
- Task watchdog (30 s) on loop(), paused during OTA uploads
- Crash counter in RTC memory: OTA-only window after a crash, 10 min
  safe mode (WiFi + OTA only) after 3 crashes in a row
- Restart when WiFi stays down for 10 min
- Home Assistant sensor 'FlipDot Display Firmware' with version/state
- logic/boot_policy with tests (60 tests total)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-13 01:05:06 +02:00
1 parent 683a47c055
commit ddbdf7e65f
14 files changed
+517 -42

No files matched your search

+23 -2
View File
@@ -13,6 +13,7 @@
#include "nano_link/nano_link.h"
#include "net/home_assistant.h"
#include "net/wifi_ota.h"
#include "system/firmware_guard.h"
NanoLink nano(Serial2, NANO_RX_PIN, NANO_TX_PIN, RELAY_PIN, NANO_RESET_PIN);
BROSE9323 display(DISPLAY_WIDTH, DISPLAY_HEIGHT, PANEL_WIDTH);
@@ -30,12 +31,25 @@ void setup()
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
nano.begin();
nano.begin(); // display off until the main code runs
// Decided first, before anything that could crash
BootMode boot_mode = firmwareGuardBegin();
wifiBegin();
otaBegin();
if (boot_mode == BootMode::SafeMode)
{
// Crashed too often: only WiFi and OTA, then try the main code once more
otaOnlyMode(SAFE_MODE_TIME, LED_PIN);
firmwareGuardSafeModeEnded();
ESP.restart();
}
if (boot_mode == BootMode::PanicWindow)
otaOnlyMode(OTA_PANIC_WINDOW, LED_PIN);
flashBridge.begin();
otaPanicWindow(LED_PIN);
nano.on();
display.begin(&nano.stream());
@@ -45,11 +59,18 @@ void setup()
configTzTime(TIMEZONE, NTP_SERVER);
homeAssistantBegin(controller);
firmwareGuardStartWatchdog();
}
void loop()
{
// OTA and the firmware guard come first, so they keep working whatever happens below
otaLoop();
firmwareGuardLoop(wifiConnected());
wifiWatchdog();
homeAssistantSetFirmwareStatus(firmwareGuardStatus());
homeAssistantLoop();
// While the Nano is being flashed, nothing else may talk to it