Skip to content

Instantly share code, notes, and snippets.

@connorjfarrell
Last active March 30, 2026 23:11
Show Gist options
  • Select an option

  • Save connorjfarrell/e91a91242236eb64ff338ba84a467223 to your computer and use it in GitHub Desktop.

Select an option

Save connorjfarrell/e91a91242236eb64ff338ba84a467223 to your computer and use it in GitHub Desktop.
blueprint:
name: Fridge / Freezer Left Open Escalation
description: >
Escalating notifications for a fridge/freezer door left open.
Stage 1 after X minutes, stage 2 after Y minutes, and stage 3 after Z minutes,
with optional flashing lights, additional lights, TTS, and an all-clear notification.
Notes:
- This blueprint sends push notifications through notify.family_phones.
- This blueprint uses tts.google_translate_say for TTS.
- For best results, keep stage1 < stage2 < stage3.
- On close after stage 3, it turns off the flashing light and the additional stage 3 lights.
It does not restore prior light state.
domain: automation
input:
door_sensor:
name: Door sensor
selector:
entity:
domain: binary_sensor
appliance_name:
name: Appliance friendly name
default: Fridge/Freezer
selector:
text:
stage1_minutes:
name: Stage 1 delay from open (minutes)
default: 2
selector:
number:
min: 1
max: 120
mode: box
stage2_minutes:
name: Stage 2 delay from open (minutes)
default: 5
selector:
number:
min: 1
max: 240
mode: box
stage3_minutes:
name: Stage 3 delay from open (minutes)
default: 10
selector:
number:
min: 1
max: 480
mode: box
stage1_critical:
name: Stage 1 critical push
default: false
selector:
boolean:
stage2_critical:
name: Stage 2 critical push
default: true
selector:
boolean:
stage3_critical:
name: Stage 3 critical push
default: true
selector:
boolean:
send_all_clear:
name: Send all-clear notification
default: true
selector:
boolean:
enable_flash_lights:
name: Enable flashing lights at stage 3
default: true
selector:
boolean:
flash_light:
name: Flashing light target
default:
entity_id: light.living_room_lamps
selector:
target:
entity:
domain: light
flash_rgb:
name: Flash RGB color
default:
- 255
- 0
- 0
selector:
color_rgb:
flash_brightness_pct:
name: Flash brightness percent
default: 100
selector:
number:
min: 1
max: 100
mode: slider
flash_on_seconds:
name: Flash ON time (seconds)
default: 1
selector:
number:
min: 1
max: 10
mode: box
flash_off_seconds:
name: Flash OFF time (seconds)
default: 1
selector:
number:
min: 1
max: 10
mode: box
stage3_turn_on_lights:
name: Additional lights to turn on at stage 3
default: {}
selector:
target:
entity:
domain: light
enable_tts:
name: Enable TTS at stage 3
default: false
selector:
boolean:
tts_media_player:
name: TTS media player
default: media_player.master_bedroom_homepod
selector:
entity:
domain: media_player
tts_volume:
name: Temporary TTS volume
default: 1.0
selector:
number:
min: 0
max: 1
step: 0.05
mode: slider
mode: parallel
max: 20
trigger:
- platform: state
entity_id: !input door_sensor
from: "off"
to: "on"
variables:
door_sensor: !input door_sensor
appliance_name: !input appliance_name
stage1_minutes: !input stage1_minutes
stage2_minutes: !input stage2_minutes
stage3_minutes: !input stage3_minutes
stage1_critical: !input stage1_critical
stage2_critical: !input stage2_critical
stage3_critical: !input stage3_critical
send_all_clear: !input send_all_clear
enable_flash_lights: !input enable_flash_lights
enable_tts: !input enable_tts
tts_media_player: !input tts_media_player
tts_volume: !input tts_volume
opened_at: "{{ now() }}"
stage1_title: "{{ appliance_name }} Left Open"
stage1_message: "The {{ appliance_name | lower }} has been open."
stage2_title: "{{ appliance_name }} Left Open"
stage2_message: "The {{ appliance_name | lower }} is still open after {{ stage2_minutes }} minutes!"
stage3_title: "{{ appliance_name }} Left Open"
stage3_message: "The {{ appliance_name | lower }} is still open after {{ stage3_minutes }} minutes!"
all_clear_title: "{{ appliance_name }} Closed"
action:
- wait_template: "{{ is_state(door_sensor, 'off') }}"
timeout:
minutes: !input stage1_minutes
continue_on_timeout: true
- choose:
- conditions:
- condition: template
value_template: "{{ wait.completed }}"
sequence:
- stop: Closed before stage 1
- choose:
- conditions:
- condition: template
value_template: "{{ stage1_critical }}"
sequence:
- action: notify.family_phones
data:
title: "{{ stage1_title }}"
message: "{{ stage1_message }}"
data:
push:
sound:
name: default
critical: 1
volume: 1.0
default:
- action: notify.family_phones
data:
title: "{{ stage1_title }}"
message: "{{ stage1_message }}"
data:
push:
sound:
name: default
critical: 0
volume: 1.0
- wait_template: "{{ is_state(door_sensor, 'off') }}"
timeout:
seconds: "{{ ((stage2_minutes - stage1_minutes) * 60) | int }}"
continue_on_timeout: true
- variables:
duration_text: >-
{% set s = (as_timestamp(now()) - as_timestamp(opened_at)) | int(0) %}
{% set m = s // 60 %}
{% set r = s % 60 %}
{{ m }} minute{{ 's' if m != 1 else '' }}{% if r > 0 %} and {{ r }} second{{ 's' if r != 1 else '' }}{% endif %}
all_clear_message: "{{ appliance_name }} was closed after {{ duration_text }}."
- choose:
- conditions:
- condition: template
value_template: "{{ wait.completed }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ send_all_clear }}"
sequence:
- action: notify.family_phones
data:
title: "{{ all_clear_title }}"
message: "{{ all_clear_message }}"
- stop: Closed before stage 2
- choose:
- conditions:
- condition: template
value_template: "{{ stage2_critical }}"
sequence:
- action: notify.family_phones
data:
title: "{{ stage2_title }}"
message: "{{ stage2_message }}"
data:
push:
sound:
name: default
critical: 1
volume: 1.0
default:
- action: notify.family_phones
data:
title: "{{ stage2_title }}"
message: "{{ stage2_message }}"
data:
push:
sound:
name: default
critical: 0
volume: 1.0
- wait_template: "{{ is_state(door_sensor, 'off') }}"
timeout:
seconds: "{{ ((stage3_minutes - stage2_minutes) * 60) | int }}"
continue_on_timeout: true
- variables:
duration_text: >-
{% set s = (as_timestamp(now()) - as_timestamp(opened_at)) | int(0) %}
{% set m = s // 60 %}
{% set r = s % 60 %}
{{ m }} minute{{ 's' if m != 1 else '' }}{% if r > 0 %} and {{ r }} second{{ 's' if r != 1 else '' }}{% endif %}
all_clear_message: "{{ appliance_name }} was closed after {{ duration_text }}."
- choose:
- conditions:
- condition: template
value_template: "{{ wait.completed }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ send_all_clear }}"
sequence:
- action: notify.family_phones
data:
title: "{{ all_clear_title }}"
message: "{{ all_clear_message }}"
- stop: Closed before stage 3
- choose:
- conditions:
- condition: template
value_template: "{{ stage3_critical }}"
sequence:
- action: notify.family_phones
data:
title: "{{ stage3_title }}"
message: "{{ stage3_message }}"
data:
push:
sound:
name: default
critical: 1
volume: 1.0
default:
- action: notify.family_phones
data:
title: "{{ stage3_title }}"
message: "{{ stage3_message }}"
data:
push:
sound:
name: default
critical: 0
volume: 1.0
- action: light.turn_on
target: !input stage3_turn_on_lights
- choose:
- conditions:
- condition: template
value_template: "{{ enable_tts }}"
sequence:
- variables:
old_volume: "{{ state_attr(tts_media_player, 'volume_level') | float(0.35) }}"
- action: media_player.volume_set
target:
entity_id: !input tts_media_player
data:
volume_level: !input tts_volume
- action: tts.google_translate_say
data:
cache: false
entity_id: !input tts_media_player
message: "{{ appliance_name }} has been left open for {{ stage3_minutes }} minutes."
- parallel:
- sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ enable_flash_lights }}"
sequence:
- repeat:
while:
- condition: state
entity_id: !input door_sensor
state: "on"
sequence:
- action: light.turn_on
target: !input flash_light
data:
rgb_color: !input flash_rgb
brightness_pct: !input flash_brightness_pct
- delay:
seconds: !input flash_on_seconds
- action: light.turn_off
target: !input flash_light
- delay:
seconds: !input flash_off_seconds
- sequence:
- wait_template: "{{ is_state(door_sensor, 'off') }}"
- choose:
- conditions:
- condition: template
value_template: "{{ enable_tts }}"
sequence:
- delay: "00:00:08"
- action: media_player.volume_set
target:
entity_id: !input tts_media_player
data:
volume_level: "{{ old_volume | default(0.35) }}"
- action: light.turn_off
target: !input flash_light
- action: light.turn_off
target: !input stage3_turn_on_lights
- variables:
duration_text: >-
{% set s = (as_timestamp(now()) - as_timestamp(opened_at)) | int(0) %}
{% set m = s // 60 %}
{% set r = s % 60 %}
{{ m }} minute{{ 's' if m != 1 else '' }}{% if r > 0 %} and {{ r }} second{{ 's' if r != 1 else '' }}{% endif %}
all_clear_message: "{{ appliance_name }} was closed after {{ duration_text }}."
- choose:
- conditions:
- condition: template
value_template: "{{ send_all_clear }}"
sequence:
- action: notify.family_phones
data:
title: "{{ all_clear_title }}"
message: "{{ all_clear_message }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment