Skip to content

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_severeon 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.louishome off
5 asleep (input_boolean.sleeping) off
6 severe weather (binary_sensor.weather_is_severe) storm scene (per-SKU)
7 default ambiancesensor.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 via binary_sensor.weather_is_severe.)

6. Corner lamp refactor (behavior-preserving except SOFI removal)

  • Delete the shipped market-hours SOFI ticker branch and its tmap ticker 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 inline block/wx/smap templates.
  • 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) — was zone.home == 0.
  • rest_command call updated to govee_scene with 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 via rest_command.govee_scene (loop of 3). Power via the 3 switch.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 on sensor.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_manual on / office_lamp_auto off), mirroring the corner lamp.
  • script.wake_house gains: clear office_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-alarm 9690/16565 (Breathe); alert-leak 9695/16570 (Dripping); storm 9705/16580 (Thunderstorm).
  • Office (H600B): ids are SKU-specific and fetched at implementation (H600B has 59 scenes; confirmed available: Forest 1175/1237, Fire 3128/3278, Sunset Glow 1173/1235, Starry Sky 1174/1236, Aurora 3125/3275, Rainbow 3126/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 1 07:F6:3C:DC:75:17:45:E8, bulb 2 D2:06:3C:DC:75:14:FF:8C, bulb 3 8D:97:3C:DC:75:11:63:54.

9. Out of scope / unchanged

  • TOU indicator (automation.office_bulb_tou_color on Sengled bulb_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/template with real states) the sensor.ambiance_scene template, the severe binary sensor, and the movie-mode/presence conditions before deploy — the #74 lesson that check_config validates schema, not template execution ([[ha-template-runtime-gotchas]]).
  • New helpers/sensors → entities_allow.txt pre-deploy, then make snapshot (also folds in the 12 bulb entities) → move to entities.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 (verified paused in 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.louis to true office occupancy.