From 5868658565ed7f9deb9ca371a73d7a9c01f64045 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sat, 30 May 2026 10:02:14 -0700 Subject: [PATCH] docs: document smart lighting control paths --- .../Automation/Gentle Wake Routine.md | 119 ++++++++++++++++++ .../Automation/Smart Home Lighting Control.md | 88 +++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Gentle Wake Routine.md create mode 100644 swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Smart Home Lighting Control.md diff --git a/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Gentle Wake Routine.md b/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Gentle Wake Routine.md new file mode 100644 index 0000000..1716df7 --- /dev/null +++ b/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Gentle Wake Routine.md @@ -0,0 +1,119 @@ +--- +title: Gentle Wake Routine +area: automation +tags: [automation, wake, smart-home, wiz, bluetooth, wonderboom, hermes-cron] +created: 2026-05-29 +updated: 2026-05-29 +status: active +related: [[Cron Jobs]], [[Service Catalog]], [[Architecture - Automation Flow]] +--- + +# Gentle Wake Routine + +Daily bedroom wake-up automation managed by Hermes cron. Goal: wake gently with a warm WiZ light ramp first, then low-volume music on the Wonderboom after the room has started brightening. + +## Current behavior + +### Weekdays + +| Time | Action | +|---|---| +| 06:30 | Bedroom WiZ bulb on, very warm, 3% | +| 06:40 | Ramp to 20% | +| 06:50 | Ramp to 55% | +| 07:00 | Start gentle ambient music on Wonderboom, low volume | +| 07:10 | Raise light to 85%, music slightly louder | +| 07:30 | Morning mode: brighter light, morning music profile | + +### Weekends + +Same pattern shifted later: + +| Time | Action | +|---|---| +| 08:30 | Bedroom WiZ bulb on, very warm, 3% | +| 08:40 | Ramp to 20% | +| 08:50 | Ramp to 55% | +| 09:00 | Start gentle ambient music on Wonderboom, low volume | +| 09:10 | Raise light to 85%, music slightly louder | +| 09:30 | Morning mode: brighter light, morning music profile | + +## Hardware / targets + +- Bedroom WiZ bulb: `192.168.153.234` +- Wonderboom 4 Bluetooth MAC: `68:59:32:F3:08:F8` +- Wonderboom PipeWire/Pulse sink: `bluez_output.68_59_32_F3_08_F8.1` +- Audio source: VLC via `day_mood_audio.py`, routed to the Wonderboom sink. + +## Scripts + +- Main controller: `~/.hermes/scripts/wake_gently.py` +- Quiet cron wrapper: `~/.hermes/scripts/wake_gently_quiet.sh` +- Light protocol: direct WiZ UDP `setPilot` to bedroom bulb; see [[Smart Home Lighting Control]] for the Home Assistant vs direct-LAN split. +- Audio backend: `~/.hermes/scripts/day_mood_audio.py --audio-sink bluez_output.68_59_32_F3_08_F8.1` +- Idempotence/state file: `~/.hermes/state/wake_gently.json` + +The script chooses the current step from the wall-clock offset relative to the configured wake time. Each named step runs once per date unless `--force` is used. + +## Active Hermes cron jobs + +| Job | Schedule | +|---|---| +| `weekday-gentle-wake-bedroom-wiz-wonderboom` | `30,40,50 6 * * 1-5` | +| `weekday-gentle-wake-music-and-morning` | `0,10,30 7 * * 1-5` | +| `weekend-gentle-wake-bedroom-wiz-wonderboom` | `30,40,50 8 * * 6,0` | +| `weekend-gentle-wake-music-and-morning` | `0,10,30 9 * * 6,0` | + +Healthy cron runs use the quiet wrapper and should be silent. Non-empty stdout means something needs attention. + +## Failure behavior + +- If the Wonderboom sink is already present, music starts there. +- If missing, the script tries `bluetoothctl connect 68:59:32:F3:08:F8`. +- If the Wonderboom still cannot be reached, the light step still runs and music is skipped with diagnostic output. +- If the bedroom bulb fails to respond to UDP, the cron run should produce an error. + +## Manual checks + +Dry-run weekday start: + +```bash +~/.hermes/scripts/wake_gently.py --dry-run --now '2026-06-01T06:30:00-07:00' +``` + +Dry-run music step: + +```bash +~/.hermes/scripts/wake_gently.py --dry-run --now '2026-06-01T07:00:00-07:00' +``` + +Run current step manually and print details: + +```bash +~/.hermes/scripts/wake_gently.py +``` + +Re-apply current step even if already marked done today: + +```bash +~/.hermes/scripts/wake_gently.py --force +``` + +Check Wonderboom sink: + +```bash +pactl list short sinks | grep bluez_output.68_59_32_F3_08_F8.1 +``` + +Stop owned VLC audio if needed: + +```bash +~/.hermes/scripts/day_mood_audio.py --stop --json +``` + +## Tuning notes + +- To change wake times, edit `wake_time_for()` in `~/.hermes/scripts/wake_gently.py` and update the four Hermes cron schedules to match. +- To change brightness/color temperature, edit the `STEPS` list in `wake_gently.py`. +- To change music, tune the profile/volume entries in `STEPS`, or update stream/profile mapping in `day_mood_audio.py`. +- The current setup intentionally uses Hermes/local Bluetooth because Home Assistant sees the phone only as sensors/device-tracker and has no `media_player` entity for the phone or Wonderboom. diff --git a/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Smart Home Lighting Control.md b/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Smart Home Lighting Control.md new file mode 100644 index 0000000..358713c --- /dev/null +++ b/swarm-common/obsidian-vault/will/will-shared-zap/Infrastructure/Automation/Smart Home Lighting Control.md @@ -0,0 +1,88 @@ +--- +tags: + - infrastructure + - smart-home + - home-assistant + - wiz +updated: 2026-05-30 +--- + +# Smart Home Lighting Control + +Will's light bulbs are Philips/WiZ bulbs. They are managed through **two control paths**: + +1. **Home Assistant** for the normal smart-home entity layer. +2. **Hermes local LAN scripts** for automation routines that need deterministic local control. + +## Home Assistant + +Home Assistant is reachable from Atlas/Hermes at `http://192.168.153.245:8080`. + +As of 2026-05-30, Home Assistant exposes these WiZ entities: + +| Purpose | Entity | Last checked state | +|---|---|---| +| Living room WiZ bulb | `light.wiz_rgbw_tunable_a601b8` | `off` | +| Living room effect speed | `number.wiz_rgbw_tunable_a601b8_effect_speed` | `unavailable` | +| Living room power sensor | `sensor.wiz_rgbw_tunable_a601b8_power` | `0.0` | +| Bedroom WiZ bulb | `light.wiz_rgbw_tunable_a6907c` | `unavailable` | +| Bedroom effect speed | `number.wiz_rgbw_tunable_a6907c_effect_speed` | `unavailable` | +| Bedroom power sensor | `sensor.wiz_rgbw_tunable_a6907c_power` | `unavailable` | + +The `unavailable` bedroom state usually means Home Assistant cannot currently reach that bulb or the bulb is powered off/offline. It does not mean the entity is missing. + +## Direct WiZ LAN control + +The bulbs also support local WiZ UDP control on port `38899`. Hermes scripts use direct UDP for some routines because it is local, fast, and does not depend on Home Assistant service-call availability. + +Known bulb IPs from the WiZ LAN setup: + +| Bulb | IP | MAC / suffix | Notes | +|---|---:|---|---| +| Living room | `192.168.153.85` | `98:77:d5:a6:01:b8` / `a601b8` | Home Assistant entity: `light.wiz_rgbw_tunable_a601b8` | +| Bedroom | `192.168.153.234` | `98:77:d5:a6:90:7c` / `a6907c` | Home Assistant entity: `light.wiz_rgbw_tunable_a6907c` | + +If direct commands fail, rediscover the bulbs before assuming the integration is broken; IPs may change unless DHCP reservations are present. + +## Automation ownership + +- [[Gentle Wake Routine]] uses direct WiZ UDP for the bedroom bulb and Hermes cron for scheduling. +- Weather/time adaptive lighting uses `~/.hermes/scripts/wiz_weather_lighting.py` and may also speak directly to the bulbs. +- Home Assistant remains the canonical visible smart-home layer for dashboards, state inspection, and service calls. + +## Quick checks + +Check Home Assistant WiZ entities: + +```bash +python - <<'PY' +import os, urllib.request, json +url = os.environ['HOME_ASSISTANT_URL'].rstrip('/') + '/api/states' +req = urllib.request.Request(url, headers={ + 'Authorization': 'Bearer ' + os.environ['HOME_ASSISTANT_TOKEN'], + 'Content-Type': 'application/json', +}) +with urllib.request.urlopen(req, timeout=10) as r: + states = json.load(r) +for ent in states: + eid = ent.get('entity_id', '') + if 'wiz' in eid.lower() or 'a601b8' in eid.lower() or 'a6907c' in eid.lower(): + print(eid, ent.get('state'), ent.get('attributes', {}).get('friendly_name')) +PY +``` + +Dry-run the Hermes lighting decision without changing bulbs: + +```bash +~/.hermes/scripts/wiz_weather_lighting.py --dry-run --json +``` + +Apply the current Hermes lighting policy once: + +```bash +~/.hermes/scripts/wiz_weather_lighting.py --json +``` + +## Operational note + +When asked “are we using Home Assistant for the bulbs?”, the accurate answer is: **yes, Home Assistant has WiZ entities for them, but Hermes also controls the bulbs directly over local WiZ UDP for selected automations.**