Skip to content

Master-Bedroom Sitting-Area Lamp — Automations

Date: 2026-07-07 Ticket: #72 Status: Approved (design settled via brainstorm; device corrected to plug_2)

Context

switch.upstairs_hallway_plug_2 is a power-monitored ZHA smart plug (on/off only) that now physically powers a wall lamp in the master-bedroom sitting area.

Clean slate — plug_2 has no automations today. (The §11 "Upstairs Hallway" schedule and the §49 toggle button belong to a different plug, switch.upstairs_hallway_1 = Henry's Ramen Sign — do not touch those.) plug_2 is not in group.lights, so Good Night doesn't currently turn it off; the renderer's sleeping → off will (single-owner). plug_2 is referenced by homekit.yaml (exposed to Apple Home) and the Command dashboard (a power-monitoring card + a switch tile).

Goal

Four coordinated behaviors on the (on/off) sitting lamp, driven by one priority renderer (same pattern as script.night_lights_render) so they never fight over the plug: evening ambiance, wake-to-lamp, movie mode, and away presence-simulation. Plus rename the entity to match reality.

Step 0 — Rename the entity

Rename the switch entity id (ZHA, live registry — controller step, not a repo edit): switch.upstairs_hallway_plug_2switch.master_bedroom_sitting_lamp.

Update the repo references to the switch: - homekit.yaml — the whitelist entry (~line 48) and the entity_config key + its name: (~line 100 → name: Master Bedroom Sitting Lamp). - lovelace/home_command_dashboard.json — the switch tile entity ref (~line 857). Storage-mode dashboard: pull fresh first (user also edits it in the UI), edit, deploy via deploy-lovelace.

Scope: rename the switch only. Leave the diagnostic sensors (sensor.upstairs_hallway_plug_2_power/_voltage/_summation_delivered/_lqi/…) as-is — this preserves InfluxDB energy history and keeps the dashboard's power-monitoring card working (those tiles reference the sensor ids, which don't change). The card keeps its "Upstairs Hallway Plug 2" label (cosmetic; relabel later if desired).

Apple Home caveat (accepted): renaming a HomeKit-bridged entity makes the bridge drop and re-add the accessory, so it reappears in the Apple Home app as a new device — re-assign its room/name there once after deploy.

