Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
832a71380f | ||
|
7626c05ad2 | ||
|
98849314e3 | ||
|
716cf3f1b1 | ||
|
b18f09094b | ||
|
fa6bb40bc5 | ||
|
d2e97b133b | ||
|
508e3e37e9 | ||
|
09c41900b2 | ||
|
0702a851ff | ||
|
2277d37989 | ||
|
82a3508b87 | ||
|
4615be6cee | ||
|
9daf98c604 | ||
|
76d8721a7c | ||
|
610acdc1c4 | ||
|
1771b154e0 | ||
|
65a542484d | ||
|
914b9f7449 | ||
|
467fcd30e3 | ||
|
2cab185ac6 | ||
|
19e6fbf577 | ||
|
3534adff19 | ||
|
0f41bf3f6a | ||
|
9b9d5a3466 | ||
|
aa187ac3a2 | ||
|
9f143ffb9a |
37
README.md
Normal file
37
README.md
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
# Mike's Motion Activated Scenes
|
||||
|
||||
by Mike Peralta
|
||||
|
||||
This is another "motion activated light" automation blueprint for [Home Assistant](https://www.home-assistant.io/).
|
||||
It uses scenes rather than toggling to allow for robust behavior and attempts to adjust its delay dynamically based on activity.
|
||||
|
||||
It features several stages after motion is no longer detected:
|
||||
|
||||
* Initial delay (nothing happens)
|
||||
|
||||
* Notice: Configurable scene + delay
|
||||
|
||||
* Warning: Configurable scene + delay
|
||||
|
||||
* Off
|
||||
|
||||
The initial delay starts off at a user configured number of seconds. Each time the user interrupts the off-sequence with motion,
|
||||
the delay gets multiplied by a user configured multiplier, with a user configurable limit.
|
||||
When the user allows the off-sequence to complete (the off-scene activates), the delay resets to the user configured baseline.
|
||||
This allows a room to stay on longer when there is frequent activity, but shorter when activity is infrequent.
|
||||
|
||||
The automation also obeys a toggle helper to enable/disable motion activation. The user can configure which scene to use when when disabled.
|
||||
|
||||
This automation can retry a scene multiple times in a row to help overcome buggy/slow networks or lights that fail to set brightness/color correctly when first turned on.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
By using this software you agree to the disclaimer.
|
||||
|
768
mikes-motion-activated-scenes.yaml
Normal file
768
mikes-motion-activated-scenes.yaml
Normal file
@ -0,0 +1,768 @@
|
||||
|
||||
|
||||
########################
|
||||
### Blueprint definition
|
||||
########################
|
||||
|
||||
mode: queued
|
||||
max: 25
|
||||
blueprint:
|
||||
|
||||
name: "Mike's Motion Activated Scenes"
|
||||
description: "Activate scenes based on motion with notice and warning phases, plus an increasing delay when motion is continuously detected."
|
||||
domain: automation
|
||||
input:
|
||||
|
||||
motion_sensor:
|
||||
name: "Motion Sensor"
|
||||
description: "Entity ID of the motion sensor"
|
||||
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
|
||||
|
||||
|
||||
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."
|
||||
selector:
|
||||
entity:
|
||||
domain: input_number
|
||||
|
||||
|
||||
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."
|
||||
default: 30
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
notice_seconds:
|
||||
name: "Notice seconds"
|
||||
description: "The number of seconds to wait in the Notice scene."
|
||||
default: 15
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
warning_seconds:
|
||||
name: "Warning seconds"
|
||||
description: "The number of seconds to wait in the Warning scene."
|
||||
default: 15
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
scene_on:
|
||||
name: "On Scene"
|
||||
description: "The scene to activate when motion is detected"
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_notice:
|
||||
name: "Notice Scene"
|
||||
description: "The first scene to activate when motion is no longer detected (notice phase)."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_warning:
|
||||
name: "Warning Scene"
|
||||
description: "The second scene to activate when motion is no longer detected (warning phase)."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_off:
|
||||
name: "Off Scene"
|
||||
description: "The scene to activate when the user has failed to produce motion, and the light should be considered \"off\"."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
scene_repeat_count:
|
||||
name: "Scene repeat/retry count"
|
||||
description: >
|
||||
When activating a scene, try this many times in a row.
|
||||
This is sometimes useful when the network seems buggy or laggy,
|
||||
or for certain lights that fail to correctly apply brightness/color when first turning on.
|
||||
|
||||
default: 1
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 60
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
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:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 0.1
|
||||
mode: box
|
||||
|
||||
|
||||
enabled_helper:
|
||||
name: "Enabled helper"
|
||||
description: >
|
||||
Helper variable that will control whether motion activation is enabled or disabled.
|
||||
This will allow the automation 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
|
||||
|
||||
|
||||
disabled_scene:
|
||||
name: "Disabled scene"
|
||||
description: >
|
||||
Choose the scene that will be activated when the "enabled_helper" is set to off.
|
||||
In the "auto" mode, the "on" or "off" scene will be chosen based on whether motion is currently detected.
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "auto"
|
||||
- "on"
|
||||
- "off"
|
||||
- "notice"
|
||||
- "warning"
|
||||
|
||||
|
||||
debug_mode:
|
||||
name: "Debug mode."
|
||||
description: "Enable debug mode, which increases logging."
|
||||
default: false
|
||||
selector:
|
||||
boolean: {}
|
||||
|
||||
|
||||
#############
|
||||
### Variables
|
||||
#############
|
||||
|
||||
variables:
|
||||
|
||||
motion_sensor: !input motion_sensor
|
||||
delay_seconds_helper: !input delay_seconds_helper
|
||||
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
|
||||
disabled_scene: !input disabled_scene
|
||||
debug_mode: !input debug_mode
|
||||
|
||||
scene_repeat_count: !input scene_repeat_count
|
||||
scene_repeat_delay_milliseconds: 500
|
||||
|
||||
trigger_variables:
|
||||
enabled_helper: !input enabled_helper
|
||||
|
||||
|
||||
############
|
||||
### Triggers
|
||||
############
|
||||
|
||||
trigger:
|
||||
|
||||
- platform: state
|
||||
id: Motion changed
|
||||
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
|
||||
###########
|
||||
|
||||
action:
|
||||
|
||||
# Action #0
|
||||
- alias: "Initial debug logging"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
|
||||
- alias: "Debug log whether the enabled_helper was set"
|
||||
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"
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Enabled helper"
|
||||
message: "Enabled helper name is: {{ enabled_helper }}"
|
||||
|
||||
- alias: "Debug log the current delay_seconds value"
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Delay seconds"
|
||||
message: "Delay seconds is: {{ states[delay_seconds_helper].state }}"
|
||||
|
||||
- alias: "Debug log the on_just_before_off_seconds value"
|
||||
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
|
||||
# Action #1
|
||||
- if:
|
||||
- condition: trigger
|
||||
id:
|
||||
- Enabled helper is on
|
||||
- Enabled helper is off
|
||||
then:
|
||||
|
||||
# Debug log
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
- alias: "Debug log that the enabled helper is toggled"
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Debug: Trigger"
|
||||
message: "Enabled helper was toggled, and has triggered this automation"
|
||||
- alias: "Debug log the disabled scene"
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Debug: Disabled scene"
|
||||
message: "Disabled scene is currently set to: {{ disabled_scene }}"
|
||||
|
||||
# If the enabled helper is OFF, we should start by resetting
|
||||
# the countdown timer to default
|
||||
- alias: "If the enabled helper is OFF, reset countdown timer to default"
|
||||
if:
|
||||
- condition: trigger
|
||||
id:
|
||||
- Enabled Helper is off
|
||||
then:
|
||||
- alias: "Reset countdown timer when enabled helper is switched OFF."
|
||||
service: input_number.set_value
|
||||
data:
|
||||
entity_id: !input delay_seconds_helper
|
||||
value: "{{ delay_seconds_default }}"
|
||||
|
||||
# In "auto" mode, activate the ON or OFF scene based on whether motion is currently detected
|
||||
# Also use "auto" mode if motion activation is ENABLED.
|
||||
- alias: "auto mode: Activate ON scene, if motion is currently detected, otherwise activate the OFF scene"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ disabled_scene == 'auto' or (enabled_helper != None and is_state( enabled_helper, 'on' )) }}"
|
||||
then:
|
||||
- if:
|
||||
- condition: state
|
||||
entity_id: !input motion_sensor
|
||||
state: "on"
|
||||
then:
|
||||
- alias: "Activate the ON scene"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
else:
|
||||
- alias: "Activate the OFF scene"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_off
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
- stop: "Enabled helper was on or auto mode was on; Determined scene to activate based on current motion."
|
||||
|
||||
# At this point, the enabled helper is assumed to be OFF
|
||||
|
||||
# In disabled_scene::ON mode, just activate the ON scene
|
||||
- alias: "disabled_scene::on mode: just activate the ON scene"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ disabled_scene == 'on' }}"
|
||||
then:
|
||||
- repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
- stop: "Enabled helper is off and disabled scene was ON; Set ON scene"
|
||||
|
||||
# In disabled_scene::OFF mode, just activate the OFF scene
|
||||
- alias: "disabled_scene::off mode: just activate the OFF scene"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ disabled_scene == 'off' }}"
|
||||
then:
|
||||
- repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_off
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
- stop: "Enabled helper is off and disabled scene was OFF; Set OFF scene"
|
||||
|
||||
# In disabled_scene::notice mode, just activate the NOTICE scene
|
||||
- alias: "disabled_scene::notice mode: just activate the NOTICE scene"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ disabled_scene == 'notice' }}"
|
||||
then:
|
||||
- repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_notice
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
- stop: "Enabled helper is off and disabled scene was NOTICE; Set NOTICE scene"
|
||||
|
||||
# In disabled_scene::warning mode, just activate the WARNING scene
|
||||
- alias: "disabed_scene::warning mode: just activate the WARNING scene"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ disabled_scene == 'warning' }}"
|
||||
then:
|
||||
- repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_warning
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
- stop: "Enabled helper is off and disabled scene was WATNING; Set WARNING scene"
|
||||
|
||||
# Don't do anything after processing the enabled_helper triggers
|
||||
- stop: "Done handling enabled helper"
|
||||
|
||||
|
||||
|
||||
|
||||
# Take actions based on whether Motion is detected
|
||||
# Action #2
|
||||
- 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"
|
||||
|
||||
|
||||
# Motion is detected
|
||||
then:
|
||||
|
||||
- alias: "Debug Log that motion was detected."
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Motion On"
|
||||
message: "Motion was detected."
|
||||
|
||||
- alias: "Activate the ON scene"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
|
||||
|
||||
# Motion is not detected
|
||||
else:
|
||||
|
||||
# Debug log
|
||||
- alias: "Debug Log that the motion-off sequence will run, due to motion no longer detected."
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Motion Off"
|
||||
message: "Initiating motion-off sequence, because motion no longer detected."
|
||||
|
||||
# Initial period where nothing happens
|
||||
- alias: "Delay appropriately before doing anything"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' or (enabled_helper != None and is_state(enabled_helper, 'off') ) }}"
|
||||
timeout: "{{ states[delay_seconds_helper].state }}"
|
||||
|
||||
- alias: "Quit now if the enabled-helper went OFF"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ enabled_helper != None }}"
|
||||
- condition: template
|
||||
value_template: "{{ is_state( enabled_helper, 'off' ) }}"
|
||||
then:
|
||||
stop: "Interrupted initial delay because the enabled helper turned OFF."
|
||||
|
||||
- alias: "Motion detected again during initial delay; Interrupt initial delay"
|
||||
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."
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Motion Off"
|
||||
message: "Finished initial no-motion delay"
|
||||
|
||||
|
||||
|
||||
# Notice period, where the notice scene is shown
|
||||
- alias: "Log that the notice period has begun."
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Begin notice period"
|
||||
message: "Begin notice period; Waiting while motion is still off."
|
||||
|
||||
- alias: "Activate Scene: Notice"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_notice
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
|
||||
- alias: "Delay during the notice period"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' or (enabled_helper != None and is_state('enabled_helper', 'off') ) }}"
|
||||
timeout: "{{ notice_seconds }}"
|
||||
|
||||
- alias: "Quit now if the enabled-helper went OFF"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ enabled_helper != None }}"
|
||||
- condition: template
|
||||
value_template: "{{ is_state( enabled_helper, 'off' ) }}"
|
||||
then:
|
||||
stop: "Interrupting NOTICE period because the enabled-helper went OFF."
|
||||
|
||||
|
||||
- alias: "If motion interrupted the NOTICE period, activate the ON scene"
|
||||
if:
|
||||
- condition: state
|
||||
entity_id: !input motion_sensor
|
||||
state: "on"
|
||||
then:
|
||||
|
||||
- alias: "Activate Scene: On"
|
||||
service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
|
||||
- alias: "Increase countdown timer when user interrupts the notice 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 }}"
|
||||
- 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"
|
||||
- stop: "Motion detected during notice period."
|
||||
- if:
|
||||
condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
- service: logbook.log
|
||||
data:
|
||||
name: "Notice period finished."
|
||||
message: "Notice period has finished (motion is still off)."
|
||||
|
||||
|
||||
# Warning period, just before the light turns off. The warning scene is shown.
|
||||
- alias: "Log that the warning period has begun."
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Begin warning period"
|
||||
message: "Begin warning period; Waiting while motion is still off."
|
||||
|
||||
- alias: "Activate Scene: Warning"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_warning
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
|
||||
- alias: "Delay during the warning period"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' or (enabled_helper != None and is_state('enabled_helper', 'off') ) }}"
|
||||
timeout: "{{ warning_seconds }}"
|
||||
|
||||
- alias: "Quit now if the enabled-helper went OFF"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ enabled_helper != None }}"
|
||||
- condition: template
|
||||
value_template: "{{ is_state( enabled_helper, 'off' ) }}"
|
||||
then:
|
||||
stop: "Interrupting the WARNING sequence because the enabled-helper went OFF."
|
||||
|
||||
- alias: "If motion interrupts the WARNING sequence, just activate the ON scene"
|
||||
if:
|
||||
- condition: state
|
||||
entity_id: !input motion_sensor
|
||||
state: "on"
|
||||
then:
|
||||
|
||||
- alias: "Activate Scene: On"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
|
||||
- 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 }}"
|
||||
|
||||
- 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."
|
||||
- stop: "Motion detected during the warning period."
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
- service: logbook.log
|
||||
data:
|
||||
name: "Warning period finished."
|
||||
message: "Warning period has finished and motion is still off."
|
||||
|
||||
|
||||
# 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
|
||||
value_template: "{{ on_just_before_off_seconds > 0 }}"
|
||||
then:
|
||||
- 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:
|
||||
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"
|
||||
|
||||
- alias: "Activate Scene: Off (Done)"
|
||||
repeat:
|
||||
count: "{{ scene_repeat_count }}"
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_off
|
||||
- delay:
|
||||
milliseconds: "{{ scene_repeat_delay_milliseconds }}"
|
||||
|
||||
- alias: "Reset countdown timer after turning off lights."
|
||||
service: input_number.set_value
|
||||
data:
|
||||
entity_id: !input delay_seconds_helper
|
||||
value: "{{ delay_seconds_default }}"
|
||||
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ debug_mode == true }}"
|
||||
then:
|
||||
- service: logbook.log
|
||||
data:
|
||||
name: "Turning off light, due to motion off."
|
||||
message: "Activated off-scene and reset delay."
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,430 +0,0 @@
|
||||
|
||||
|
||||
########################
|
||||
### Blueprint definition
|
||||
########################
|
||||
|
||||
blueprint:
|
||||
|
||||
name: "Mike's Motion Activated Light"
|
||||
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"
|
||||
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
|
||||
|
||||
|
||||
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."
|
||||
selector:
|
||||
entity:
|
||||
domain: input_number
|
||||
|
||||
|
||||
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."
|
||||
default: 30
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
notice_seconds:
|
||||
name: "Notice seconds"
|
||||
description: "The number of seconds to wait in the Prep1 (Notice) scene."
|
||||
default: 15
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
warning_seconds:
|
||||
name: "Warning seconds"
|
||||
description: "The number of seconds to wait in the Prep2 (Warning) scene."
|
||||
default: 15
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
scene_on:
|
||||
name: "On Scene"
|
||||
description: "The scene to activate when motion is detected"
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_off_prep_1:
|
||||
name: "Off Prep Scene 1 (Notice)"
|
||||
description: "The first scene to activate when motion is no longer detected (notice phase)."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_off_prep_2:
|
||||
name: "Off Prep Scene 2 (Warning)"
|
||||
description: "The second scene to activate when motion is no longer detected (warning phase)."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
scene_off:
|
||||
name: "Off Scene"
|
||||
description: "The scene to activate when the user has failed to produce motion, and the light should be considered \"off\"."
|
||||
selector:
|
||||
entity:
|
||||
domain: scene
|
||||
|
||||
|
||||
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:
|
||||
number:
|
||||
min: 1
|
||||
max: 86400
|
||||
step: 1
|
||||
mode: box
|
||||
|
||||
|
||||
debug_mode:
|
||||
name: "Debug mode."
|
||||
description: "Enable debug mode, which increases logging."
|
||||
default: false
|
||||
selector:
|
||||
boolean: {}
|
||||
|
||||
|
||||
#############
|
||||
### Variables
|
||||
#############
|
||||
|
||||
variables:
|
||||
|
||||
motion_sensor: !input motion_sensor
|
||||
delay_seconds: !input delay_seconds_helper
|
||||
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
|
||||
debug_mode: !input debug_mode
|
||||
|
||||
|
||||
############
|
||||
### Triggers
|
||||
############
|
||||
|
||||
trigger:
|
||||
|
||||
- platform: state
|
||||
entity_id:
|
||||
- !input motion_sensor
|
||||
to:
|
||||
- "on"
|
||||
- "off"
|
||||
|
||||
###########
|
||||
### Actions
|
||||
###########
|
||||
|
||||
action:
|
||||
|
||||
- service: logbook.log
|
||||
data:
|
||||
name: "First log"
|
||||
message: "Motion automation has started. Delay counter is: {{ states[delay_seconds].state }}"
|
||||
|
||||
- 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 }} "
|
||||
|
||||
- if:
|
||||
- condition: state
|
||||
entity_id: !input motion_sensor
|
||||
state: "on"
|
||||
|
||||
# Take actions based on Motion being detected!
|
||||
then:
|
||||
|
||||
- alias: "Log that motion was detected."
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Motion On"
|
||||
message: "Motion was detected."
|
||||
|
||||
- parallel:
|
||||
- alias: "Activate the ON scene"
|
||||
service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
|
||||
|
||||
# Take actions based on Motion being undetected
|
||||
else:
|
||||
|
||||
- alias: "Log that the motion-off sequence will run, due to motion no longer detected."
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Motion Off"
|
||||
message: "Initiating motion-off sequence, because motion no longer detected."
|
||||
|
||||
|
||||
# Initial period where nothing happens
|
||||
- alias: "Delay appropriately before doing anything"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' }}"
|
||||
timeout: "{{ states[delay_seconds].state }}"
|
||||
- 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
|
||||
data:
|
||||
name: "Motion Off"
|
||||
message: "Finished initial no-motion delay"
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
- alias: "Delay during the notice period"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' }}"
|
||||
timeout: "{{ notice_seconds }}"
|
||||
- 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
|
||||
- alias: "Increase countdown timer when user interrupts the notice period."
|
||||
service: input_number.set_value
|
||||
data:
|
||||
entity_id: !input delay_seconds_helper
|
||||
value: "{{ states[delay_seconds].state | int * delay_seconds_multiplier }}"
|
||||
- alias: "Limit delay seconds to its defined maximum"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ states[delay_seconds].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].state }}"
|
||||
- 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].state }} seconds"
|
||||
- stop: "Motion detected during notice period."
|
||||
- service: logbook.log
|
||||
data:
|
||||
name: "Notice period finished."
|
||||
message: "Notice period has finished (motion is still off)."
|
||||
|
||||
|
||||
# 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
|
||||
- alias: "Delay during the warning period"
|
||||
wait_template: "{{ states[motion_sensor].state == 'on' }}"
|
||||
timeout: "{{ warning_seconds }}"
|
||||
- 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
|
||||
- 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].state | int * delay_seconds_multiplier }}"
|
||||
- alias: "Limit delay seconds to its defined maximum"
|
||||
if:
|
||||
- condition: template
|
||||
value_template: "{{ states[delay_seconds].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].state }}"
|
||||
- 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].state }} seconds."
|
||||
- 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."
|
||||
|
||||
|
||||
# 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
|
||||
value_template: "{{ on_just_before_off_seconds > 0 }}"
|
||||
then:
|
||||
- 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:
|
||||
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
|
||||
|
||||
- alias: "Reset countdown timer after turning off lights."
|
||||
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."
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user