The Pool Monitor is a compact E-Ink display device that shows current pool data by subscribing to Home Assistant MQTT topics from the Pool Controller:
- Pool water temperature
- Solar storage temperature
- Pool pump status (on/off)
- Solar heating status (on/off)
All data is read-only — the monitor displays what the pool controller publishes. No sensors, relays, or wiring required. Just power via USB-C and configure WiFi + MQTT through the captive portal.
- WiFi configuration via captive portal (ESP-WiFiSettings)
- MQTT connection to existing pool controller
- Reads Home Assistant MQTT state topics
- NTP time synchronisation with automatic CET/CEST
- Deep-sleep operation (180 s cycle, ~5.5 mA average)
- Solar-powered operation (documented in Hardware Guide)
- OTA firmware updates via GitHub Releases
- System monitoring with watchdog and memory checks
- Boot-loop detection for reliable operation
- Configuration portal with QR code on MQTT errors
- Support for additional display sizes
- Ability to switch solar heating on/off (requires interactive mode)
- Ability to switch pool pump on/off (requires interactive mode)
- Web dashboard (served from ESP32 during configuration mode)
- Users Guide — Setup, configuration, display layout
- Hardware Guide — Board variants, pinout, solar powering
- Software Guide — Development, build, MQTT topics
The firmware follows the same patterns as the Pool Controller for consistency:
- PoolMonitorContext — main singleton that owns all subsystems
- SystemMonitor — watchdog, memory monitoring, boot-loop detection
- NetworkManager — WiFi and MQTT connection management
- DisplayManager — E-Ink display control
- OtaUpdater — OTA firmware update checker and installer
- TimeClientHelper — NTP time sync and timezone support
Key design principles: RAII resource management, static method access for
subsystems, dependency injection via Preferences handles, stack-allocated
buffers for memory safety, and graceful degradation on errors.
Run the local quality gates before pushing changes:
- Install Python-based linters once:
python3 -m pip install --user cpplint yamllint markdownlint-cli2andjscpdare executed on demand vianpxmake lintruns Super-Linter via Docker (see CONTRIBUTING.md)- Stage your changes first, then run:
platformio check --environment LILYGO_T5_V231 --skip-packages
platformio run --environment LILYGO_T5_V231
mapfile -t cpp_files < <(git diff --cached --name-only -- '*.cpp' '*.hpp' '*.h')
((${#cpp_files[@]})) && cpplint "${cpp_files[@]}"
mapfile -t md_files < <(git diff --cached --name-only -- '*.md')
((${#md_files[@]})) && npx --yes markdownlint-cli2 "${md_files[@]}"
mapfile -t yaml_files < <(git diff --cached --name-only -- '*.yml' '*.yaml')
((${#yaml_files[@]})) && yamllint "${yaml_files[@]}"
npx --yes jscpd --config .jscpd.json src .github/workflows
python -m json.tool .jscpd.json > /dev/nullSee GitHub Discussions.