Added
- Optional password for the frame's HTTP API (HTTP Basic; off by default; Settings → General → Advanced network settings). Wrong guesses are rate-limited per client (5 free, then 30 s doubling to 15 min). A server-pushed config can't set or clear it. The photoframe server (≥ v1.17.0), Home Assistant integration (≥ v2.11.0) and mobile app (≥ v1.6.0) must be given the same password — older versions stop syncing once it's on. Basic over plain HTTP is replayable on a shared network; a forgotten password requires a USB reflash. (#130)
- M5Stack M5Paper v1.0/v1.1 (4.7" 960×540 16-level grayscale, IT8951) — the first original-ESP32 board. Flash
photoframe-firmware-m5stack_m5paper_v11-merged.binat 0x0 with--chip esp32, or use the web flasher. Known limits: USB power isn't detectable (disable deep sleep for always-on use), the Clear button only works while awake, the touchscreen is unused. Thanks @YasithLokuge. (#124) - Time zone picker by IANA name (464 zones, tzdata 2026d); the POSIX rule is kept verbatim so schedules follow DST, and an advanced field accepts any rule. (#128)
- Crash reports. Core dumps are captured in every build and summarised at the next boot into a
last_crashrecord (reason, task, PC, backtrace, firmware, ELF hash): Maintenance → Last Crash with Copy Report / Clear,last_crashin GET /api/system-info, POST /api/crash/clear, per-board.elfsymbol files attached to each release, decoding steps in docs/DEV.md. Frames updated over the air keep their old partition table and start recording dumps after their next USB flash. (idea from PR #132 by @EinMaulwurf) - Config export includes
system_info, andphotoframe-process --device-config <export.json>converts with a frame's exact settings without the frame on the network. (#141) - The debug log records stack headroom and awake time at every sleep.
Changed
- Weak-WiFi battery drain (#121): a WiFi connect is bounded to 30 s; image fetches use a 30 s socket timeout and retry only within a 20 s budget, never after a 4xx; after consecutive failed unattended wakes the frame backs off from 5 min to 6 h by skipping scheduled slots (any success, or any button/power-on wake, clears it). An hourly URL frame whose server is unreachable now wakes at most every 6 h. (adapted from PR #134 by @EinMaulwurf)
- A failed URL fetch keeps the picture on the panel instead of rotating to a random local image;
/api/rotateanswers 502 with the reason; a ROTATE press with no network goes straight back to sleep. (PR #134, @EinMaulwurf) - WiFi credentials are cleared only when the access point rejects the password six times in a row. A router that is merely off or rebooting no longer sends the frame back to provisioning, and USB-powered frames rejoin by themselves after a router reboot.
X-Battery-Percentageis omitted rather than sent as -1 when the level is unknown. (#123)- Web UI assets are embedded gzipped (app image ~800 KB smaller); internal-flash boards use the last 896 KB of flash after a USB flash. (#112)
- Build:
--debugandsdkconfig.defaults.debugare gone (core dumps are always on);boards.jsongainstarget;build.pyruns on Windows (#127, @psykokwak-com). - The gallery's delete button is discoverable, keyboard-reachable and always visible on touch. (#126, @psykokwak-com)
Fixed
- Waking any ESP32-S3 frame with its CLEAR button panicked (double SPI bus init) and rebooted instead of clearing the screen.
- reTerminal E1002/E1003/E1004: the SD card could go missing after a panic or software reset; its rail is now power-cycled every boot. M5Paper and PhotoPainter retry an unanswered card once.
- reTerminal E1004: half the panel skipping an update — the SPI bus is held across the ed2208 command path (#136, @jeremyrode); the same hold was added to the IT8951 primitives (E1003, EE03, M5Paper).
- reTerminal E1003: the IT8951 bias-enable pad is latched through deep sleep (suspected sleep drain, #121).
- PhotoPainter reported -1% battery while charging. (#120)
- The image ETag is stored only once the picture is displayed — a failed decode no longer leaves the frame stuck on a 304. (PR #134, @EinMaulwurf)
- Scheduled wakes in the repeated hour after a DST fall-back landed on the wrong instant.
- Always-on rotation scheduled the next refresh ~30 s early after a slow panel update. (#138, @EinMaulwurf)
- The debug log lost its tail on SD boards (it is flushed before the card is powered down).
- Timezone: the settings UI no longer collapses a DST rule to a UTC offset (#128); empty, over-long or non-printable rules are rejected.
- Uploads dither with the same calibrated palette the preview shows.
- Boot logs the core dump's panic reason and keeps a dump it can't summarise for
idf.py coredump-info. (@EinMaulwurf) - RTC boards (reTerminal E100x, XIAO EE03, M5Paper) restored a clock one hour ahead on every cold boot during DST until the next SNTP sync. (#143, @t3ste)
- A config PATCH applies every valid field and reports the rejected ones, instead of stopping at the first error with earlier fields already applied. (#143, @t3ste)
- The settings endpoints bound their request bodies and read them completely; a split body no longer fails as "Invalid JSON". (#143, @t3ste)
- The enabled-album list is guarded against a settings change racing a rotation. (#143, @t3ste)
- OTA: the release metadata is read when GitHub answers chunked, release URLs must be https, and the periodic check can no longer start a second check task. (#143, @t3ste)
- A JPEG carrying two frame headers could overflow the decode buffer (the decoder follows the last header, the size check followed the first); the decoded size is now taken from the frame tjpgd will use and bounded before allocation. (#143, reported by @t3ste)
Installation
Web Flasher (Easiest)
Flash directly from your browser (Chrome/Edge/Opera required):
https://aitjcize.github.io/esp32-photoframe/#flash
Manually
Choose the appropriate merged binary for your board:
photoframe-firmware-waveshare_photopainter_73-merged.bin: For Waveshare 7.3" 7-color e-paperphotoframe-firmware-seeedstudio_xiao_ee02-merged.bin: For Seeed XIAO EE02photoframe-firmware-seeedstudio_reterminal_e1002-merged.bin: For Seeed reTerminal E1002photoframe-firmware-seeedstudio_xiao_ee04-merged.bin: For Seeed XIAO EE04photoframe-firmware-seeedstudio_reterminal_e1004-merged.bin: For Seeed reTerminal E1004photoframe-firmware-seeedstudio_reterminal_e1003-merged.bin: For Seeed reTerminal E1003 (10.3" grayscale)photoframe-firmware-seeedstudio_xiao_ee03-merged.bin: For Seeed XIAO EE03 (10.3" grayscale)photoframe-firmware-m5stack_m5paper_v11-merged.bin: For M5Stack M5Paper v1.0/v1.1 (4.7" grayscale)
# ESP32-S3 boards (everything except the M5Paper)
esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 921600 write_flash 0x0 photoframe-firmware-[board]-merged.bin
# M5Stack M5Paper (ESP32)
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 write_flash 0x0 photoframe-firmware-m5stack_m5paper_v11-merged.binThe [board]-[version].elf files are debug symbols for decoding crash reports; they are not needed to install.