Office Lamp + Shared Ambiance Renderer — Design¶
Status: design approved 2026-07-10, pending implementation. Related: #74 (corner lamp renderer — refactored here),
projects/smart_lighting_scenes.md,docs/superpowers/specs/2026-07-10-corner-lamp-renderer-design.md.
1. Goal & guiding principle¶
Add the 3-head office lamp (light.office_lamp_bulb_1/2/3, H600B, LAN-controlled, each head washing a circle on the wall) as a pure ambiance fixture, and refactor the corner lamp (H607C) so both are twin ambiance lamps driven by one shared schedule.
Guiding principle (the reason for every decision below): ambiance lamps stay ambient; data lives on dedicated indicator bulbs. The two nice Govee lamps show only coordinated circadian + weather ambiance and safety alerts. All data/notifications live on the two cheap Sengled A19 bulbs — bulb_1 = TOU price (unchanged), bulb_2 = SOFI ticker (unchanged, §19).
Consequence: the SOFI ticker is removed from the corner lamp (it duplicated the Sengled §19). This simplifies #74 and makes the two Govee lamps identical twins, always in sync.
2. What "ambient" includes (and excludes)¶
- Includes: the shared circadian arc + mild-weather override, the severe-weather storm layer, and safety alerts (alarm / leak). Alerts are safety, not data — a whole lamp going red is a deliberately hard-to-miss cue and stays.
- Excludes: SOFI ticker, TOU, and any "is Lindsay home"-style status. None of that goes on either Govee lamp.
3. Architecture¶
sensor.ambiance_scene ───────────┐ (MASTER SCHEDULE: time block + mild weather → logical key)
binary_sensor.weather_is_severe ─┤ (shared severe-weather condition)
rest_command.govee_scene ────────┤ (generalized: device, scene_id, param_id)
├─→ script.corner_lamp_render (map→H607C ids, corner device)
└─→ script.office_lamp_render (map→H600B ids, 3 office devices)
Shared "master schedule" (edit these to tune BOTH lamps): - sensor.ambiance_scene — template sensor returning a logical scene key from the ET clock + weather.forecast_home. This is the single source of the circadian/weather policy. Values: morning · afternoon · twilight · night · starry_sky · raining · snowing · dense_fog. - binary_sensor.weather_is_severe — on when weather.forecast_home is lightning/lightning-rainy/pouring/hail/exceptional. - Both live in one package file (e.g. configuration_ambiance_addition.yaml, loaded via homeassistant.packages) — the file to tune the office ambiance.
Generalized scene command: refactor the device-hardcoded rest_command.govee_corner_lamp_scene into rest_command.govee_scene taking device, scene_id, param_id. The corner lamp passes its one device; the office renderer calls it once per bulb (3 device ids) to light all heads with the same scene.
What stays per-lamp (must — different SKUs): the logical-key → device scene id map, the manual flag, and the device id(s). The shared part is the policy; the hardware ids can't be.
4. Unified priority stack (both lamps — top wins)¶
The two renderers run the same stack. They differ only in device/scene-map/manual-flag.
| # | Condition | Result |
|---|---|---|
| 0 | manual (this lamp's own flag) | yield (stop, stamp token "manual") |
| 1 | alarm triggered | alert scene (per-SKU) |
| 2 | leak wet (binary_sensor.any_leak_wet) | alert scene (per-SKU) |
| 3 | movie mode: sun.sun below horizon and media_player.office_apple_tv in playing/paused | off |
| 4 | Louis away: person.louis ≠ home | off |
| 5 | asleep (input_boolean.sleeping) | off |
| 6 | severe weather (binary_sensor.weather_is_severe) | storm scene (per-SKU) |
| 7 | default | ambiance → sensor.ambiance_scene → this lamp's scene map |
- Alerts (1,2) sit above the off-gates so an alarm shows mid-movie or while away. Severe (6) sits below the off-gates so a movie/empty office isn't interrupted by a storm animation.
- On-at-wake / off-at-sleep is emergent: Good Night sets
sleeping→ §5 off; Good Morning clears it → §7 renders (= on). - No SOFI branch on either lamp — the previously-shipped corner §5 ticker is deleted.
5. sensor.ambiance_scene definition¶
Reproduces the corner lamp's shipped circadian logic (behavior-preserving) so its output is unchanged after the refactor:
- Time blocks (ET hour):
05–12 morning·12–17 afternoon·17–20 twilight·20–23 night·23–05 starry_sky. - Mild-weather override (replaces the time block):
rainy → raining,snowy/snowy-rainy → snowing,fog → dense_fog. Anything else → the time block. (Severe conditions are NOT here — they're handled by §6 viabinary_sensor.weather_is_severe.)
6. Corner lamp refactor (behavior-preserving except SOFI removal)¶
- Delete the shipped market-hours SOFI ticker branch and its
tmapticker scene map + the market-hours/freshness templates (this is the branch #74 shipped between "asleep" and "default"). - Default branch now reads
states('sensor.ambiance_scene')and maps the key via the existing H607C map (same ids, same result) — replaces the inlineblock/wx/smaptemplates. - Severe branch reads
binary_sensor.weather_is_severe(shared) instead of the inline condition. - Add movie-mode gate (§3) and switch presence to
person.louis(§4) — waszone.home == 0. rest_commandcall updated togovee_scenewith the corner device.- Net visible change: identical circadian/weather/alert behavior; SOFI gone; off when Louis is out (vs. everybody-out) and off during dark-Apple-TV.
7. Office lamp renderer (new)¶
script.office_lamp_render— the §4 stack, mapping to H600B scene ids, firing all 3 bulb devices per scene viarest_command.govee_scene(loop of 3). Power via the 3switch.office_lamp_bulb_*_power_switch.input_boolean.office_lamp_manual— one flag for all 3 heads; §0 yields all three.input_text.office_lamp_last_render— dedupe token (per lamp).automation.office_lamp_render_triggers— re-render onsensor.ambiance_scene,binary_sensor.weather_is_severe,media_player.office_apple_tv,person.louis,sun.sun,input_boolean.sleeping,input_boolean.office_lamp_manual,alarm_control_panel.blairmont_alarm,binary_sensor.any_leak_wet, HA start.- Two webhooks (
office_lamp_manualon /office_lamp_autooff), mirroring the corner lamp. script.wake_housegains: clearoffice_lamp_manual+ render the office lamp (mirroring its corner-lamp step).
8. Scene maps¶
- Corner (H607C): existing ids —
morning 9668/16543 · afternoon 9669/16544 · twilight 9670/16545 · night 9709/16584 · starry_sky 9707/16582 · raining 9706/16581 · snowing 9636/16511 · dense_fog 9651/16526; alert-alarm9690/16565(Breathe); alert-leak9695/16570(Dripping); storm9705/16580(Thunderstorm). - Office (H600B): ids are SKU-specific and fetched at implementation (H600B has 59 scenes; confirmed available: Forest
1175/1237, Fire3128/3278, Sunset Glow1173/1235, Starry Sky1174/1236, Aurora3125/3275, Rainbow3126/3276). Map the same 8 logical keys + 3 alert/storm scenes to the nearest H600B scenes; where the H607C scene name has no H600B equivalent, pick the closest so the two lamps read as coordinated (not pixel-identical). Device ids: bulb 107:F6:3C:DC:75:17:45:E8, bulb 2D2:06:3C:DC:75:14:FF:8C, bulb 38D:97:3C:DC:75:11:63:54.
9. Out of scope / unchanged¶
- TOU indicator (
automation.office_bulb_tou_coloron Sengledbulb_1) — untouched. - SOFI ticker (§19 on Sengled
bulb_2) — untouched; now the sole SOFI display. - Ticket #75 (retire Sengled §19) is reframed — the Sengled SOFI is now the intended home, so #75 should be closed/repurposed as part of this work.
10. Testing, deploy, docs¶
- Render-test live (
POST /api/templatewith real states) thesensor.ambiance_scenetemplate, the severe binary sensor, and the movie-mode/presence conditions before deploy — the #74 lesson thatcheck_configvalidates schema, not template execution ([[ha-template-runtime-gotchas]]). - New helpers/sensors →
entities_allow.txtpre-deploy, thenmake snapshot(also folds in the 12 bulb entities) → move toentities.txt. - Config touches
configuration.yaml/package +scripts.yaml+automations.yaml→ CI full restart. Scenes fire via the cloud Platform API (!secret govee_api_key, already on the box). - Docs: new office-lamp + shared-schedule section in
projects/smart_lighting_scenes.md, CLAUDE.md (new automation entry, Key Entities, the ambiance-schedule concept),docs/lighting.md,docs/automations.md; update the corner-lamp docs for the SOFI removal + shared-schedule refactor.
11. Open items / future¶
- H600B scene mapping finalized at implementation (fetch full list; pick nearest matches).
- Apple-TV "watching" state set — designed as
playing/paused; confirm against the live entity's actual state values during implementation (verifiedpausedin use). - Prettier data bulbs — giving the two Sengled TOU/SOFI dots a nicer fixture is a separate future task.
- Office presence sensor — when a real one is added, the presence gate can move from
person.louisto true office occupancy.