Add window rooms template
This commit is contained in:
@@ -87,7 +87,11 @@ action:
|
|||||||
occupied: "{{ is_state(occupancy_entity, 'on') }}"
|
occupied: "{{ is_state(occupancy_entity, 'on') }}"
|
||||||
|
|
||||||
- choose:
|
- choose:
|
||||||
# Case 1: Manual physical switch flipped
|
# Case 1: Manual physical switch flipped (either direction).
|
||||||
|
# The Shelly's edge input mode has already flipped the relay locally -
|
||||||
|
# HA must NOT issue a light.turn_on/off here, or it will fight the
|
||||||
|
# person's manual action. We only start the override timer so that
|
||||||
|
# occupancy/lux logic stays out of the way for the configured window.
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ trigger.id == 'manual_switch' }}"
|
value_template: "{{ trigger.id == 'manual_switch' }}"
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
blueprint:
|
||||||
|
name: Occupancy Lighting with Manual Override (Window Rooms)
|
||||||
|
description: >
|
||||||
|
Turns lights on when an occupancy group sensor indicates presence AND
|
||||||
|
the room is dark enough (lux below threshold). Turns lights off when
|
||||||
|
the group becomes inactive for the configured delay.
|
||||||
|
|
||||||
|
A physical switch toggle suppresses sensor-based automation for a
|
||||||
|
configurable period using a timer helper. This automation never
|
||||||
|
commands the light directly in response to the switch - it assumes
|
||||||
|
your switch/relay (e.g. a Shelly in edge/detached input mode) already
|
||||||
|
controls the light locally and instantly, independent of Home
|
||||||
|
Assistant. HA only watches for the switch event to start the override
|
||||||
|
window, so it never fights a manual on/off.
|
||||||
|
|
||||||
|
Create a 'Binary Sensor Group' helper for your room's occupancy
|
||||||
|
sensors, a 'Sensor Group' helper (mean or min) for your room's lux
|
||||||
|
sensors if you have more than one, and one timer helper per room.
|
||||||
|
domain: automation
|
||||||
|
input:
|
||||||
|
light_target:
|
||||||
|
name: Light
|
||||||
|
selector:
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
domain: light
|
||||||
|
|
||||||
|
occupancy_group:
|
||||||
|
name: Occupancy Sensor / Group
|
||||||
|
description: Select a single binary sensor or a Binary Sensor Group helper containing this room's sensors.
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: binary_sensor
|
||||||
|
|
||||||
|
illuminance_sensor:
|
||||||
|
name: Illuminance Sensor / Group
|
||||||
|
description: Select a lux sensor (e.g. Apollo R-Pro1 LTR390) or a Sensor Group helper averaging multiple lux sensors in this room.
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: sensor
|
||||||
|
device_class: illuminance
|
||||||
|
|
||||||
|
illuminance_threshold:
|
||||||
|
name: Darkness threshold (lux)
|
||||||
|
description: Lights will only turn on for occupancy if measured lux is below this value. Typical indoor daylight near a window is 300-1000+ lux; a dim room is under 50 lux. Tune to taste.
|
||||||
|
default: 50
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 2000
|
||||||
|
step: 1
|
||||||
|
mode: box
|
||||||
|
unit_of_measurement: lux
|
||||||
|
|
||||||
|
switch_input:
|
||||||
|
name: Physical switch input
|
||||||
|
description: >
|
||||||
|
Select the switch/relay's INPUT entity (e.g. a Shelly's input
|
||||||
|
binary_sensor reporting the physical toggle), NOT the light entity
|
||||||
|
itself and not a mirror of the light's on/off state. If this is
|
||||||
|
wired to something that also changes state whenever this
|
||||||
|
automation calls light.turn_on/off, you'll get a feedback loop
|
||||||
|
where the automation's own actions look like manual switch events.
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: binary_sensor
|
||||||
|
|
||||||
|
override_timer:
|
||||||
|
name: Override timer
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: timer
|
||||||
|
|
||||||
|
override_duration:
|
||||||
|
name: Override duration (minutes)
|
||||||
|
default: 30
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 1
|
||||||
|
max: 1440
|
||||||
|
step: 1
|
||||||
|
mode: box
|
||||||
|
unit_of_measurement: minutes
|
||||||
|
|
||||||
|
off_delay:
|
||||||
|
name: Off delay (seconds)
|
||||||
|
default: 5
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 300
|
||||||
|
step: 1
|
||||||
|
mode: box
|
||||||
|
unit_of_measurement: seconds
|
||||||
|
|
||||||
|
mode: restart
|
||||||
|
|
||||||
|
variables:
|
||||||
|
occupancy_entity: !input occupancy_group
|
||||||
|
illuminance_entity: !input illuminance_sensor
|
||||||
|
lux_threshold: !input illuminance_threshold
|
||||||
|
timer_entity: !input override_timer
|
||||||
|
duration_minutes: !input override_duration
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- id: occupancy_change
|
||||||
|
platform: state
|
||||||
|
entity_id: !input occupancy_group
|
||||||
|
|
||||||
|
- id: manual_switch
|
||||||
|
platform: state
|
||||||
|
entity_id: !input switch_input
|
||||||
|
|
||||||
|
- id: timer_finished
|
||||||
|
platform: event
|
||||||
|
event_type: timer.finished
|
||||||
|
event_data:
|
||||||
|
entity_id: !input override_timer
|
||||||
|
|
||||||
|
# Re-evaluate if it gets dark while someone is already sitting in the room
|
||||||
|
- id: illuminance_change
|
||||||
|
platform: state
|
||||||
|
entity_id: !input illuminance_sensor
|
||||||
|
for:
|
||||||
|
seconds: 10
|
||||||
|
|
||||||
|
action:
|
||||||
|
- variables:
|
||||||
|
override_active: "{{ is_state(timer_entity, 'active') }}"
|
||||||
|
occupied: "{{ is_state(occupancy_entity, 'on') }}"
|
||||||
|
is_dark: "{{ states(illuminance_entity) | float(9999) < lux_threshold }}"
|
||||||
|
|
||||||
|
- choose:
|
||||||
|
# Case 1: Manual physical switch flipped (either direction).
|
||||||
|
# The Shelly's edge input mode has already flipped the relay locally -
|
||||||
|
# HA must NOT issue a light.turn_on/off here, or it will fight the
|
||||||
|
# person's manual action. We only start the override timer so that
|
||||||
|
# occupancy/lux logic stays out of the way for the configured window.
|
||||||
|
- conditions:
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ trigger.id == 'manual_switch' }}"
|
||||||
|
sequence:
|
||||||
|
- action: timer.start
|
||||||
|
target:
|
||||||
|
entity_id: !input override_timer
|
||||||
|
data:
|
||||||
|
# We multiply by 60 because timer.start data maps natively to HH:MM:SS or raw seconds
|
||||||
|
duration: "{{ duration_minutes * 60 }}"
|
||||||
|
|
||||||
|
# Case 2: Occupancy or lux changed, but manual override is currently active (Do Nothing)
|
||||||
|
- conditions:
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ (trigger.id in ['occupancy_change', 'illuminance_change']) and override_active }}"
|
||||||
|
sequence: []
|
||||||
|
|
||||||
|
# Case 3: Occupancy detected, override NOT active, and room is dark enough
|
||||||
|
- conditions:
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ occupied and is_dark }}"
|
||||||
|
sequence:
|
||||||
|
- action: light.turn_on
|
||||||
|
target: !input light_target
|
||||||
|
|
||||||
|
# Default Case: Not occupied, or occupied-but-bright-enough, or timer finished -> sequence handles turning off
|
||||||
|
default:
|
||||||
|
- delay:
|
||||||
|
seconds: !input off_delay
|
||||||
|
- condition: template
|
||||||
|
value_template: >
|
||||||
|
{{
|
||||||
|
not is_state(timer_entity, 'active')
|
||||||
|
and (not is_state(occupancy_entity, 'on') or states(illuminance_entity) | float(9999) >= lux_threshold)
|
||||||
|
}}
|
||||||
|
- action: light.turn_off
|
||||||
|
target: !input light_target
|
||||||
|
|
||||||
Reference in New Issue
Block a user