Compare commits
31 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 | ||
|
baa226bcab | ||
|
c059a2773f | ||
|
acaf3518c2 | ||
|
c289fce42b |
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,317 +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
|
||||
|
||||
|
||||
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:
|
||||
name: "Use On scene just before Off scene."
|
||||
description: "Toggle this to \"on\" if you would like the \"On\" scene to trigger just before the \"Off\" scene. This is sometimes helpful to mitigate an issue where the \"On\" scene doesn't apply all colors and settings correctly from an \"Off\" state."
|
||||
selector:
|
||||
boolean: {}
|
||||
|
||||
|
||||
#############
|
||||
### Variables
|
||||
#############
|
||||
|
||||
variables:
|
||||
|
||||
motion_sensor: !input motion_sensor
|
||||
delay_seconds: !input delay_seconds_helper
|
||||
delay_seconds_default: !input delay_seconds_default
|
||||
notice_seconds: !input notice_seconds
|
||||
warning_seconds: !input warning_seconds
|
||||
on_just_before_off: !input on_just_before_off
|
||||
|
||||
|
||||
############
|
||||
### 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 bool"
|
||||
enabled: false
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "Debug: On just before off?"
|
||||
message: "On just before off is: {{ on_just_before_off }} "
|
||||
|
||||
- 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: "Double 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 * 2 }}"
|
||||
- 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 * 2 }}"
|
||||
- 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 == true }}"
|
||||
then:
|
||||
- alias: "Do a debug log"
|
||||
enabled: false
|
||||
service: logbook.log
|
||||
data:
|
||||
name: "DEBUG: Will turn on before off?"
|
||||
message: "Yes, will turn on just before off!"
|
||||
- service: scene.turn_on
|
||||
target:
|
||||
entity_id: !input scene_on
|
||||
- alias: "Wait a second to set the \"On\" scene."
|
||||
delay:
|
||||
seconds: 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