Skip to content

Commit a3b095f

Browse files
refactor: extract Q10 map compositing into a single render result object
Addresses review feedback that `_render_packet` mutated ~8 trait fields through 3-4 layers of side-effecting methods, making the trait hard to review and blurring the state-management / pixel-work boundary. - Add `roborock/map/b01_q10_render.py`: `render_q10_map()` composes a map packet + path + overlays + calibration into one `Q10MapRender` result (image + MapData + layers), and owns the erase blanking, world->pixel overlay placement, path drawing and calibration policy that previously lived on the trait. The whole data flow reads top-to-bottom in one function instead of nested mutations. - `MapContentTrait` is now just state management: it accumulates the pushed inputs and rebuilds the single `Q10MapRender` wholesale on each change, exposing read-only properties. No more per-field clearing. The derived rendering scaffolding (erase zones, header calibration) is off the public surface; layers/calibration stay (used by the CLI + frontend compositing). - Move the geometry/pixel tests to tests/map/test_b01_q10_render.py; the trait tests now cover state management. - `UpdatableTrait` explicitly declares the `DpsUpdatable` protocol so the heterogeneous fan-out list's shared shape is documented (the map trait satisfies it structurally without being a converter-backed read-model).
1 parent c646086 commit a3b095f

5 files changed

Lines changed: 796 additions & 504 deletions

File tree

roborock/devices/traits/b01/q10/common.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,20 @@
2323
class DpsUpdatable(Protocol):
2424
"""A trait that updates itself from the Q10 DPS push stream.
2525
26-
Implemented by :class:`UpdatableTrait` (read-model traits) and by the map
27-
trait, which owns the vector-overlay data points. The ``Q10PropertiesApi``
28-
subscribe loop fans each push out to every such trait; each picks out the
29-
data points it is responsible for and ignores the rest.
26+
The ``Q10PropertiesApi`` subscribe loop fans each push out to every trait in
27+
its ``_updatable_traits`` list; each picks out the data points it is
28+
responsible for and ignores the rest. That list is heterogeneous -- most
29+
members are converter-backed :class:`UpdatableTrait` read-models, but the map
30+
trait implements ``update_from_dps`` directly to decode the vector overlays it
31+
owns without a read-model. This Protocol is the shared shape the loop needs;
32+
:class:`UpdatableTrait` declares it explicitly and the map trait satisfies it
33+
structurally.
3034
"""
3135

3236
def update_from_dps(self, decoded_dps: dict[B01_Q10_DP, Any]) -> None: ...
3337

3438

35-
class UpdatableTrait(TraitUpdateListener):
39+
class UpdatableTrait(TraitUpdateListener, DpsUpdatable):
3640
"""Base for Q10 traits backed by a read-model updated from the DPS stream.
3741
3842
Concrete traits subclass both their ``RoborockBase`` read-model and this

0 commit comments

Comments
 (0)