mikes-motion-activated-scenes/motion-activated-light.yaml

549 lines
17 KiB
YAML
Raw Normal View History

2023-07-28 20:29:37 -07:00
########################
### Blueprint definition
########################
2023-12-08 17:26:27 -08:00
mode: queued
max: 10
2023-07-28 20:29:37 -07:00
blueprint:
2023-11-15 05:54:36 -08:00
name: "Mike's Motion Activated Light"
2023-07-28 20:29:37 -07:00
description: "Turn lights on or off based on motion, plus an increasing delay when motion is continuously detected."
domain: automation
input:
motion_sensor:
name: "Motion Sensor"
description: "Entity ID of the motion sensor"
2023-07-28 20:29:37 -07:00
selector:
entity:
domain: binary_sensor
# for some reason, using a device_class of motion_sensor ends up hiding the actual motion sensors
# device_class: motion_sensor
2023-07-28 20:29:37 -07:00
delay_seconds_helper:
name: "Delay seconds (helper)"
description: "The delay before the motion-off sequence will be initiated. Must be a helper so it can persist across activations."
2023-07-28 20:29:37 -07:00
selector:
entity:
domain: input_number
2023-07-28 20:29:37 -07:00
delay_seconds_default:
name: "Default delay seconds"
description: "The default delay before the motion-off sequence begins. Will be used to reset the running delay."
2023-07-28 20:29:37 -07:00
default: 30
selector:
number:
min: 1
max: 86400
step: 1
mode: box
2023-11-15 05:00:36 -08:00
delay_seconds_multiplier:
name: "Delay seconds multiplier"
description: "When the off sequence gets interrupted by new motion, multiply the delay seconds by this number. A decent value might be 2."
default: 2.0
selector:
number:
min: 1.0
max: 1000.0
step: 0.1
2023-11-15 05:00:36 -08:00
mode: box
delay_seconds_max:
name: "Maximum delay seconds"
description: "The maximum delay during no motion before the motion-off sequence begins."
default: 3600
selector:
number:
min: 5
max: 3000000
step: 1
mode: box
2023-07-28 20:29:37 -07:00
notice_seconds:
name: "Notice seconds"
2023-07-28 20:29:37 -07:00
description: "The number of seconds to wait in the Prep1 (Notice) scene."
default: 15
selector:
number:
min: 1
max: 86400
step: 1
mode: box
2023-07-28 20:29:37 -07:00
warning_seconds:
name: "Warning seconds"
2023-07-28 20:29:37 -07:00
description: "The number of seconds to wait in the Prep2 (Warning) scene."
default: 15
selector:
number:
min: 1
max: 86400
step: 1
mode: box
2023-07-28 20:29:37 -07:00
scene_on:
name: "On Scene"
description: "The scene to activate when motion is detected"
2023-07-28 20:29:37 -07:00
selector:
entity:
domain: scene
2023-07-28 20:29:37 -07:00
scene_off_prep_1:
name: "Off Prep Scene 1 (Notice)"
description: "The first scene to activate when motion is no longer detected (notice phase)."
2023-07-28 20:29:37 -07:00
selector:
entity:
domain: scene
2023-07-28 20:29:37 -07:00
scene_off_prep_2:
name: "Off Prep Scene 2 (Warning)"
description: "The second scene to activate when motion is no longer detected (warning phase)."
2023-07-28 20:29:37 -07:00
selector:
entity:
domain: scene
2023-07-28 20:29:37 -07:00
scene_off:
name: "Off Scene"
2023-07-28 20:29:37 -07:00
description: "The scene to activate when the user has failed to produce motion, and the light should be considered \"off\"."
selector:
entity:
domain: scene
2023-11-15 05:00:36 -08:00
on_just_before_off_seconds:
name: "\"On\" just before \"Off\""
description: >
When the "Off" scene is about to be shown, you may wish to quickly show the "On" scene for a number of seconds just before.
This is sometimes helpful to mitigate an issue where the "On" scene doesn't apply all colors and settings correctly from an "Off" state.
Set this to a value greater than 0 to enable.
A value of 0 will disable this feature.
Note that sometimes, a value that is too short (e.g., 1) may also cause issues.
default: 1
selector:
2023-11-15 05:00:36 -08:00
number:
min: 1
max: 86400
step: 1
mode: box
enabled_helper:
name: "Enabled helper"
description: >
Helper variable that will control whether motion activation is enabled or disabled.
This will allow this blueprint to correctly select the "On" or "Off" scene, based on whether motion is currently detected when disabled.
An example would be a "Toggle" helper.
default: # Allows no selection
selector:
entity:
domain: input_boolean
2023-11-15 05:00:36 -08:00
debug_mode:
name: "Debug mode."
description: "Enable debug mode, which increases logging."
default: false
2023-11-15 05:00:36 -08:00
selector:
boolean: {}
#############
### Variables
#############
2023-07-28 20:29:37 -07:00
variables:
2023-11-15 05:00:36 -08:00
motion_sensor: !input motion_sensor
delay_seconds_helper: !input delay_seconds_helper
2023-11-15 05:00:36 -08:00
delay_seconds_default: !input delay_seconds_default
delay_seconds_multiplier: !input delay_seconds_multiplier
delay_seconds_max: !input delay_seconds_max
notice_seconds: !input notice_seconds
warning_seconds: !input warning_seconds
on_just_before_off_seconds: !input on_just_before_off_seconds
enabled_helper: !input enabled_helper
2023-11-15 05:00:36 -08:00
debug_mode: !input debug_mode
2023-07-28 20:29:37 -07:00
trigger_variables:
enabled_helper: !input enabled_helper
############
### Triggers
############
2023-07-28 20:29:37 -07:00
trigger:
- platform: state
id: Motion changed
2023-07-28 20:29:37 -07:00
entity_id:
- !input motion_sensor
to:
- "on"
- "off"
- platform: template
id: "Enabled helper is on"
value_template: "{{ (enabled_helper != None) and is_state( enabled_helper, 'on' ) }}"
- platform: template
id: "Enabled helper is off"
value_template: "{{ (enabled_helper != None) and is_state( enabled_helper, 'off' ) }}"
###########
### Actions
###########
2023-07-28 20:29:37 -07:00
action:
- alias: "Debug log whether the enabled_helper was set"
if:
- condition: template
value_template: "{{ debug_mode == true or true }}"
then:
- if:
- condition: template
value_template: "{{ not enabled_helper == None }}"
then:
- service: logbook.log
data:
name: "Enabled helper"
message: "Enabled helper is: {{ enabled_helper }}"
else:
- service: logbook.log
data:
name: "Enabled helper"
message: "Enabled helper is not set."
- alias: "Debug log the enabled_helper name"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Enabled helper"
message: "Enabled helper name is: {{ enabled_helper }}"
- alias: "Debug log the current delay_seconds value"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Delay seconds"
message: "Delay seconds is: {{ states[delay_seconds_helper].state }}"
2023-07-28 20:29:37 -07:00
2023-11-15 05:00:36 -08:00
- alias: "Debug log the on_just_before_off_seconds value"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
service: logbook.log
data:
name: "Debug: On just before off seconds"
message: "On just before off is: {{ on_just_before_off_seconds }} "
# Take actions based on whether the "Enabled helper" was just toggled on or off
2023-07-28 20:29:37 -07:00
- if:
- condition: trigger
id:
- Enabled helper is on
- Enabled helper is off
then:
# Debug log
- alias: "Debug log"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Debug: Trigger"
message: "Enabled helper was toggled, and has triggered this automation"
# Activate the "On" scene, if motion is currently detected
- alias: "Activate ON scene, if motion is currently detected, otherwise activate the OFF scene"
if:
- condition: state
entity_id: !input motion_sensor
state: "on"
then:
- parallel:
- alias: "Activate the ON scene"
service: scene.turn_on
target:
entity_id: !input scene_on
else:
- parallel:
- alias: "Activate the OFF scene"
service: scene.turn_on
target:
entity_id: !input scene_off
- stop: "Done handling enabled helper"
# Take actions based on whether Motion is detected
- alias: "Refuse to do anything if the enabled-helper says we're OFF."
if:
- condition: template
value_template: "{{ enabled_helper != None }}"
- condition: template
value_template: "{{ not is_state( enabled_helper, 'on' ) }}"
then:
stop: "Refusing to continue because the enabled-helper is OFF."
- if:
- condition: state
entity_id: !input motion_sensor
state: "on"
2023-07-28 20:29:37 -07:00
# Motion is detected
2023-07-28 20:29:37 -07:00
then:
- alias: "Log that motion was detected."
2023-07-28 20:29:37 -07:00
service: logbook.log
data:
name: "Motion On"
message: "Motion was detected."
2023-07-28 20:29:37 -07:00
- parallel:
- alias: "Activate the ON scene"
service: scene.turn_on
target:
entity_id: !input scene_on
2023-07-28 20:29:37 -07:00
# Motion is not detected
2023-07-28 20:29:37 -07:00
else:
- alias: "Log that the motion-off sequence will run, due to motion no longer detected."
2023-07-28 20:29:37 -07:00
service: logbook.log
data:
name: "Motion Off"
message: "Initiating motion-off sequence, because motion no longer detected."
2023-07-28 20:29:37 -07:00
2023-11-15 05:00:36 -08:00
# Initial period where nothing happens
- alias: "Delay appropriately before doing anything"
wait_template: "{{ states[motion_sensor].state == 'on' }}"
timeout: "{{ states[delay_seconds_helper].state }}"
2023-07-28 20:29:37 -07:00
- if:
- condition: state
entity_id: !input motion_sensor
state: "on"
then:
- stop: "Motion detected again during initial delay."
- alias: "Log that the initial delay has finished."
service: logbook.log
2023-07-28 20:29:37 -07:00
data:
name: "Motion Off"
message: "Finished initial no-motion delay"
2023-07-28 20:29:37 -07:00
# Notice period, where the notice scene is shown
- alias: "Log that the notice period has begun."
service: logbook.log
data:
name: "Begin notice period"
message: "Begin notice period; Waiting while motion is still off."
- parallel:
- alias: "Activate Scene: Off Prep 1 (Notice)"
service: scene.turn_on
target:
entity_id: !input scene_off_prep_1
2023-07-28 20:29:37 -07:00
- alias: "Delay during the notice period"
wait_template: "{{ states[motion_sensor].state == 'on' }}"
timeout: "{{ notice_seconds }}"
2023-07-28 20:29:37 -07:00
- if:
- condition: state
entity_id: !input motion_sensor
state: "on"
then:
- parallel:
- alias: "Activate Scene: On"
service: scene.turn_on
target:
entity_id: !input scene_on
2023-11-15 05:00:36 -08:00
- alias: "Increase countdown timer when user interrupts the notice period."
2023-07-28 20:29:37 -07:00
service: input_number.set_value
data:
entity_id: !input delay_seconds_helper
value: "{{ states[delay_seconds_helper].state | int * delay_seconds_multiplier }}"
- alias: "Limit delay seconds to its defined maximum"
if:
- condition: template
value_template: "{{ states[delay_seconds_helper].state | int > delay_seconds_max | int }}"
then:
- service: input_number.set_value
data:
entity_id: !input delay_seconds_helper
value: "{{ delay_seconds_max | int }}"
- if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Limiting delay seconds"
message: "Delay limited to max: {{ states[delay_seconds_helper].state }}"
2023-11-15 05:00:36 -08:00
- alias: "Log new delay"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "New delay"
message: "New delay is {{ states[delay_seconds_helper].state }} seconds"
2023-07-28 20:29:37 -07:00
- stop: "Motion detected during notice period."
- service: logbook.log
data:
name: "Notice period finished."
message: "Notice period has finished (motion is still off)."
2023-07-28 20:29:37 -07:00
# Warning period, just before the light turns off. The warning scene is shown.
- alias: "Log that the warning period has begun."
service: logbook.log
data:
name: "Begin warning period"
message: "Begin warning period; Waiting while motion is still off."
- parallel:
- alias: "Activate Scene: Off Prep 2 (Warning)"
service: scene.turn_on
target:
entity_id: !input scene_off_prep_2
2023-07-28 20:29:37 -07:00
- alias: "Delay during the warning period"
wait_template: "{{ states[motion_sensor].state == 'on' }}"
timeout: "{{ warning_seconds }}"
2023-07-28 20:29:37 -07:00
- if:
- condition: state
entity_id: !input motion_sensor
state: "on"
then:
- parallel:
- alias: "Activate Scene: On"
service: scene.turn_on
target:
entity_id: !input scene_on
2023-07-28 20:29:37 -07:00
- alias: "Double countdown timer when user interrupts the warning period."
service: input_number.set_value
data:
entity_id: !input delay_seconds_helper
value: "{{ states[delay_seconds_helper].state | int * delay_seconds_multiplier }}"
- alias: "Limit delay seconds to its defined maximum"
if:
- condition: template
value_template: "{{ states[delay_seconds_helper].state | int > delay_seconds_max | int }}"
then:
- service: input_number.set_value
data:
entity_id: !input delay_seconds_helper
value: "{{ delay_seconds_max | int }}"
- if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Limiting delay seconds"
message: "Delay limited to max: {{ states[delay_seconds_helper].state }}"
2023-11-15 05:00:36 -08:00
- alias: "Log new delay seconds"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "New delay seconds"
message: "New delay is {{ states[delay_seconds_helper].state }} seconds."
2023-07-28 20:29:37 -07:00
- stop: "Motion detected during the warning period."
- service: logbook.log
data:
name: "Warning period finished."
message: "Warning period has finished and motion is still off."
2023-07-28 20:29:37 -07:00
# Finally, we decide to actually turn off the lights with the "Off" scene.
# Maybe turn on the "On" scene just before the "Off" scene, if the user enabled this option
- if:
- condition: template
2023-11-15 05:00:36 -08:00
value_template: "{{ on_just_before_off_seconds > 0 }}"
then:
2023-11-15 05:00:36 -08:00
- alias: "Log the number of on-before-off seconds"
if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
service: logbook.log
data:
name: "On-Before-Off seconds"
message: "Will turn on for {{ on_just_before_off_seconds }} seconds before off."
- service: scene.turn_on
target:
entity_id: !input scene_on
- alias: "Wait a second to set the \"On\" scene."
delay:
2023-11-15 05:00:36 -08:00
seconds: "{{ on_just_before_off_seconds }}"
else:
- if:
- condition: template
value_template: "{{ debug_mode == true }}"
then:
- service: logbook.log
data:
name: "Won't run on-before-off"
message: "Won't run on-before-off because seconds was less than 1"
- parallel:
- alias: "Activate Scene: Off (Done)"
service: scene.turn_on
target:
entity_id: !input scene_off
2023-07-28 20:29:37 -07:00
- alias: "Reset countdown timer after turning off lights."
2023-07-28 20:29:37 -07:00
service: input_number.set_value
data:
entity_id: !input delay_seconds_helper
value: "{{ delay_seconds_default }}"
- service: logbook.log
data:
name: "Turning off light, due to motion off."
message: "Activated off-scene and reset delay."
2023-07-28 20:29:37 -07:00