Slow mode (Home Assistant switch "FlipDot Display Slow mode", dropdown
"FlipDot Display Slow mode interval", web UI Settings) makes the display
change only every 1, 2, 5, 10, 15, 20, 30 or 60 minutes, on the clock, and
powers it off in between: less noise. Nothing else is drawn meanwhile, also
no page changes. It updates at once after boot, the night, the Power switch
and live mode, and when it is switched off. Rules can override it ("show at
once in slow mode"): while their page is shown the display works normally.
Settings layout 7 and schedule layout 4 (older records are converted; they
are stored again once the firmware is marked good, so a rollback still
finds the old ones). Pages in older formats are rewritten in the current
one, in time-boxed steps. /api/status reports old_data_left.
Version 2.15.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Home Assistant attributes can be paths into lists (forecast.1.condition).
- Date elements can show a day ahead (day offset 0-7).
- Pages hold 16 elements (page format 6; the old formats are frozen at 8).
Pages are reset in place (clearPage), not through a 4 KB temporary.
- Verwachting page: today (icon, temperature, max/min) and the next 2
days with 7 x 7 icons (weer7 <condition>), from a template sensor
(docs/home-assistant.md).
- examples/home-pages.json is exported from the display with all pages
and their icons, private entity id parts replaced by placeholders
(tools/export_examples.py replaces tools/make_example_pages.py).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Rules: "also over a page chosen by hand" (on by default); off, a rule
waits until the manual pick ends. Schedule store version 3, version 2
records are read with the option on.
- The Clock page is stored at boot from the built-in one and can be
edited; Reset (deleting it) brings back the original.
- Home Assistant attributes were never found: ArduinoJson 7.4 takes a
char array key as a literal of its full array length.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- net/ha_api: the HTTP requests run in a FreeRTOS task on core 0; loop()
only hands over copies through queues. The web UI's test button polls.
No more 3-4 s loop() stalls once a minute; timeout raised to 5 s.
- Progress bar page element (page format 4, v3 pages are converted)
- Plex user setting (settings v6): {plex_user} in entity ids
- Plex page (examples): watchers, play/pause icon, title, progress
- Bitmaps cached in RAM: a LittleFS read took ~100 ms on every render
and web preview; long JSON lists sent in 2 KB pieces
- Backup includes the refresh settings and the Plex user
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Schedule: daily blocks from a start time, each with up to 6 rotating pages
or bitmaps (own duration), switching with the effect or instantly. A manual
pick (Show tab, HA Mode) lasts until the next block; Back to schedule ends it.
- Rules: an HA state (=, is not, above, below) shows a page while true, adds it
to the rotation while true, or shows it for N seconds when it becomes true.
Each rule is polled at its own interval, with a 60 s back-off on errors.
- PageSelector (pure logic, tested) decides the shown page; schedule stored in
NVS; HA sensor Shown page and button Back to schedule.
- Web UI: Schedule and Stopwatch tabs, bitmaps used by pages or rules in their
own subsection, schedule in export/import. Version 2.6.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Text elements can scroll in a window at a set speed; clock, countdown and
stopwatch can show seconds. Moving pages are sent as instant frames (new
Nano command D1) and paced by the estimated flip time.
- Countdown to a date and time (smart, days, days + time, with seconds),
stopwatch (web UI, HA switch and reset button), image element (fixed or
by Home Assistant state), multiplier for HA values, degree sign (char 127)
in all fonts and the font converter.
- Page format version 2; version 1 pages are converted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hardcoded clock is now the built-in dynamic page "Clock". A dynamic page
has a background bitmap per time of day and up to 8 elements (clock, date,
Home Assistant value, text), each with position, alignment, font and overlay.
Pages are drawn on the ESP32, also for the web previews.
- Pages tab in the web UI: page editor with drag and drop, font upload
(TTF/OTF converted in the browser to the FDF1 dot font format)
- Built-in fonts Small, Normal, Large and Full height (generated by
tools/make_builtin_fonts.py), built-in bitmaps Pikachu and Pikachu yawning
- Home Assistant values over the REST API (URL and token in the HA tab)
- Settings version 4: evening settings removed (now time slots of the Clock
page), old records are converted
- HA Mode dropdown lists the dynamic pages and bitmaps
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home Assistant: remove the Clock switch (its entity is deleted on connect),
add an IP sensor and Mode / Off image dropdowns whose options follow the
saved bitmaps. Remove the built-in "Nintendo border" bitmap.
Off image: a bitmap (or blank) left on the dots when the display switches off.
Nano: pause after each flip pulse and repeat pulses for changed dots, both
stored in EEPROM (G/N commands). Refresh effects (E command): instant,
sparkle, wipe, rain, from the middle out, diagonal, spiral, flip all then
reveal, push and random, optionally only for small changes. Effects run in
steps from loop() so serial input keeps flowing.
Web UI: flip settings, refresh effect and test patterns under Settings; the
System tab shows why the ESP32 last restarted. Settings records from
versions 1 and 2 are migrated. Firmware 2.3.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 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>
- 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>
- 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>
Structure (src/esp32/):
- logic/: DisplayController, schedule, power timer, LED pattern; pure C++
- display/: FlipdotFrames and bitmaps
- nano_link/: NanoLink (relay, serial, READY, bootloader) and flash bridge
- net/: WiFi/OTA/panic window, Home Assistant
- config.h with all settings; libs.h (globals in a header) removed
Bug fixes:
- Home Assistant switches now report their state back and start as ON
- loop() no longer blocks: WiFi.waitForConnectResult() (up to 60 s
without WiFi) and getLocalTime() (5 s before NTP sync) were called
every iteration
- Power switch off now powers off after 1 s even when a 30 s countdown
is already running
- millis() overflow safe power-off timer; no frame catch-up bursts
- No garbage time string before NTP sync; 'Connecting...' stays instead
- Frames are only sent when the screen changes instead of every second
- Reset reasons are logged once instead of every 100 ms
- Removed dead code (unused fonts, WiFiMulti, rotated bitmap, ...)
Tests: new test_esp32 environment (26 tests); native renamed to test_nano
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>