Add two physical buttons: factory-reset and next-photo
Build and push server image / build-and-push (push) Successful in 35s

Factory-reset (GPIO3, hold 10s): clears stored WiFi/server config and
restarts into provisioning -- the deliberate, USB-free replacement for
the earlier reverted RST-based auto-reprovisioning idea.

Next-photo (GPIO2, tap): wakes the device and forces the server to
advance immediately via a new POST /frame/advance, instead of waiting
for the refresh interval. Both buttons arm themselves as deep-sleep GPIO
wakeup sources so a press is noticed promptly even while asleep.

Also makes GET /frame/image side-effect-free: it now only advances once
refresh_interval_s has elapsed since the current photo was set (tracked
server-side), so a device reboot for any reason just redisplays the
current photo instead of silently skipping ahead. The server maintains a
small reorderable upcoming-photos queue, viewable and rearrangeable from
the web UI.
This commit is contained in:
2026-07-18 23:28:36 -04:00
parent 7013311249
commit d395cf3bb9
19 changed files with 668 additions and 47 deletions
+30 -3
View File
@@ -44,6 +44,9 @@ Under **ESPresso Frame Configuration**:
| `FRAME_FETCH_TIMEOUT_MS` | 15000 | Timeout for `GET /frame/image` |
| `FRAME_SLEEP_INTERVAL_S` | 3600 | **Fallback only** -- the refresh interval is normally set server-side; see below |
| `FRAME_RETRY_INTERVAL_S` | 300 | Sleep duration after a failed cycle, before retrying |
| `FRAME_RESET_BUTTON_GPIO` | 3 | Factory-reset button GPIO (-1 to disable). Must be 0-7 (ESP32-C6's deep-sleep-wakeup-capable pins) |
| `FRAME_RESET_BUTTON_HOLD_MS` | 10000 | How long the button must be held to trigger a reset |
| `FRAME_NEXT_BUTTON_GPIO` | 2 | Next-photo button GPIO (-1 to disable). Must be 0-7 |
Under **E-Paper Display (epd7in3e) Configuration**: SPI/GPIO pin
assignments and SPI clock speed -- see
@@ -77,11 +80,35 @@ Server" address (`host:port` of the [server](../server/) -- **not** your
Immich server). Saving reboots the device, which then connects to your
home network and starts its normal fetch/sleep cycle.
## Skipping to the next photo
Wire a momentary push button between GPIO2 and GND (internal pull-up,
active-low, same wiring style as the reset button). A press wakes the
device (if asleep) and tells the server to advance to the next photo
right away, regardless of the configured refresh interval -- no long hold
needed, unlike the factory-reset button, since advancing is easily
reversible by pressing again. See `FRAME_NEXT_BUTTON_GPIO` above to
change the pin or disable the feature.
Normal wakes and reboots never advance the photo on their own -- the
server decides when to advance based on its own clock (see
[`server/README.md`](../server/README.md)), so an unplanned reboot just
redisplays whatever was already showing instead of skipping ahead.
## Resetting to provisioning mode
There's currently no in-field way to force the device back into
provisioning (a future addition) -- reconfiguring means erasing its NVS
partition over USB:
Wire a momentary push button between GPIO3 and GND (internal pull-up,
active-low -- no external resistor needed). Hold it for 10 seconds (from
either power-on or while the device is deep-asleep -- GPIO3 is armed as a
wakeup source) and it clears the stored WiFi/server config and restarts
into provisioning. Releasing it early is a no-op; nothing happens until
the full hold duration elapses, so a brief accidental bump won't
reprovision the device. See `FRAME_RESET_BUTTON_GPIO`/
`FRAME_RESET_BUTTON_HOLD_MS` above to change the pin or hold duration, or
disable the feature.
Without the button wired up (or with `FRAME_RESET_BUTTON_GPIO` set to
`-1`), reconfiguring still works by erasing the NVS partition over USB:
```
python -m esptool --chip esp32c6 -p PORT erase-region 0x9000 0x6000