Because the config references the new id before the live registry has it, add switch.master_bedroom_sitting_lamp to tests/fixtures/entities_allow.txt (with a #-comment); fold into entities.txt via make snapshot after deploy.

Component A — script.master_bedroom_sitting_lamp_render (the brain)

Single renderer that decides on/off from a priority stack (top wins), via a choose: whose conditions are evaluated in order (first match wins) — mirrors script.night_lights_render.

1. away  (zone.home count == 0)                                 -> STOP (yield; away-sim owns lamp)
2. waking (input_boolean.morning_armed on) AND dark              -> switch.turn_on  (outranks sleeping)
3. sleeping (input_boolean.sleeping on)                          -> switch.turn_off
4. movie (master_bedroom_apple_tv playing OR bedroom_tv on)      -> switch.turn_off
5. occupied (bedroom_occupancy on) AND dark AND time 16:00-02:00 -> switch.turn_on  (evening ambiance)
default                                                          -> switch.turn_off

dark = sun.sun is below_horizon. The away branch uses a stop: action (yield). The 20-min "empty" delay is not here — it lives in the occupancy trigger's for: (Component B), so the renderer reads binary_sensor.bedroom_occupancy directly. mode: restart.

Wake-to-lamp lives here (priority 2), triggered by input_boolean.morning_armed → on — the moment the phone comes off the charger and arms Good Morning, while you're still in the bedroom (before the kitchen-motion stage). It outranks sleeping (still on at arm time).

Morning-off is the kitchen-motion moment. When you reach the kitchen, its NL2 motion fires Good Morning, which clears morning_armed and sleeping. morning_armed→off re-runs the renderer (Component B trigger): priority 2 is now false, so the lamp drops — and it stays off because the Evening rule (priority 5) is time-gated to 16:00–02:00, excluding the early-morning wake window. This gate is essential: a partner still asleep in bed keeps bedroom_occupancy on, so without the time gate the Evening rule would re-light the lamp at 5 AM after Good Morning cleared sleeping. With it, once you're downstairs making coffee the bedroom goes dark for the sleeping partner. The dark gate on wake also keeps it from lighting in summer daylight.

Component B — automation: master_bedroom_sitting_lamp_render_triggers

One automation, many triggers, one action (script.master_bedroom_sitting_lamp_render), mode: restart. Triggers: - input_boolean.morning_armed (any state change) - input_boolean.sleeping (any state change) - binary_sensor.bedroom_occupancyon (immediate) - binary_sensor.bedroom_occupancyoff for 00:20:00 (the empty-delay) - sun.sunbelow_horizon and → above_horizon (the two real transitions — not a bare trigger, which would fire on every elevation attribute update) - media_player.master_bedroom_apple_tv and media_player.bedroom_tv (state change — movie) - zone.home (state change — returning home re-renders and takes the lamp back from the sim)

Component C — Away presence-simulation

  • automation: master_bedroom_sitting_lamp_away_simtime_pattern every 30 min; conditions away AND sun below_horizon AND now < 23:00; action: if [true,false]|random then turn_on else turn_off. Randomized evening presence.
  • automation: master_bedroom_sitting_lamp_away_off — at 23:00, if away, switch.turn_off (so it doesn't sit on overnight). Return-home re-render is Component B's zone.home trigger.

The renderer yields while away (priority 1 → stop), so sim and renderer never fight: sim owns the lamp when away, renderer when home.

Known limitations

  • On/off only (plain bulb) — no dimming/circadian.
  • Manual override is soft: a manual toggle (Apple Home/app) sticks only until the next render trigger fires; since the renderer fires on state changes, a manual off while sitting still (stable occupancy) persists until a real event (sun/TV/sleep/leave). Acceptable.
  • Presence-sim is a fixed 30-min cadence.

Testing

  • Entity-ref (Tier 3): driving entities exist; switch.master_bedroom_sitting_lamp goes in entities_allow.txt until make snapshot post-deploy.
  • New structural test tests/test_sitting_lamp.py: the 3 new automations + the render script exist; the render script and triggers reference switch.master_bedroom_sitting_lamp. (No assertion about §11 — those belong to a different plug and are untouched.)
  • Unique automation id/alias; make test green; Tier-1 check_config in CI validates load.
  • Manual post-deploy: morning_armed→on (dark); evening occupancy on/off (20-min); movie off/on; away-sim toggling; Good Night → off (via renderer).

Docs

  • CLAUDE.md — add a "Master Bedroom Sitting Lamp" automation entry + the entity rename note (plug_2 → sitting_lamp). Do not change the §11 Upstairs Hallway entry (different plug).
  • docs/automations.md — new section for the renderer + triggers + away-sim.
  • docs/lighting.md — household-facing description.
  • projects/smart_lighting_scenes.md — mark the away-simulation backlog item first implemented here.

Out of scope

  • The §11 hallway schedule / §49 toggle / group.lights (all belong to switch.upstairs_hallway_1).
  • Dimming / smart-bulb / color; renaming the diagnostic sensors; relabeling the dashboard power card.
  • Extending presence-sim to other lights.

Acceptance criteria

  • [ ] switch.upstairs_hallway_plug_2 renamed to switch.master_bedroom_sitting_lamp; homekit.yaml (whitelist + name) and the dashboard switch tile updated; allowlisted until snapshot.
  • [ ] script.master_bedroom_sitting_lamp_render implements the priority stack (away→stop, waking&dark→on, sleeping→off, movie→off, occupied&dark&time-16:00–02:00→on, else off).
  • [ ] Trigger automation calls the renderer on all listed events; 20-min empty delay via for:.
  • [ ] Wake-to-lamp fires on input_boolean.morning_armed→on (dark), outranking sleeping.
  • [ ] Morning-off: when Good Morning fires (morning_armed→off at kitchen motion), the lamp turns off and stays off with a partner still in bed — the Evening rule's 16:00–02:00 gate prevents a 5 AM re-light.
  • [ ] Movie mode: lamp off while bedroom TV/Apple TV playing, re-renders when it stops.
  • [ ] Away presence-sim toggles when away+dark+<23:00; off at 23:00 away; hands back on return.
  • [ ] §11 / §49 / group.lights untouched (different plug).
  • [ ] make test passes; docs (CLAUDE.md, automations.md, lighting.md, smart_lighting_scenes.md) updated.