Design: make a scheme describe intent, so it can drive devices other than WLED #155

Open
opened 2026-09-26 05:02:12 +00:00 by claude-bot · 0 comments
Collaborator

Why this has to come first

Every other "beyond WLED" item depends on this decision. That includes #13 (multi-controller), #12 (MQTT/HA) and the device issues filed alongside it: on/off decorations (#156), colour smart lights (#157), and FPP shows (#158). It is much cheaper to make now than after they are built.

Today a scheme is a WLED payload in disguise. Its segments carry WLED effect_id, sx, ix, pal and colour slots, and scheme_translator.py turns that almost 1:1 into /json/state. Verified against main:

  • There is no controller interface. DemoController subclasses the concrete HTTP WLEDController (services/demo_controller.py), and every call site type-hints the concrete class (wled_push, ramp, quick_push_manager).
  • The controller is a module-level singleton. The comment reads "v2: replace with dict[str, WLEDController]" (services/wled_controller.py).
  • Spec §16.3's design note was "abstract the client into a WLEDController class early": a single-vendor abstraction.

Iris's distinctive value is the calendar, schemes and human review, not device control; Home Assistant already controls every device. So the goal is that the curated calendar can drive whatever decorations someone owns, without Iris turning into a home-automation hub.

Proposal to evaluate

1. A scheme expresses intent, with optional device-specific detail:

  • a palette (ordered colours, from #28's palette work)
  • energy / motion (still → gentle → lively), brightness, and mood tags (festive, sombre, spooky, …)
  • a per-segment role (accent, fill, highlight)
  • an optional device-specific override block keyed by device type, e.g. wled: {effect_id, sx, ix, pal}. It lets WLED keep exact fidelity, because nobody should lose the ability to pick Fire 2012 at speed 140.

2. Device renderers, one per device type, each turning intent (plus its override block, if present) into that device's command:

  • A WLED renderer: today's translator, fed by the override block or derived from intent.
  • An on/off renderer: "on" whenever the envelope is on and the scheme's energy is above zero; that's all a smart plug can do.
  • A colour-light renderer: palette → per-bulb colours, energy → transition style.

3. A Controller Protocol, with capability flags (pixels, color, switch, sequence), implemented by WLEDController, DemoController and each new backend. The scheduler iterates devices and pushes each one its rendering. Push, retry, watchdog (#148), ramp and quick-push logic become per-device.

4. Migration:

  • Existing schemes become intent plus a wled: override block holding their exact current values, so nothing about an existing install changes.
  • Intent fields are derived where possible: the palette from the colour slots, energy from the effect family (the twelve families from #14 map naturally).

Questions the design must answer

  • How does review work when one approved scheme renders differently on five devices? Proposal: approve the intent, and preview each device's rendering in the side panel.
  • Segments versus devices: does a smart plug count as a "segment"? Probably a device is the top level, and WLED segments live inside a WLED device.
  • Multi-controller (#13) becomes "multiple devices", and the controller_id FKs in §16.3 become device_id. Reconcile the two before either is built.
  • Scheme version history (#11): does versioning cover the override blocks? Yes, it has to.
  • The AI prompt (prompt_builder.py) should generate intent plus the WLED block. Intent is also easier for a model to get right than opaque effect IDs (see #132 for how that went).
  • The photosensitivity guard (#150) must apply to every renderer, not only WLED's.

Deliverable

A design doc (docs/design/device-model.md) and an updated spec §16, reviewed before any of the dependent issues start, plus a spike: the Protocol and WLED renderer refactor with zero behaviour change, proven by the existing test suite passing unchanged.

## Why this has to come first Every other "beyond WLED" item depends on this decision. That includes #13 (multi-controller), #12 (MQTT/HA) and the device issues filed alongside it: on/off decorations (#156), colour smart lights (#157), and FPP shows (#158). It is much cheaper to make now than after they are built. **Today a scheme is a WLED payload in disguise.** Its segments carry WLED `effect_id`, `sx`, `ix`, `pal` and colour slots, and `scheme_translator.py` turns that almost 1:1 into `/json/state`. Verified against `main`: - **There is no controller interface.** `DemoController` subclasses the concrete HTTP `WLEDController` (`services/demo_controller.py`), and every call site type-hints the concrete class (`wled_push`, `ramp`, `quick_push_manager`). - **The controller is a module-level singleton.** The comment reads "v2: replace with dict[str, WLEDController]" (`services/wled_controller.py`). - **Spec §16.3's design note** was "abstract the client into a `WLEDController` class early": a single-vendor abstraction. Iris's distinctive value is **the calendar, schemes and human review**, not device control; Home Assistant already controls every device. So the goal is that the curated calendar can drive whatever decorations someone owns, without Iris turning into a home-automation hub. ## Proposal to evaluate **1. A scheme expresses intent, with optional device-specific detail:** - a **palette** (ordered colours, from #28's palette work) - **energy / motion** (still → gentle → lively), **brightness**, and **mood** tags (festive, sombre, spooky, …) - a per-segment **role** (accent, fill, highlight) - an optional **device-specific override block** keyed by device type, e.g. `wled: {effect_id, sx, ix, pal}`. It lets WLED keep exact fidelity, because nobody should lose the ability to pick *Fire 2012* at speed 140. **2. Device renderers**, one per device type, each turning intent (plus its override block, if present) into that device's command: - A WLED renderer: today's translator, fed by the override block or derived from intent. - An on/off renderer: "on" whenever the envelope is on and the scheme's energy is above zero; that's all a smart plug can do. - A colour-light renderer: palette → per-bulb colours, energy → transition style. **3. A `Controller` Protocol**, with capability flags (`pixels`, `color`, `switch`, `sequence`), implemented by `WLEDController`, `DemoController` and each new backend. The scheduler iterates devices and pushes each one its rendering. Push, retry, watchdog (#148), ramp and quick-push logic become per-device. **4. Migration:** - Existing schemes become intent **plus** a `wled:` override block holding their exact current values, so nothing about an existing install changes. - Intent fields are derived where possible: the palette from the colour slots, energy from the effect family (the twelve families from #14 map naturally). ## Questions the design must answer - How does **review** work when one approved scheme renders differently on five devices? Proposal: approve the intent, and preview each device's rendering in the side panel. - **Segments versus devices:** does a smart plug count as a "segment"? Probably a device *is* the top level, and WLED segments live inside a WLED device. - **Multi-controller (#13)** becomes "multiple devices", and the `controller_id` FKs in §16.3 become `device_id`. Reconcile the two before either is built. - **Scheme version history (#11):** does versioning cover the override blocks? Yes, it has to. - The AI prompt (`prompt_builder.py`) should generate **intent** plus the WLED block. Intent is also easier for a model to get right than opaque effect IDs (see #132 for how that went). - The photosensitivity guard (#150) must apply to every renderer, not only WLED's. ## Deliverable A design doc (`docs/design/device-model.md`) and an updated spec §16, reviewed before any of the dependent issues start, plus a spike: the Protocol and WLED renderer refactor with zero behaviour change, proven by the existing test suite passing unchanged.
claude-bot added this to the v2.0.0 milestone 2026-09-26 05:02:39 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Iris-WLED#155
No description provided.