Redesign panels, add 11 card fixes, new icons and app surfaces
Panel fixes: tall card row_span, room tab styling, vacuum card image+value, AC airflow labels, AC fan speed sections (auto 3-btn + manual 5-step slider), light subtitle fallback, curtain pane dividers, dimmable light presets, LED panel brightness + reorder. New assets: 34 ui-icons (climate modes, cover, effects, battery, led-strip, switch states), 3 logos, 90 app surface PNGs, design system specs (components, ux-mechanics, tokens). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
89ff17a3bc
commit
86191ba5f3
221 files changed
+6017
-1123
No files matched your search
@@ -0,0 +1,465 @@
|
||||
# Luma Home — UX mechanics
|
||||
|
||||
The behaviour contract for the Home Assistant tab. Every rule here is meant to be implemented
|
||||
exactly; where a number is given (timings, steps, sizes) it is the spec, not an example.
|
||||
Visual reference for every card and panel: `screens/`. Measurements and colours: `components.md`
|
||||
and `tokens.json`.
|
||||
|
||||
Input is the LG remote only: **◀ ▶ ▲ ▼, OK, Back**. Viewing distance 5–6 m on a 65" TV, logical
|
||||
layout 1920 × 1080.
|
||||
|
||||
---
|
||||
|
||||
## Part A — Global rules
|
||||
|
||||
### A1. Tap and hold on OK
|
||||
|
||||
| | Rule |
|
||||
|---|---|
|
||||
| Tap | OK pressed and released in **under 0.4 s**. The action runs **on release**. |
|
||||
| Hold | OK still down at **0.4 s**. The hold action runs **at 0.4 s**, while the key is still down. The release that follows is ignored. |
|
||||
| Hold cue | From the moment OK goes down, a ring fills around the focused element's icon over 0.4 s (white stroke on a 18%-white track). Released early: the ring disappears and the tap runs. |
|
||||
| No hold action | If the focused element has no hold action, there is no ring and a long press behaves as a tap on release. |
|
||||
| Key repeat | OK auto-repeat events from the TV are ignored. Arrow auto-repeat is used where stated (sliders, volume). |
|
||||
|
||||
Timing is measured from the key-down event to the key-up event as delivered by SDL-webOS
|
||||
(Wayland press/release). A tap never toggles anything on key-down, so a hold can never toggle by accident.
|
||||
|
||||
### A2. Screen structure and focus order
|
||||
|
||||
```
|
||||
Top nav (Start · Apps · Home · Settings)
|
||||
▼
|
||||
Room tabs (Home · Living Area · Kitchen · …)
|
||||
▼
|
||||
Card grid (4 × 3 or 3 × 3)
|
||||
```
|
||||
|
||||
- **▲ from the top row of the grid** → room tabs (the active room's tab). **▲ from room tabs** → top nav.
|
||||
- **▼ from room tabs** → the card that was focused last in that room (first card the first time).
|
||||
- **◀ ▶ on room tabs** switches rooms immediately (no OK needed); the grid below changes, focus stays on the tabs.
|
||||
- **Back from a card** → room tabs. **Back from room tabs** → top nav. Back from top nav does nothing.
|
||||
- Focus memory: each room remembers its last focused card for the session.
|
||||
|
||||
### A3. The grid
|
||||
|
||||
- Every screen is a fixed grid: **4 columns × 3 rows** (cell 424 × 240) or, chosen per screen,
|
||||
**3 columns × 3 rows** (cell 572 × 240). Gap 18 px, grid area 1752 × 756 at x 84, y 206.
|
||||
- Cards fill whole cells only: **1×1**, or **1×2** (one column, two rows tall, 498 px) for weather and media.
|
||||
- No scrolling inside a screen. A room with more cards than cells shows the first 12 (or 9); more
|
||||
rooms or screens are added as tabs, not as scrolling.
|
||||
- Movement is spatial: ◀ ▶ ▲ ▼ go to the card whose cell is next in that direction. No wrap-around.
|
||||
- **1×2 cards:** entering from the side keeps the row you came from in memory; leaving sideways
|
||||
returns to that row on the other side. ▼ from a 1×2 card goes to the cell below its bottom row.
|
||||
- Empty cells are skipped: the move continues in the same direction to the next card, or does nothing.
|
||||
|
||||
### A4. Focus visuals
|
||||
|
||||
- Focused card: **4 px white ring (96%)** with a **4 px dark gap** (`rgba(8,11,18,0.85)`) between
|
||||
ring and card, card **scales to 1.04**, fill brightens, shadow deepens. 120 ms ease-out.
|
||||
- Inside a panel or the media card the ring sits on the focused control, not on the card.
|
||||
- Exactly one ring on screen at any time.
|
||||
|
||||
### A5. Card anatomy (1×1)
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────┐
|
||||
│ (icon) Name Value │ ← top row: 48 px icon circle, name 19 px, value 20 px bold
|
||||
│ │
|
||||
│ ───────── middle band ─────────────── │ ← graph / level bar / colour strip / window / photo
|
||||
│ │
|
||||
│ Subtitle (context) │ ← 14 px, optional; context, never the state
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **On**: icon circle and value take the card's accent colour, plus a soft radial glow top-left.
|
||||
- **Off**: grey icon circle (white 10%), value white 60%, no glow.
|
||||
- **Unavailable** (HA `unavailable`/`unknown`): card at 50% opacity, value "Offline", OK does nothing,
|
||||
hint bar shows "Offline". Hold OK still opens the panel if the card has one (read-only).
|
||||
|
||||
### A6. The hint bar
|
||||
|
||||
Bottom-left of every screen, 14 px. It always describes the **focused** element:
|
||||
`OK <tap action> · Hold OK <hold action> · Back <where Back goes>`.
|
||||
- Labels are verbs for the actual next result: "Turn on" when off, "Turn off" when on.
|
||||
- If there is no hold action, the "Hold OK" item is **not shown** (no "Details", no placeholder).
|
||||
- Media and panels add their arrow hints (e.g. "▲▼ Volume").
|
||||
|
||||
### A7. Panels (Hold OK)
|
||||
|
||||
- A panel opens on the **right side**, 620 × 1080, on top of the grid. The grid stays visible and dimmed behind it.
|
||||
- Focus moves into the panel on its **first section**. The card keeps a static (non-focused) highlight so you can see which card the panel belongs to.
|
||||
- Inside a panel: **▲ ▼ move between sections (rows)**, **◀ ▶ adjust or choose within the row**,
|
||||
**OK selects / presses**, **Back closes** the panel and returns focus to the card.
|
||||
- Changes apply **live** while the panel is open — there is no Save. Slider changes are sent
|
||||
**200 ms after the last press** (one call per burst); buttons and presets are sent at once.
|
||||
- If the entity becomes unavailable while the panel is open, the panel stays, controls go
|
||||
disabled, and the header subtitle shows "Offline".
|
||||
- Sections that the entity doesn't support are **hidden**, not disabled (e.g. no airflow rows
|
||||
on a radiator, no colour on a dimmable light).
|
||||
|
||||
### A8. Sliders inside panels
|
||||
|
||||
- ◀ ▶ change by the stated step. Holding an arrow repeats every **150 ms** after an initial **400 ms**;
|
||||
after 2 s of holding the step doubles.
|
||||
- The value label updates on every step; HA receives the value 200 ms after the last step.
|
||||
- Values clamp at the ends; no wrap-around.
|
||||
|
||||
### A9. State updates and errors
|
||||
|
||||
- **Optimistic:** the card shows the new state the moment the action is sent.
|
||||
- **Confirmation:** the real HA state replaces it when it arrives. If no matching state arrives within **5 s**,
|
||||
the card reverts and the hint bar shows "Couldn't reach <Name>" for 4 s.
|
||||
- HA state changes from elsewhere (app, automation) update cards and open panels live, except a
|
||||
control currently being adjusted (it keeps the local value until 1.5 s after the last press).
|
||||
|
||||
---
|
||||
|
||||
## Part B — Cards
|
||||
|
||||
Each card: what it shows, every key, the panel, states, hint bar and Home Assistant calls.
|
||||
|
||||
### B1. Light — on/off
|
||||
|
||||
For lights that only switch (no brightness).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Name, value **On / Off**, optional subtitle. No middle band. Accent gold `#F5B85A`. |
|
||||
| OK (tap) | Toggle. |
|
||||
| Hold OK | Nothing (no panel, no ring). |
|
||||
| Hint bar | `OK Turn on` / `OK Turn off` |
|
||||
| HA | `light.toggle` (or `light.turn_on` / `light.turn_off`) |
|
||||
|
||||
### B2. Light — dimmable (no colour)
|
||||
|
||||
For lights with brightness only (e.g. Ceiling Lights).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = brightness % or **Off**. Middle band: brightness bar (12 px) in the accent. |
|
||||
| OK (tap) | On / off. Turning on restores the **last brightness**. |
|
||||
| Hold OK | Brightness panel. |
|
||||
| Hint bar | `OK Turn on · Hold OK Brightness & presets` |
|
||||
|
||||
**Panel — sections top to bottom**
|
||||
1. **Brightness** — slider 1–100 %, ◀ ▶ **10 %** steps (A8). Going below 10 % with ◀ stops at 1 %; ◀ again turns off.
|
||||
2. **Presets** — Off · 25 % · 50 % · 100 %. ◀ ▶ choose, OK applies.
|
||||
|
||||
OK on the Brightness row toggles on/off. Back closes.
|
||||
|
||||
HA: `light.turn_on` with `brightness_pct`; `light.turn_off`.
|
||||
|
||||
### B3. Light — colour (white + RGB)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = brightness %. Middle band: brightness bar **in the light's current colour**. Accent, glow and bar follow the live colour (warm white → gold). Subtitle: "White · 2700 K" or "Colour". |
|
||||
| OK (tap) | On / off at the last colour and brightness. |
|
||||
| Hold OK | Brightness & colour panel. |
|
||||
| Hint bar | `OK Turn on · Hold OK Brightness & colour` |
|
||||
|
||||
**Panel**
|
||||
1. **Brightness** — as B2.
|
||||
2. **Light type** — two buttons **White · Colour**. ◀ ▶ + OK switches. White restores the last
|
||||
colour temperature, Colour restores the last hue.
|
||||
3. **White temperature** (White mode) — slider, ◀ ▶ **250 K** steps within the light's min–max
|
||||
(typically 2700–6500 K). Label "2700 K · warm" / "4000 K · neutral" / "6500 K · cool".
|
||||
**or Hue** (Colour mode) — ◀ ▶ **15°** steps around the colour wheel, full saturation.
|
||||
4. **Swatches** — White mode: 2700 · 3000 · 4000 · 5000 · 6500 K. Colour mode: 8 colours
|
||||
(red, orange, yellow, green, blue, violet, pink, white). OK applies.
|
||||
|
||||
HA: `light.turn_on` with `brightness_pct`, `color_temp_kelvin` or `hs_color`.
|
||||
|
||||
### B4. LED strips and TV lights (with effects)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = brightness % or Off. Middle band: 34 px strip showing the current colour, or the effect's gradient. Subtitle: "Effect: Aurora", "White · 3000 K" or "Colour". |
|
||||
| OK (tap) | On / off (restores last colour or effect). |
|
||||
| Hold OK | Colours & effects panel. |
|
||||
| Hint bar | `OK Turn on · Hold OK Colours & effects` |
|
||||
|
||||
**Panel**
|
||||
1. **Brightness** — as B2.
|
||||
2. **Light** — White · Colour (as B3). Switching modes swaps the presets in row 4.
|
||||
3. **Temperature** (White) or **Hue** (Colour) — as B3.
|
||||
4. **White presets** (2700 · 3000 · 4000 · 5000 · 6500 K) **or Colour presets** (8 swatches).
|
||||
5. **Effects** — up to **6 pinned effects** as buttons, then **"All effects · N ›"**.
|
||||
OK on an effect plays it (the button shows "Playing"). OK on "All effects" opens the list.
|
||||
|
||||
**All effects list** (replaces the panel content, same position)
|
||||
- Two groups: **Pinned** (in pin order, numbered) then **All effects A–Z**.
|
||||
- ▲ ▼ move, the list scrolls to keep focus visible. **OK plays** the effect.
|
||||
**Hold OK pins / unpins** it (star fills gold).
|
||||
- Pins are unlimited. **The panel shows the first 6 pins.** A 7th or later pin stays in the
|
||||
Pinned group at the top of this list, tagged "Not on panel"; nothing changes on the panel.
|
||||
Unpinning one of the first 6 moves the next pin up onto the panel.
|
||||
- Back returns to the panel with focus on the Effects row.
|
||||
- Pins are stored per light in local preferences.
|
||||
|
||||
HA: `light.turn_on` with `effect` (list from the entity's `effect_list`), `brightness_pct`, `hs_color`, `color_temp_kelvin`.
|
||||
|
||||
### B5. Air conditioner (Gree AC)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = target temperature ("25°"). Middle band: 24 h room-temperature graph (grey when off). Subtitle: "Heat · 26° inside". Accent by mode: heat `#F06A4A`, cool blue. |
|
||||
| OK (tap) | On / off; turning on resumes the **last mode**. |
|
||||
| Hold OK | AC panel. |
|
||||
| Hint bar | `OK Turn on · Hold OK Mode, fan & airflow` |
|
||||
|
||||
**Panel — sections top to bottom**
|
||||
1. **Target** — ◀ ▶ by the entity's step (Gree: 1°), within its min–max.
|
||||
2. **Mode** — icon buttons: Auto · Cool · Dry · Fan · Heat. OK selects.
|
||||
3. **Fan speed · auto** — preset pills **Auto · Quiet · Turbo**. OK selects.
|
||||
4. **Fan speed · manual** — 5-step slider Low · Medium-low · Medium · Medium-high · High.
|
||||
◀ ▶ moves one step and selects manual. Selecting a step clears the auto preset;
|
||||
selecting an auto preset greys the slider (still focusable).
|
||||
5. **Up–down airflow** — icon-only: **Swing** + 5 fixed positions.
|
||||
6. **Left–right airflow** — icon-only: **Swing** + 5 fixed positions.
|
||||
Row label shows the current value ("Fixed · position 2", "Swing").
|
||||
|
||||
Radiators and wall thermostats have their own card (B5b).
|
||||
Gree extra toggles (Light, X-Fan, Health, Sleep, SE) are **not** included.
|
||||
|
||||
HA: `climate.turn_on/turn_off`, `climate.set_temperature`, `climate.set_hvac_mode`,
|
||||
`climate.set_fan_mode`, `climate.set_swing_mode` (and the Gree integration's swing-position
|
||||
entities for fixed positions).
|
||||
|
||||
### B5b. Heating — radiator valve (TRV) and wall thermostat
|
||||
|
||||
One card type with two versions, picked by the device. Both are `climate` entities with modes
|
||||
**off / heat** only.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = target temperature, or **Off**. Middle band: 24 h room-temperature graph. Subtitle: what it is doing + room temperature — "Heating · 22.5° inside", "Idle · 23° inside" (target reached), or "22.5° inside" when off. Accent heat `#F06A4A`. |
|
||||
| Warnings | Shown in the subtitle in **amber** `#F2B84B`, 600 weight, replacing the normal text: "Window open · paused" (value shows the setback temperature), "Battery low". |
|
||||
| Unavailable | Card at 50 %, value "Offline", subtitle "Last seen <time>". OK does nothing; Hold OK opens the panel read-only. |
|
||||
| OK (tap) | Heat / off. Turning on restores the last target. |
|
||||
| Hold OK | Heating panel. |
|
||||
| Hint bar | `OK Turn on · Hold OK Temperature & preset` |
|
||||
|
||||
**Panel — sections top to bottom**
|
||||
1. **Target** — dial with − / +; shows target, room temperature inside the dial and the step and range below.
|
||||
◀ ▶ by the entity's step (**0.5°**), clamped to its range. Radiator valve: **5–30°**.
|
||||
Wall thermostat: the device reports 5–90° (boiler relay); the panel **limits it to 5–35°**.
|
||||
2. **Mode** — Off · Heat.
|
||||
3. **Preset** — radiator valve: **Auto** (follows the device schedule) · **Manual** · **Holiday**.
|
||||
Wall thermostat: **Program** (shows the program name, e.g. "P1") · **Hold**. The `none` preset is not shown.
|
||||
Choosing a preset is sent at once; changing the target while in Auto / Program moves the device to Manual / Hold
|
||||
(the device does this itself — the panel just shows the new preset when HA reports it).
|
||||
4. **Temperature sensor** (wall thermostat only) — options from the device's sensor select (e.g. Internal · External · Both).
|
||||
5. **Settings** — toggles. Radiator valve: **Open-window detection**, **Child lock**. Wall thermostat: **Child lock**.
|
||||
6. Footer line (read-only): radiator valve "Battery OK" / "Battery low" (amber); thermostat "Controls the boiler".
|
||||
|
||||
Not shown (set once on the device or in HA): comfort / eco / open-window temperatures, temperature
|
||||
calibration, heating stop.
|
||||
|
||||
HA: `climate.set_hvac_mode` (`off` / `heat`), `climate.set_temperature`, `climate.set_preset_mode`,
|
||||
`switch.turn_on/off` for open-window detection and child lock, `select.select_option` for the
|
||||
thermostat's sensor, `binary_sensor.*_battery_low` for the battery warning, `hvac_action` for Heating / Idle.
|
||||
|
||||
### B6. Curtains (covers)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value = position % (100 = open). Middle band: a small window with two curtain panels drawn at the current position. While moving the value shows the direction ("Opening…"). |
|
||||
| OK (tap) | **Moving → Stop.** Closed → Open. Open or partly open → Close. |
|
||||
| Hold OK | Curtain panel. |
|
||||
| Hint bar | `OK Close · Hold OK Position & presets` (verb follows the rule above) |
|
||||
|
||||
**Panel**
|
||||
1. **Window** — large drawing of the window and rail with the current position; ◀ ▶ close / open by **10 %** (A8).
|
||||
2. **Buttons** — Open · Stop · Close (below the window). OK presses.
|
||||
3. **Presets** — Open · 60 % · 45 % · 30 % · Closed. OK moves there; the active preset is outlined.
|
||||
|
||||
HA: `cover.open_cover`, `cover.close_cover`, `cover.stop_cover`, `cover.set_cover_position`.
|
||||
|
||||
### B7. Switches, plugs and locks
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Value On / Off (locks: Locked / Unlocked). No middle band. Accent blue `#7EB8DA`, locks green. |
|
||||
| OK (tap) | Toggle. |
|
||||
| Hold OK | Nothing — no panel for now. |
|
||||
| Hint bar | `OK Turn on` / `OK Turn off` (no Hold OK item) |
|
||||
| HA | `switch.toggle`, `lock.lock` / `lock.unlock` |
|
||||
|
||||
### B8. Weather
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 or 1×2, chosen per screen. |
|
||||
| Shows | 1×1: icon, temperature, condition, humidity, wind, high/low. 1×2: the same on top, **5-day forecast below**. |
|
||||
| OK (tap) **and** Hold OK | Open the forecast panel (there is nothing to switch, so a tap opens it too). |
|
||||
| Hint bar | `OK Forecast` |
|
||||
|
||||
**Panel**
|
||||
1. Header: now · condition · high / low, Humidity, Wind.
|
||||
2. **Next hours** — ◀ ▶ scroll hour by hour.
|
||||
3. **Next days** — 5 days with a low–high range bar.
|
||||
|
||||
Data source: the existing Open-Meteo weather service (`src/weather.rs`).
|
||||
|
||||
### B9. Media player
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 or 1×2. |
|
||||
| Shows | Artwork, "Playing · Spotify", volume (icon + %, right-aligned on the same line), title, artist, progress bar, and three buttons **Previous · Play/Pause · Next**. 1×2 adds large artwork and elapsed / remaining times. |
|
||||
|
||||
The only card with its own buttons. Arriving on it puts the ring on **Play/Pause**.
|
||||
|
||||
**Keys**
|
||||
|
||||
| Key | Does |
|
||||
|---|---|
|
||||
| ◀ ▶ | Move between the three buttons. ◀ on Previous / ▶ on Next → the neighbouring card. |
|
||||
| ▲ ▼ | **Volume**, from any button. Never moves focus. |
|
||||
| OK (tap) | Previous · play/pause · next. Previous restarts the track if more than 3 s in, otherwise previous track. |
|
||||
| Hold OK on Previous / Next | **Rewind / fast-forward** (below). |
|
||||
| Hold OK on Play/Pause | Media panel. |
|
||||
| Back | Leave upward to the room tabs (the only vertical exit). While seeking: cancel the seek. |
|
||||
|
||||
**Fast-forward and rewind**
|
||||
1. Press OK on Next (or Previous). For 0.4 s the hold ring fills around the button.
|
||||
2. At 0.4 s seeking starts: the playhead jumps **+10 s** (−10 s) and a white bubble appears
|
||||
above it: `current → target · jump`, e.g. "3:09 → 3:49 · +40 s". Times follow the target.
|
||||
3. While held: another 10 s every **0.3 s**; after **2 s** of holding, steps are **30 s**.
|
||||
4. Release: **one** `media_player.media_seek` to the target. Playback continues (or stays paused)
|
||||
from there; the bubble fades after 1 s.
|
||||
5. Nothing is sent to HA while holding — only the preview moves.
|
||||
6. Clamped to 0:00 and duration − 1 s; seeking never changes track.
|
||||
7. If the player doesn't support seek: no ring, no hold action, hint bar omits "Hold OK".
|
||||
|
||||
**Volume**
|
||||
- ▲ / ▼ = **±2 %** per press; holding repeats every **150 ms** (0 → 100 % in about 7 s).
|
||||
- The readout turns into a **white pill** with the new value while changing and returns to plain
|
||||
text **1.5 s** after the last press.
|
||||
- Shown at once; `media_player.volume_set` is sent **200 ms** after the last press. Clamped 0–100 %.
|
||||
- No volume support: ▲ ▼ do nothing and the readout is hidden.
|
||||
|
||||
**States**
|
||||
- Playing: purple accent `#9B7DDB` and glow, Pause icon.
|
||||
- Paused: muted label, no glow, Play icon.
|
||||
- Idle / off: "Nothing playing", last artwork dimmed; OK on Play resumes the last source.
|
||||
- Unavailable: card dimmed, buttons disabled, hint "Player offline".
|
||||
|
||||
**Hint bar**
|
||||
- Play/Pause: `OK Pause · Hold OK Queue & source · ▲▼ Volume`
|
||||
- Next: `OK Next track · Hold OK Fast-forward · ▲▼ Volume`
|
||||
- Previous: `OK Previous · Hold OK Rewind · ▲▼ Volume`
|
||||
|
||||
**Panel (Hold OK on Play/Pause)**
|
||||
1. Now playing header with volume.
|
||||
2. **Play on** — output devices (Soundbar · TV · speakers). OK switches the source.
|
||||
3. **Up next** — queue, if the player exposes one; otherwise hidden.
|
||||
4. **Search** — only if implemented; otherwise hidden.
|
||||
|
||||
HA: `media_player.media_play_pause`, `media_next_track`, `media_previous_track`,
|
||||
`media_seek`, `volume_set`, `select_source`.
|
||||
|
||||
### B10. Robot vacuum (Roborock)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 |
|
||||
| Shows | Middle band: the **vacuum photo on the right**, facts on the left. **Cleaning:** Mode (e.g. "Vac & Mop", in green) and Now in (room); subtitle "Battery 64 % · 2 rooms left". **Docked:** Battery and **Water · clean / dirty** from the dock; subtitle "Ready". |
|
||||
| Accent | Green `#60C090` while cleaning; grey when docked. |
|
||||
| OK (tap) | Docked → **start** (full clean in the last mode). Cleaning → **return to dock**. Paused → resume. |
|
||||
| Hold OK | Room cleaning panel. |
|
||||
| Hint bar | `OK Start · Hold OK Room cleaning` / `OK Back to dock · Hold OK Room cleaning` |
|
||||
|
||||
**Dock water:** each tank reads **OK**, **Refill** (clean tank low) or **Empty** (dirty tank full).
|
||||
A problem turns that fact **amber** `#F2B84B` and the subtitle says what to do
|
||||
("Refill the clean water tank"). If the dock reports percentages, show "80 % / 15 %" in the same place.
|
||||
|
||||
**Panel**
|
||||
1. **Rooms** — grid of rooms; ◀ ▶ ▲ ▼ move, OK toggles a room (selected = green outline).
|
||||
2. **Mode** — Vacuum · Mop · Vac & Mop.
|
||||
3. **Routines** — saved routines (e.g. After Meals, V&M Fast); OK runs one.
|
||||
4. **Dock** — send to dock.
|
||||
5. **Primary button** — "Clean N rooms" (disabled with 0 rooms). OK starts.
|
||||
|
||||
HA: `vacuum.start`, `vacuum.return_to_base`, `vacuum.pause`, room cleaning via
|
||||
`vacuum.send_command` (`app_segment_clean` with segment IDs), mode via the integration's select
|
||||
entities, routines via their button entities, dock water via the integration's dock sensors.
|
||||
|
||||
---
|
||||
|
||||
### B11. Room card (Home overview)
|
||||
|
||||
One card per room, for the Home overview: how the room is at a glance, and quick on/off for its devices.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Size | 1×1 (also on the 3-column grid). Default placement: one row of four on the Home overview. |
|
||||
| Background | The Home Assistant **area picture** (provided by Home Assistant only — see *Room photos* below), cover-cropped, with a dark gradient at the top (behind name and temperature) and the bottom (behind the stats). **Any light on:** photo at full brightness. **All lights off:** photo at 45 % brightness, 20 % saturation. No picture: a normal glass card with the gold glow while any light is on. |
|
||||
| Top row | Room icon circle (gold when any light is on, grey otherwise) · room name · **value = room temperature** (the area's temperature sensor; hidden if none). |
|
||||
| Bottom line | Up to three stats, icon + value, no labels: **Lights** "3 on" / "Off" (gold when on) · **Curtains** "72%" / "Open" / "Closed" · **Air** "Good" (green `#3DDC97`) / "Fair" (amber) / "Poor" (red `#FF6B5A`). A stat the room has no device for is left out. |
|
||||
| Subtitle | What the room's climate is doing: "Radiator heating to 23°", "AC cooling to 24°"; empty when idle. Warnings replace it in amber: "Open a window" (poor air), and the device warnings from B5b. |
|
||||
| OK (tap) | **Open the room**: switch to the room's tab, focus on its first card. |
|
||||
| Hold OK | Room quick panel. |
|
||||
| Hint bar | `OK Open <Room> · Hold OK Quick controls · Back Rooms` |
|
||||
|
||||
**Counting rules**
|
||||
- Lights: every `light.*` entity in the area, LED strips and TV lights included. "3 on" counts lights that are on.
|
||||
- Curtains: one cover → its position ("72%", 100 % = "Open", 0 % = "Closed"). Several → "Open" if any is open, else "Closed".
|
||||
- Air quality from CO₂: **Good < 800 ppm**, **Fair 800–1200**, **Poor > 1200** (to be confirmed per sensor; PM2.5 or a combined index can replace CO₂ with its own thresholds).
|
||||
|
||||
**Room photos — provided by Home Assistant only**
|
||||
|
||||
The room photo is **not** part of Luma. Home Assistant is the single source: each room card shows the
|
||||
picture set on its **Home Assistant area**. Luma must never ship, bundle or ask for room photos itself.
|
||||
|
||||
| | Rule |
|
||||
|---|---|
|
||||
| Where the photo is set | In Home Assistant: *Settings → Areas, labels & zones → (area) → picture*. One photo per area. |
|
||||
| How Luma finds it | Read the area registry over the existing WebSocket (`config/area_registry/list`). The area's `picture` field is a path on the HA server (e.g. `/api/image/serve/<id>/…`). Empty → no photo. |
|
||||
| How Luma loads it | HTTP GET of that path on the HA base URL, with the same access token Luma already uses. On a worker thread, never the SDL thread. Decode, cover-crop and scale to the card size (424 × 240, or 572 × 240 on a 3-column screen), then upload to the GPU on the SDL thread. |
|
||||
| Caching | Keep the scaled image in Luma's local cache, keyed by the `picture` value. Reuse it on restart; no download while the value is unchanged. |
|
||||
| When it changes | On `area_registry_updated`, re-read the area. A new `picture` value → fetch the new photo and replace the cached one. Removed → fall back to the glass card. |
|
||||
| When it fails | No picture, HTTP error, timeout or undecodable image → glass card with the gold glow. Retry on the next registry update or app start. No error message on screen. |
|
||||
| Never | No room photos in the repository or the IPK, no photo setting inside Luma, no images from any other source. The blurred photos in the design renders are placeholders for the mock-ups only and must not ship. |
|
||||
|
||||
**Setting it up (once per room, in Home Assistant):** upload a landscape photo of the room to its area.
|
||||
Best results: taken with the room lights on, at least 1200 px wide, with the interesting part in the
|
||||
middle (the top and bottom of the card are darkened for text).
|
||||
|
||||
**Quick panel — sections top to bottom**
|
||||
1. Header: room name; temperature · humidity · air quality.
|
||||
2. **Lights · N of M on** with an **All off** button (first focus stop when any light is on), then one row per light: icon, name, state ("50%", effect name, "On", "Off") and an on/off switch.
|
||||
3. **Curtains**: one row per cover with **Open · Stop · Close**.
|
||||
4. **Climate**: one row per AC / radiator / thermostat with its state ("Heat · 23°") and an on/off switch.
|
||||
|
||||
Keys: ▲ ▼ move between rows (All off counts as a row). OK toggles the focused row. On a curtain row ◀ ▶ choose Open / Stop / Close and OK presses it. Back closes the panel. Only on/off here — brightness, colour, target and modes stay in each device's own panel.
|
||||
**All off** turns off lights only, not climate.
|
||||
|
||||
HA: the area registry (`area_id`, `picture`) and entity registry for the room's entities; `light.turn_off` with `area_id` for All off; `light.toggle`, `cover.open_cover` / `stop_cover` / `close_cover`, `climate.turn_on` / `turn_off`; the area's temperature, humidity and CO₂ sensors.
|
||||
|
||||
## Part C — Quick reference
|
||||
|
||||
| Card | Tap OK | Hold OK | On the card |
|
||||
|---|---|---|---|
|
||||
| Light · on/off | On / off | — | No middle band |
|
||||
| Light · dimmable | On / off at last brightness | Brightness & presets | Brightness bar |
|
||||
| Light · colour | On / off at last colour | Brightness, white / colour, swatches | Bar in the live colour |
|
||||
| LED & TV lights | On / off | Colour, white, 6 pinned effects, All effects | Colour or effect strip |
|
||||
| Air conditioner | On / off in last mode | Target, mode, fan auto / manual, airflow | 24 h temperature graph |
|
||||
| Heating (valve, thermostat) | Heat / off | Target, mode, preset, sensor, settings | 24 h temperature graph; warnings in amber |
|
||||
| Curtain | Open · close · stop if moving | Window, Open / Stop / Close, presets | Mini window |
|
||||
| Switch, plug, lock | Toggle | — | None |
|
||||
| Weather | Opens the panel | Forecast panel (same as tap) | Forecast on 1×2 |
|
||||
| Media | Presses the focused button | Rewind / FF on ◀◀ ▶▶ · panel on ▶❚❚ | Own buttons, ▲ ▼ volume |
|
||||
| Room (Home overview) | Opens the room | Lights, curtains, climate on/off; All off | Room photo; lights, curtains, air quality |
|
||||
| Vacuum | Start if docked · dock if cleaning | Rooms, mode, routines, dock | Photo + mode and room, or battery and dock water |
|
||||
Reference in new issue
Block a user