Files
thermostat-hw/TODO.md
T

108 lines
5.3 KiB
Markdown

# TODO
## Not yet verified on hardware
Flashed and booting clean (two-phase display init, icons on, first poll ~9s,
no errors), but eyes and fingers haven't confirmed:
1. Slider feel: press sends one command at the touch position immediately,
drag is display-only tracking the finger, lift sends the final level.
Poll data never moves a pressed knob.
2. Trend arrows appear ~5 minutes after boot (indoor big card, outdoor and
pressure cells) once the local ring has history. They are local-history
based and reset on reboot — that is by design, not a bug.
3. Artefact lifetime: interactions schedule a one-shot full repaint 600ms
after the last touch, and every poll repaints too. Artefacts should now
visibly self-clean in under a second after touching, and within a poll
otherwise. If they *persist* beyond that, the repaint isn't reaching
them; if they merely *recur* during interaction, that is the PSRAM
bandwidth ceiling (README) and the honest remaining levers are fewer
redraws or 120MHz PSRAM on a newer IDF.
## Done
The six items from the 2026-08-03 review were completed in `d4b2ab7`
("Work through the remaining review items in TODO.md"). See that commit
message for the reasoning behind each. Summary:
1. **UI pause window shrunk** — HTTP session kept alive between polls, timeout
drops 30s→10s once warm. Measured on hardware: fetch went from ~1.3s to
~80ms, so `lvgl_port_pause()` no longer blocks rendering and touch for a
meaningful period.
2. **Stale readings indicated** — temperature dims and the status line shows
age after two consecutive failures.
3. **Touch readout gated** behind `UI_DEBUG_TOUCH`, default off.
4. **`main/utils` deleted** — no callers.
5. **OTA partitions laid out** — two 4MB slots, `otadata`, ~7.9MB unallocated.
6. **Cleanups** — truncation logged once per response; weather task stack
high-water mark measured (~2400 bytes spare of 6144).
Verified on hardware after the change: boots from the new OTA layout, three
consecutive successful polls at 60s, no reboots.
## Still open
### 1. Confirm the left-edge artefacts are actually gone
The pause window is now ~80ms instead of ~1.3s, which should make the
artefacts much rarer — but **this has not been confirmed by eye**. The
timing improvement was measured from the log; the artefacts can only be
verified by watching the panel around the moment the status line updates.
If they persist, the remaining lever is pausing only around LVGL's flush (the
actual PSRAM writes) rather than the whole network transaction. That is more
invasive; do not start it until the current change has been observed to be
insufficient.
### 2. OTA implementation
Partition layout exists; the download/apply logic does not. **This is not a
drop-in.** An OTA write is a flash write, and the bounce-buffer refill ISR
reads PSRAM, which shares the cache with flash on the S3 — downloading while
the panel scans will fault it with "Cache disabled but cached memory region
accessed". The implementation must stop the panel for the download and write,
or reboot into a dedicated updater mode. See README "Partitions".
### 3. Backlight control (optional feature)
`backlight_set()` is only ever called once, with 255. A night-dim schedule or
touch-to-wake is a natural small feature. Note the STC8H1K28 shares the I2C
bus with the GT911, so brightness writes must stay in task context (never an
ISR) and will contend with touch polls on the same bus.
### 4. The wind sensors are dead (hardware, not software)
The station anemometer has read `unavailable` since 2026-07-27 — wind speed,
gust, direction and feels-like. The WIND tile shows `--` by design and will
keep doing so until the hardware is fixed. Nothing to change in the firmware;
noted so it is not re-diagnosed as a parsing bug. See README "Home Assistant".
### 5. The actual thermostat
Setpoint, HVAC relay control, scheduling and persistence are all still
unimplemented — this remains a weather display. Note a separate project
(`~/workspace/rotaryThermo`) has a PRD for building this on the CrowPanel 2.1"
rotary display instead, driven by Zigbee room sensors. Decide which board
hosts the thermostat before building it twice.
## Facts already established — do not re-investigate
- Build is clean on ESP-IDF v5.3 (`. ~/esp/esp-idf/export.sh && idf.py build`).
App is ~1.4MB in a 4MB OTA slot.
- `main/app_config.h` is gitignored and holds real credentials locally.
- `resp_buf` bounds/NUL-termination in `ambient_weather.c` is correct.
- GT911 read-then-clear-status ordering is correct.
- Backlight duty inversion maps correctly at both endpoints (255→0x00 full,
0→0xF5 off).
- The `°` glyph exists in LVGL's built-in Montserrat fonts; the `·` separator
that does not appears only in log strings, never on screen.
- LVGL recursive-mutex locking is consistent across all UI entry points.
- Init order in `main.c` is deliberate and load-bearing:
`display_alloc()` before WiFi (contiguous bounce buffers from a virgin
heap), WiFi/NVS before `display_start()` (flash writes finished before
scan-out), `backlight_init()` before `touch_init()`. Never reorder.
- The bounce buffer is enabled and load-bearing.
- Board is N16R8 (16MB flash / 8MB octal PSRAM).
- `touch_get_indev()`, `display_get_panel()` and `lvgl_port_is_paused()` are
uncalled but deliberately kept as driver API surface.