This blueprint performs an action at configurable duration before an alarm and another at a configurable duration after the alarm.
- It can detect alarm snooze and delay the post-alarm actions after the snoozed alarm.
- It can detect the manual update of an entity to a specific state to abort the script
- It supports min/max hours for activation
- It supports an optional activation blocking entity
Use case: I use it to warm-up my espresso machine before I wake-up. I use my presence sensor as a blocking entity, and use the switch ‘off’ as abort condition, this way, if I manualy decides to switch off the machine, the script won’t continue.
blueprint:
name: Do something Before/After alarm
description: >
Does an action at given time before alarm and after alarm
It can delay post-actions on alarm snooze.
It can abort if an entity switches to a given state.
domain: automation
input:
alarm_sensor:
name: Alarm sensor
description: Alarm sensor used as a reference point
selector:
entity:
device_class: timestamp
before_duration_hours:
name: Pre-alarm relative duration (hours)
description: Pre-alarm action will be triggered at this duration before alarm
default: 0
selector:
number:
min: 0
max: 24
unit_of_measurement: hours
before_duration_minutes:
name: Pre-alarm relative duration (minutes)
description: Pre-alarm action will be triggered at this duration before alarm
default: 25
selector:
number:
min: 0
max: 60
unit_of_measurement: minutes
before_duration_seconds:
name: Pre-alarm relative duration (seconds)
description: Pre-alarm action will be triggered at this duration before alarm
default: 0
selector:
number:
min: 0
max: 60
unit_of_measurement: seconds
before_actions:
name: Pre-alarm actions
description: Actions to be run at Pre-alarm time
default: []
selector:
action: {}
after_duration_hours:
name: Post-alarm relative duration (hours)
description: Post-alarm action will be triggered at alarm + this duration
default: 0
selector:
number:
min: 0
max: 24
unit_of_measurement: hours
after_duration_minutes:
name: Post-alarm relative duration (minutes)
description: Post-alarm action will be triggered at alarm + this duration
default: 20
selector:
number:
min: 0
max: 60
unit_of_measurement: minutes
after_duration_seconds:
name: Post-alarm relative duration (seconds)
description: Post-alarm action will be triggered at alarm + this duration
default: 0
selector:
number:
min: 0
max: 60
unit_of_measurement: seconds
after_actions:
name: Post-alarm actions
description: Actions to be run at Post-alarm time
default: []
selector:
action: {}
postpone_on_snooze:
name: Snooze detection duration
description: >
If an alarm is detected during Post-alarm duration and is not further away than Snooze detection duration time, after actions will be delayed after that alarm.
This restarts Post-alarm duration time and can be repeated indefinitly.
Set to a value a bit > than the alarm snooze delay. Set to 0 to disable.
default: 11
selector:
number:
min: 0
max: 60
unit_of_measurement: minutes
abort_trigger_entity:
name: Abort script on specific entity trigger
description: Set to none to disable
default: none
selector:
entity: {}
abort_trigger_state:
name: Abort script on specific entity trigger state
description: Ignored if trigger entity is none
default: off
selector:
text: {}
execute_after_actions_on_abort:
name: Executes Post-alarm actions on abort
default: true
selector:
boolean:
guard_time_min:
name: Minimum time condition
description: >
Automation will not start when time is lower than this
default: '00:00:00'
selector:
time: {}
guard_time_max:
name: Maximum time condition
description: >
Automation will not start when time is over than this
default: '23:59:59'
selector:
time: {}
guard_entity:
name: Additional entity to check before triggering
description: If set, checks if entity is 'on' or 'home' before triggering. Use sensor, device_tracker or person entity.
default: none
selector:
entity: {}
mode: single
max_exceeded: silent
variables:
alarm_sensor: !input alarm_sensor
before_duration_hours: !input before_duration_hours
before_duration_minutes: !input before_duration_minutes
before_duration_seconds: !input before_duration_seconds
before_duration: '{{ ((before_duration_hours|int * 60) + before_duration_minutes|int) * 60 + before_duration_seconds|int }}'
after_duration_hours: !input after_duration_hours
after_duration_minutes: !input after_duration_minutes
after_duration_seconds: !input after_duration_seconds
after_duration: '{{ ((after_duration_hours * 60) + after_duration_minutes) * 60 + after_duration_seconds }}'
postpone_on_snooze: !input postpone_on_snooze
execute_after_actions_on_abort: !input execute_after_actions_on_abort
abort_trigger_entity: !input abort_trigger_entity
abort_trigger_state: !input abort_trigger_state
guard_entity: !input guard_entity
trigger:
- platform: time_pattern
minutes: '*'
# Check for guard condition
condition:
- condition: template
value_template: '{{ states(guard_entity) in [''unknown'', ''on'', ''home'']}}'
- condition: time
after: !input guard_time_min
before: !input guard_time_max
- condition: template
value_template: '{{ states(alarm_sensor) != ''unavailable'' and (states(alarm_sensor)|as_timestamp - now()|as_timestamp)|int <= before_duration }}'
action:
# Execute Pre-alarm actions
- choose: []
default: !input before_actions
- alias: 'Repeat until abort or timeout reached after alrm (including snoozes)'
repeat:
sequence:
# Wait for before time and exit on trigger
- wait_for_trigger:
- platform: template
value_template: '{{
(abort_trigger_entity != ''none'' and states(abort_trigger_entity) == abort_trigger_state)
or
(
states(alarm_sensor) != ''unavailable''
and
(states(alarm_sensor)|as_timestamp - now()|as_timestamp) <= postpone_on_snooze * 60
and
(states(alarm_sensor)|as_timestamp - now()|as_timestamp) > 0
)
}}'
timeout:
seconds: '{{ (states(alarm_sensor)|as_timestamp - now()|as_timestamp)|int + after_duration }}'
until: '{{
wait.remaining == 0
or
(
wait.trigger.entity_id == abort_trigger_entity
and
states(abort_trigger_entity) == abort_trigger_state
)
}}'
# Execute Post-alarm actions
- choose:
- conditions:
- '{{ execute_after_actions_on_abort or wait.remaining == 0 }}'
sequence: !input after_actions
# Wait until trigger conditions are no longer true, to avoid restart after abort
- wait_template: '{{ states(alarm_sensor) == ''unavailable'' or (states(alarm_sensor)|as_timestamp - now()|as_timestamp)|int > before_duration }}'