33This folder contains the ** actions blueprint** that pairs with WITB+ occupancy.
44
55Use this when you already have room occupancy sensors from ` witb_plus/v4 ` (for example
6- ` binary_sensor.<slug>_occupied_effective ` ) and want reliable light/fan actions with safety tags.
6+ ` binary_sensor.<slug>_occupied_effective ` ) and want reliable light/fan actions with
7+ safety tags, external gating, and automatic tag cleanup.
78
89---
910
10- ## 1. Blueprint
11-
12- ** File:** ` witb_plus_actions_lights_fan.yaml `
13-
14- This blueprint controls:
15- - Lights (brightness profiles, optional sun/lux gating)
16- - Fan (` fan.* ` or ` switch.* ` )
17- - Vacancy off behavior with optional fan run-on
18- - Optional humidity hold (fan stays on while humidity remains high)
19- - Optional startup cleanup for auto-tagged entities
20-
21- It is intended to be used from the Home Assistant UI via ** Create Automation from Blueprint** .
11+ ## 1. Blueprints
12+
13+ ### ` witb_plus_actions_lights_fan.yaml ` — main actions blueprint (v2.3.1)
14+
15+ Controls lights and fan for a single room based on occupancy state changes from
16+ ` binary_sensor.<slug>_occupied_effective ` . Key behaviors:
17+
18+ - ** Lights ON/OFF** with day/night brightness profiles and optional soft-off dim warning.
19+ - ** Manual-off hold** — if you turn lights off while occupied they stay off until
20+ vacancy clears ` auto_tag_lights ` , then re-arm next occupancy.
21+ - ** Bed suppress** — if someone is in bed and lights are off, motion re-assertion
22+ (e.g. midnight bathroom return) does not turn lights back on.
23+ - ** Light gating** — wire an external ` binary_sensor ` computed from lux, sun
24+ elevation, curtains, or season. Blueprint does not evaluate these inline.
25+ - ** Fan ON on occupancy** with optional delay and night-disable mode.
26+ - ** Fan run-on timer** after vacancy, with optional gate to hold the fan on while
27+ humidity or other conditions require it.
28+ - ** Fan vacancy gate** — wire an external ` binary_sensor ` (e.g. humidity threshold).
29+ OFF = hold fan on; ON = ok to turn off. When the gate clears while the room is
30+ already vacant the fan turns off automatically.
31+ - ** Auto-tag helpers** (` input_boolean ` ) track automation ownership of lights and fan
32+ for safe "only turn off what we turned on" behavior.
33+ - ** Startup cleanup** with double-tap validation after HA restart.
34+
35+ ### ` witb_plus_actions_cleanup.yaml ` — tag cleanup blueprint (v1.0.0)
36+
37+ Belt-and-suspenders companion that catches ` auto_tag_lights ` and ` auto_tag_fan `
38+ helpers stuck ON after a ` mode:restart ` kill mid-sequence in the main automation.
39+ Deploy ** one instance per room** alongside the main Actions instance.
40+
41+ - Two independent soak timers fire after vacancy: lights check (default 5 min),
42+ fan check (default 20 min).
43+ - Lights tag only cleared when all controlled lights are confirmed OFF.
44+ - Fan tag never cleared while ` fan_runon_timer ` is active.
45+ - Both checks re-confirm vacancy at evaluation time.
46+ - Inputs mirror the main Actions instance — wire the same entities.
47+
48+ See ` CHANGELOG_witb_plus_actions_lights_fan.md ` for full fix rationale.
2249
2350---
2451
25- ## 2. Package Helpers (helpers only)
52+ ## 2. Package Helpers
2653
27- ** Reference template:** ` room_witb_actions_package_template .yaml`
54+ ** Reference template:** ` witb_plus_actions_lights_fan_package_template .yaml`
2855** Generated output location:** ` packages/ `
2956
3057Package files provide helper entities such as:
31- - ` input_boolean.<slug>_auto_lights_on `
32- - ` input_boolean.<slug>_auto_fan_on `
33- - ` timer.<slug>_actions_cooldown `
34- - ` timer.<slug>_fan_runon `
35- - ` input_datetime.<slug>_actions_night_start `
36- - ` input_datetime.<slug>_actions_night_end `
37- - Optional ` input_number ` tuning helpers (brightness, fan %, lux threshold, humidity thresholds, fan delay)
3858
39- Load these packages with:
59+ | Entity | Purpose |
60+ | ---| ---|
61+ | ` input_boolean.<slug>_auto_lights_on ` | Auto-tag for lights ownership |
62+ | ` input_boolean.<slug>_auto_fan_on ` | Auto-tag for fan ownership |
63+ | ` input_boolean.<slug>_keep_on ` | Blocking entity — prevents vacancy off |
64+ | ` timer.<slug>_actions_cooldown ` | ON-debounce cooldown timer |
65+ | ` timer.<slug>_actions_fan_runon ` | Fan run-on countdown timer |
66+ | ` input_datetime.<slug>_actions_night_start ` | Night window start |
67+ | ` input_datetime.<slug>_actions_night_end ` | Night window end |
68+ | ` input_number.<slug>_actions_brightness_day_pct ` | Day brightness % |
69+ | ` input_number.<slug>_actions_brightness_night_pct ` | Night brightness % |
70+ | ` input_number.<slug>_actions_fan_pct_day ` | Fan speed % day |
71+ | ` input_number.<slug>_actions_fan_pct_night ` | Fan speed % night |
72+ | ` input_number.<slug>_actions_fan_runon_minutes ` | Fan run-on duration |
73+ | ` input_number.<slug>_actions_fan_on_delay_seconds ` | Fan ON delay |
74+ | ` binary_sensor.<slug>_actions_cooldown_active ` | Cooldown active indicator |
75+ | ` binary_sensor.<slug>_actions_fan_runon_active ` | Fan run-on active indicator |
76+ | ` binary_sensor.<slug>_actions_in_night_window ` | Night window indicator |
77+
78+ Load packages with:
4079
4180``` yaml
4281homeassistant :
@@ -47,26 +86,22 @@ homeassistant:
4786
4887## 3. Generator Script
4988
50- **File:** ` generate_witb_plus_actions_packages_templated.py`
51-
52- The script generates helper package YAML files only.
53- It does **not** generate automations.
89+ **File:** ` generate_witb_packages_templated.py`
5490
55- Example :
91+ Generates per-room helper package YAML files from the template. Does **not**
92+ generate automations — those are created from blueprints in the HA UI.
5693
5794` ` ` bash
58- python3 generate_witb_plus_actions_packages_templated.py \
95+ # Generate packages for specific rooms
96+ python3 generate_witb_packages_templated.py \
5997 --rooms "Office" "Master Bathroom Toilet" \
60- --template room_witb_actions_package_template .yaml \
98+ --template witb_plus_actions_lights_fan_package_template .yaml \
6199 --out ./packages
62- ` ` `
63-
64- Dry run :
65100
66- ` ` ` bash
67- python3 generate_witb_plus_actions_packages_templated .py \
101+ # Dry run to preview output
102+ python3 generate_witb_packages_templated .py \
68103 --rooms "Office" \
69- --template room_witb_actions_package_template .yaml \
104+ --template witb_plus_actions_lights_fan_package_template .yaml \
70105 --out ./packages \
71106 --dry-run
72107` ` `
@@ -75,17 +110,53 @@ python3 generate_witb_plus_actions_packages_templated.py \
75110
76111# # 4. Typical Setup Flow
77112
78- 1. Create room occupancy with `witb_plus/v4`.
79- 2. Generate helpers into `packages/`.
80- 3. Reload/restart Home Assistant so helpers exist.
81- 4. Create an automation from `WITB+ Actions - Lights + Fan`.
82- 5. Bind `occupied_effective` to `binary_sensor.<slug>_occupied_effective`.
83- 6. Bind lights/fan entities and optional helper inputs.
113+ 1. Run `witb_plus/v4` blueprint for the room to get `binary_sensor.<slug>_occupied_effective`.
114+ 2. Generate helpers via the script and reload/restart HA so all helpers exist.
115+ 3. Create an automation from **WITB+ Actions - Lights + Fan** and wire :
116+ - ` occupied_effective` → `binary_sensor.<slug>_occupied_effective`
117+ - ` auto_tag_lights` → `input_boolean.<slug>_auto_lights_on`
118+ - ` auto_tag_fan` → `input_boolean.<slug>_auto_fan_on`
119+ - ` cooldown_timer` → `timer.<slug>_actions_cooldown`
120+ - ` fan_runon_timer` → `timer.<slug>_actions_fan_runon`
121+ - ` night_start_helper` / `night_end_helper` → corresponding `input_datetime` helpers
122+ - Brightness and fan % helpers → corresponding `input_number` helpers
123+ - ` light_gating_entity` → your external lux/sun gate sensor (optional)
124+ - ` fan_vacancy_gate_entity` → your external humidity gate sensor (optional)
125+ 4. Create a second automation from **WITB+ Actions Tag Cleanup** for the same room,
126+ wiring the same lights, fan, tags, and timers. Use `mode : single`.
127+ 5. Verify in Developer Tools → Template that the `occupied_effective` sensor
128+ transitions correctly before testing lights/fan behavior.
129+
130+ ---
131+
132+ # # 5. Architecture Notes
133+
134+ **Why two blueprints (occupancy + actions)?**
135+ WITB+ deliberately separates *occupancy inference* (WITB+ v4) from *action
136+ orchestration* (Actions). This allows multiple action automations to subscribe
137+ to the same occupancy sensor independently, and keeps each blueprint focused on
138+ one concern.
139+
140+ **Why external gating (v2.3.0+)?**
141+ Lux evaluation and humidity hold logic were removed from the Actions blueprint
142+ in v2.3.0. These belong in dedicated automations that write their verdict to a
143+ binary sensor. This keeps Actions simple and testable — you can force the gate
144+ ON/OFF manually in the UI to test lighting behavior independently of ambient
145+ conditions.
146+
147+ **Why a cleanup blueprint (v2.3.1+)?**
148+ ` mode:restart` is the correct mode for an event-driven automation — it prevents
149+ stale queued runs from accumulating. The tradeoff is that any run killed mid-
150+ sequence cannot clean up after itself. The cleanup blueprint handles this with a
151+ time-delayed soak check that is safe, idempotent, and never turns anything off —
152+ it only clears boolean tags.
84153
85154---
86155
87156# # Summary
88157
89- - **WITB+ v4** handles occupancy inference.
90- - **WITB+ Actions** handles light/fan behavior.
91- - **Package files** provide helper entities for safe automation behavior and dashboard tuning.
158+ | Blueprint | Role | Instance count |
159+ |---|---|---|
160+ | `witb_plus/v4` | Occupancy inference | One per room |
161+ | `witb_plus_actions_lights_fan` | Light + fan control | One per room |
162+ | `witb_plus_actions_cleanup` | Tag stuck-ON recovery | One per room |
0 commit comments