diff --git a/docs/KNOWN_ISSUES.md b/docs/KNOWN_ISSUES.md index 48d3578..c1c2549 100644 --- a/docs/KNOWN_ISSUES.md +++ b/docs/KNOWN_ISSUES.md @@ -30,7 +30,40 @@ The new `ControllerChunker` reads state as the response drains. On a slow link o ### Related - Same exposure exists in any other endpoint converted to chunked responses next (`/discovery`, `/shades`). Resolve this issue before expanding the pattern. -- Other handlers on the web server task still change the shade model that `loop()` owns: `/setPaired` sets `paired`, and `/setRollingCode` and a shades restore change rolling codes (see [Rolling codes written from two tasks](#rolling-codes-written-from-two-tasks)). Shade commands, set-My and unpair already go through the web command queue to `loop()`. +- Other handlers on the web server task still change the shade model that `loop()` owns: + - `/addRoom`, `/saveRoom`, `/deleteRoom`, `/addShade`, `/saveShade`, `/deleteShade`, `/addGroup`, `/saveGroup` and `/deleteGroup` add, change and remove rooms, shades and groups. + - `/linkRemote` and `/unlinkRemote` change a shade's linked remotes, and `/linkRemote` also sets a linked remote's rolling code. + - `/linkToGroup` and `/unlinkFromGroup` change a group's linked shades. + - `/setPaired` sets `paired`. + - `/setRollingCode` and a shades restore change rolling codes (see [Rolling codes written from two tasks](#rolling-codes-written-from-two-tasks)). + + Shade commands, set-My and unpair already go through the web command queue to `loop()`. +- `/controller` leaves out a room, shade, group or linked shade that doesn't fit in its chunk buffer, see [Oversized `/controller` items are left out](#oversized-controller-items-are-left-out). + +## Oversized `/controller` items are left out + +**Status:** open +**Location:** `ControllerChunker::overflowed` in [src/Web.cpp](../src/Web.cpp). + +### Summary + +`ControllerChunker` builds each room, shade, group and linked shade into a 3 KB buffer before sending it. When one doesn't fit, the chunker logs an `ESP_LOGE` line, skips that item and carries on, so the document stays valid JSON. The client gets no sign that anything is missing: the item just isn't in the list. + +A shade with every linked remote populated is about 1.5 KB today, so nothing overflows yet. It becomes a silent loss as soon as a change to the shade, room or group fields pushes an item past 3 KB. + +### Concrete failure modes + +1. A shade is left out after a firmware change adds fields to it. It is missing from the config UI, and Home Assistant doesn't create an entity for it. +2. A group whose `linkedShades` entry doesn't fit loses that shade from its list. + +### Fix options (pick one later) + +- **(a) Fail loud.** Add a list of the skipped item ids to the end of the document, and show a warning in the UI. +- **(b) Check the size at build time.** Work out the worst case for each item from the field limits and `static_assert` that it fits the buffer, so a change that breaks it doesn't build. + +### Related + +- The same "lost without telling the client" problem as [Large websocket events are dropped](#large-websocket-events-are-dropped). ## Large websocket events are dropped @@ -81,3 +114,17 @@ Sending a command reads the next rolling code, queues the frame, then commits th ### Related - Same root cause as [Concurrent mutation during chunked `/controller` response](#concurrent-mutation-during-chunked-controller-response): the web server task changes the shade model that `loop()` owns. +- `/linkRemote` sets a linked remote's rolling code on the web server task, while `loop()` updates the same code when it receives a frame from that remote. The last write wins, so a received frame can undo the code just set. + +## `/setMyPosition` without a tilt uses the lift favorite + +**Status:** open +**Location:** the `/setMyPosition` handlers in [src/Web.cpp](../src/Web.cpp). This was already in the code before the radio task work. + +### Summary + +When a request for a shade with tilt leaves out `tilt`, the handler fills it in with `shade->myPos`, the lift favorite, where `shade->myTiltPos` looks intended. The favorite tilt is then set to the favorite lift position. The web UI always sends `tilt`, so only API callers that leave it out see this. + +### Fix + +Use `shade->myTiltPos` in both handlers, after checking that no API client depends on the current behaviour.