Public Access
Add a web UI to the clock firmware
- Web UI on port 80: live view of the display, choose the page (clock or a bitmap), bitmaps (list, show, live, edit, delete), draw / image upload with conversion in the browser, live mode, settings, Home Assistant - Live view from a shadow buffer in the BROSE9323 driver (shownPixel) - Settings in NVS with the original behaviour as defaults: schedule times, quarter hours, yawning Pikachu, No WiFi screen, flip time, status LED, Home Assistant broker (restart on change) - Bitmaps on LittleFS; new 320 KB partition, ota slots now 1.31 MB - DisplayController: pages, live mode, settings; app.cpp holds the objects - README for the recovery app; docs for the web UI - Tests: settings, time parsing, bitmap format and names, schedule with settings, pages and live mode (95 total) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c9e0800e36
commit
2b1ac12ed7
34 files changed
+1989
-117
No files matched your search
@@ -0,0 +1,95 @@
|
||||
# ESP32: recovery app
|
||||
|
||||
PlatformIO environment: `recovery` (USB only)
|
||||
|
||||
A small second app on the ESP32 that only does WiFi, a setup web page and OTA. It lives in
|
||||
the `factory` partition (see [partitions.csv](../../partitions.csv)), so OTA updates of
|
||||
the clock firmware never change it. Its job: the ESP32 stays reachable, whatever happens
|
||||
to the clock firmware, so it never needs USB again.
|
||||
|
||||
Installing it and using it as a user is described in the
|
||||
[main README](../../README.md#recovery-app). This file is about how it works.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| `main.cpp` | `setup()` / `loop()`: WiFi (station + setup access point), OTA, status on the display, when to start the clock firmware again |
|
||||
| `web_portal.*` | Setup page on port 80 and the captive portal (DNS) of the setup WiFi |
|
||||
| `recovery_state.h` | State shared by `main.cpp` and the web portal |
|
||||
|
||||
It also uses code from the clock firmware (see `build_src_filter` of the `recovery`
|
||||
environment in `platformio.ini`):
|
||||
|
||||
| From `src/esp32/` | Used for |
|
||||
|-------------------|----------|
|
||||
| `logic/boot_policy.*` | Recovery reasons, when to start the clock firmware again (tested in `test/test_esp32`) |
|
||||
| `system/system_store.*` | NVS: WiFi credentials, recovery reason, clock firmware slot and version |
|
||||
| `system/boot_target.*` | Starting the clock firmware in `ota_0` / `ota_1` |
|
||||
| `nano_link/nano_link.*` | Relay and serial link to the Nano, for the status messages |
|
||||
| `display/status_screen.*`, `display/text.*` | Two-line status messages on the display |
|
||||
|
||||
## How it starts
|
||||
|
||||
The clock firmware calls `rebootToRecovery(reason)`: it stores the reason in NVS, selects
|
||||
the `factory` partition (this erases otadata) and restarts. The bootloader also falls back
|
||||
to the recovery app by itself when neither `ota_0` nor `ota_1` holds a working firmware.
|
||||
|
||||
| Reason | Set by | Back to the clock firmware |
|
||||
|--------|--------|----------------------------|
|
||||
| `Wifi` | clock firmware: no WiFi at boot (30 s) or for 10 min | when WiFi works, after at least 1 min |
|
||||
| `Crash` | clock firmware: 3 crashes in a row | after 10 min |
|
||||
| `Manual` | Home Assistant button, web UI "Recovery app" | after 10 min |
|
||||
| `PowerCycle` | clock firmware: 3 quick power cycles | after 10 min |
|
||||
| `None` | bootloader fallback, or a fresh install | after 10 min, if a clock firmware exists |
|
||||
|
||||
"Stay in recovery" on the setup page turns the automatic start off; "Start the clock
|
||||
firmware now" starts it right away. The decision is `recoveryShouldStartMain()` in
|
||||
`logic/boot_policy.cpp`.
|
||||
|
||||
`startMainFirmware()` selects the slot that ran last (stored in NVS by the clock firmware),
|
||||
or the other one. `esp_ota_set_boot_partition()` checks the whole image first, so a
|
||||
broken slot is skipped. The clock firmware then starts as `PENDING_VERIFY` and must pass
|
||||
the 60 s check (see the [ESP32 README](../esp32/README.md#keeping-ota-alive)), or the
|
||||
bootloader comes back here.
|
||||
|
||||
## WiFi
|
||||
|
||||
- **Station:** the WiFi from NVS (set on the setup page), or `WIFI_SSID` / `WIFI_PASSWORD`
|
||||
from `src/esp32/secrets.h`. Retried every 30 s; auto reconnect is off so the retries
|
||||
are under control.
|
||||
- **Setup access point** `FlipDot-Setup` (password `SETUP_AP_PASSWORD`): opened when the
|
||||
station hasn't connected for 20 s. While a phone is connected to it, the station
|
||||
retries pause, because they make the access point unstable. Closed 2 minutes after
|
||||
the station works again (if nobody is connected).
|
||||
- **Captive portal:** while the access point is open, a DNS server answers every name
|
||||
with 192.168.4.1, and unknown pages redirect to the setup page, so phones open it by
|
||||
themselves.
|
||||
|
||||
## Setup page
|
||||
|
||||
`GET /` shows the reason, WiFi state, the clock firmware in both slots and when it starts
|
||||
again. `POST /wifi` stores new WiFi credentials and connects, `POST /start` starts the clock
|
||||
firmware, `POST /stay` turns the automatic start off. There is no login: on your own
|
||||
WiFi it has the same trust as OTA, on the setup WiFi the WiFi password protects it.
|
||||
|
||||
## Display
|
||||
|
||||
`StatusScreen` shows `Recovery` + reason, `WiFi setup:` + the access point name, or
|
||||
`Recovery` + the IP address, whichever applies. After each message the display is switched
|
||||
off again; the dots keep the image. New messages at most every 30 s.
|
||||
|
||||
## OTA
|
||||
|
||||
ArduinoOTA works on both networks, like in the clock firmware:
|
||||
`pio run -e esp32 -t upload` (add `--upload-port 192.168.4.1` on the setup WiFi). An upload
|
||||
from here always goes to `ota_0` (the first OTA slot after `factory`) and starts right after.
|
||||
|
||||
## Safety
|
||||
|
||||
- A task watchdog (60 s) restarts the app when `loop()` hangs. After that restart the
|
||||
bootloader starts the recovery app again (otadata still points to `factory`).
|
||||
- The watchdog is paused during an OTA upload.
|
||||
- Keep this app small and simple: it is the last line of defence, and changing it needs
|
||||
USB (`pio run -e recovery -t upload`). It must fit in the 1 MB `factory` partition
|
||||
(about 840 KB now).
|
||||
Reference in new issue
Block a user