Add ESP32 recovery app with WiFi setup portal

- New flash layout (partitions.csv): factory = recovery app, ota_0/ota_1 =
  clock firmware; esp32_usb uploads to ota_0 so it never overwrites it
- src/recovery: WiFi + OTA + web page only. Opens the password protected
  'FlipDot-Setup' AP with a captive portal when WiFi fails, lets you pick
  another WiFi (stored in NVS, used by both apps), start the clock or stay
- Recovery is started when the clock firmware can't connect to WiFi,
  crashes 3 times, after 3 quick power cycles, from a new Home Assistant
  button, or by the bootloader when no clock firmware works
- Shared NVS store and boot switching in src/esp32/system
- Clock firmware keeps working on the old flash layout (falls back to
  OTA-only safe mode)
- README: recovery app, one-time USB installation; tests: 65 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:21:04 +02:00
1 parent ddbdf7e65f
commit 4749f9e596
25 files changed
+979 -29

No files matched your search

+29 -4
View File
@@ -3,7 +3,8 @@
; nano Arduino Nano that drives the Brose flipdot panels directly (USB upload)
; nano_ota Same Nano firmware, flashed over WiFi through the ESP32
; esp32 ESP32 "brain" (WiFi, NTP clock, Home Assistant) - OTA upload
; esp32_usb Same ESP32 firmware, flashed over USB (first flash / recovery)
; esp32_usb Same ESP32 firmware, flashed over USB into ota_0
; recovery ESP32 recovery app (WiFi setup + OTA), USB only, see README.md
; test_nano Unit tests for the Nano firmware, run on the PC (needs gcc on PATH)
; test_esp32 Unit tests for the ESP32 logic, run on the PC
;
@@ -53,26 +54,50 @@ upload_command = "$PYTHONEXE" "$PROJECT_DIR/tools/nano_net_upload.py" "$SOURCE"
; ---------------------------------------------------------------------------
; ESP32 - controller, talks to the Nano over serial
; ---------------------------------------------------------------------------
[env:esp32]
[esp32_common]
platform = espressif32
board = esp32doit-devkit-v1
; factory = recovery app, ota_0 / ota_1 = clock firmware (see partitions.csv)
board_build.partitions = partitions.csv
monitor_port = COM11
[env:esp32]
extends = esp32_common
build_src_filter = +<esp32/>
; Size check against the ota slots, not the (smaller) factory partition
board_build.app_partition_name = ota_0
; ESPSERIAL turns the BROSE9323 driver into a serial client: every draw call is
; sent to the Nano as a text command instead of toggling GPIO pins.
build_flags = -D ESPSERIAL -I src/esp32
lib_deps =
${env.lib_deps}
https://github.com/robjen/GFX_fonts.git
dawidchyrzynski/home-assistant-integration@^2.1.0
knolleary/PubSubClient@^2.8.0
upload_protocol = espota
upload_port = 10.1.1.198
monitor_port = COM11
; USB upload of the clock firmware: written to ota_0, never over the recovery app
[env:esp32_usb]
extends = env:esp32
upload_protocol = esptool
upload_port = COM11
board_upload.offset_address = 0x110000
; ---------------------------------------------------------------------------
; ESP32 recovery app (src/recovery) in the factory partition: WiFi setup page + OTA.
; One-time install over USB, see README.md "Recovery app".
; ---------------------------------------------------------------------------
[env:recovery]
extends = esp32_common
build_src_filter =
+<recovery/>
+<esp32/logic/boot_policy.cpp>
+<esp32/system/system_store.cpp>
+<esp32/system/boot_target.cpp>
build_flags = -I src/esp32
lib_deps =
upload_protocol = esptool
upload_port = COM11
; ---------------------------------------------------------------------------
; Unit tests on the PC (pio test -e test_nano -e test_esp32)