Skip to content

Instantly share code, notes, and snippets.

@c-kick
Last active April 11, 2024 10:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save c-kick/2d252ec6faca02ec84a9e4a3c2e34f4f to your computer and use it in GitHub Desktop.
Save c-kick/2d252ec6faca02ec84a9e4a3c2e34f4f to your computer and use it in GitHub Desktop.
Blueprint for Home Asssistant that manages basic smart home states (home, sleep & activity)
#Blueprint by Klaas Leussink / hnldesign.nl (c) 2024 - Part of hass_package - version 2.11.4.24
# REQUIRES this package: https://gist.github.com/c-kick/fa17b4e3ec474f4169dd8fa1e59e5d49
blueprint:
name: Manage smart home basics
source_url: https://gist.github.com/c-kick/2d252ec6faca02ec84a9e4a3c2e34f4f
description: |
Blueprint for Home Asssistant that manages basic smart home states (home, sleep & activity). REQUIRES this package: https://gist.github.com/c-kick/fa17b4e3ec474f4169dd8fa1e59e5d49
domain: automation
input:
input_night_schedule:
name: Night indicator
description: |-
Schedule or Time of Day sensor that indicates the night starts/ends.
This is usually the time that (most of) your household is sleeping. Defaults to the binary_sensor supplied by the package (binary_sensor.primary_state_night).
default: binary_sensor.primary_state_night
selector:
entity:
domain:
- input_boolean
- binary_sensor
- schedule
multiple: false
input_guest_mode:
name: Guest mode indicator
description: >-
Indicates you have guests in the house, so certain automations are paused/halted, and activity detection is less strict. Defaults to packate sensor.
default: input_boolean.secondary_state_guest_mode
selector:
entity:
domain:
- input_boolean
- binary_sensor
- schedule
multiple: false
input_dark_outside:
name: Darkness indicator
description: |-
Used to determine if it's dark outside, so actions related to coming home in darkness (see below) can run efficiently
default: binary_sensor.helper_dark_outside
selector:
entity:
domain:
- binary_sensor
- input_boolean
multiple: false
input_monitor_devices:
name: HOME/AWAY state - Device trackers and/or persons to monitor
description: Track these devices and/or persons to determine home or away.
selector:
entity:
domain:
- device_tracker
- person
multiple: true
input_minutes_away:
name: HOME/AWAY state - Minutes away
description: |-
Used as a cool-down timer: wait for x minutes to consider a device/person as being away.
This prevents unnessecary triggering of away states should you momentarily lose wi-fi connection, or are only away for a small errand, for example.
default: 30
selector:
number:
min: 0
max: 60
unit_of_measurement: min
mode: slider
step: 1
input_sleep_triggers:
name: SLEEP state - Conditional states
description: |
Entities that are monitored to trigger the sleep state indicator (see above) to **ON** or **OFF**.
These entities must **ALL** be `on`/`true` to trigger sleep state. If you have a Bayesian sensor for sleep detection, you can enter it here. Adding more entities here allows you to refine the detection. For example, say you do not want sleep to be considered when the home indicator (`input_boolean.primary_state_home`) is not 'on' (i.e. no one's home), add the home indicator to this list.
default: []
selector:
entity:
domain:
- switch
- input_boolean
- binary_sensor
- remote
- sensor
- light
multiple: true
input_activity_single_event_triggers:
name: ACTIVITY state - SINGLE EVENT triggers
description: |
Entities that are monitored only to consider activity as **ON**.
Please define entities to be used as **Single event** triggers. These triggers are designed to detect human activity through events that either do not have an _off_ state or where the _off_ state should be ignored. Ideal candidates include **buttons**, **light switches**, or any device interactions that typically signify active human presence with a singular action.
Note: **Single event** triggers are distinct from **Continuous state** triggers, which you can define below. **Continuous state** triggers monitor ongoing activities, like a TV or computer that remains in an _on_ state and has a distinctive _off_ state that should be considered. Choose your entities wisely to ensure they align with the intended behavior of detecting brief, distinct actions in your home environment.
selector:
entity:
domain:
- button
- switch
- input_button
- input_boolean
- binary_sensor
- remote
- sensor
- light
multiple: true
input_activity_continuous_state_triggers:
name: ACTIVITY state - CONTINUOUS STATE triggers
description: |
Entities that are monitored to consider activity as **ON** or **OFF**.
Please define entities to be used as **Continuous state** triggers. These triggers are crucial for detecting sustained human activities. Select entities that have a clear _on_ and _off_ state, which remain active during extended use. Examples include **televisions**, **computers**, or **appliances**, or **sensors** like a running shower sensor.
Unlike **Single event** triggers, which are intended for momentary interactions, **Continuous state** triggers help ensure that activities such as watching TV or working on a computer keep the activity state active, preventing the system from mistakenly turning off activity while you are still present.
Make sure your selections reflect devices that you typically leave on during your presence in the home, and avoid selecting devices that you are likely to (accidently) _leave on_ when leaving the house or going to bed.
default: []
selector:
entity:
domain:
- button
- switch
- input_button
- input_boolean
- binary_sensor
- remote
- sensor
- light
multiple: true
input_minutes_delay:
name: ACTIVITY state - State change delay time
description: |
A timeout used to wait before considering an actual change in activity.
This is a crucial timer that determines how quickly your system reacts to changes in activity based on the triggers you've defined. The delay time you set here will apply to both **Single event** and **Continuous state** triggers under normal circumstances, helping prevent false triggers and ensuring that the system accurately reflects human activity in your home.
For **Single event** triggers, this delay helps prevent false positives, allowing the system to ignore brief, accidental interactions. For **Continuous state** triggers, it ensures the activity state remains active during short interruptions (like momentarily stepping out of the room, untriggering a motion sensor).
However, when your system knows the house is occupied (HOME state is active) and no one is sleeping (SLEEP state is inactive), this delay time is effectively _ignored_, and the timeout is set to **0 minutes**. This means the system responds instantly to activity, ensuring lights or devices don't turn off while you're active. It's a smart way to balance responsiveness with the need to avoid unnecessary activations during quiet hours or when the house is empty.
The default of **15 minutes** is a balanced starting point for most homes. Adjust based on your activity patterns and preferences for system responsiveness.
default: 15
selector:
number:
min: 0
max: 60
unit_of_measurement: min
mode: slider
step: 1
dont_set_away_when:
name: AWAY state - Blocking entities (optional)
description: |-
Entities that, when **on**, will prevent the *away* state from being triggered.
Useful if you're leaving the house for a short time and your kids are watching tv, or if you don't want any mutations while you are sleeping, or when babysitter mode is active, for example.
**Note:** <ins>guest-mode</ins> is considered a blocking entity, and will be automatically included.
default: []
selector:
entity:
multiple: true
dont_set_home_when:
name: HOME state - Blocking entities (optional)
description: |-
Entities that, when **on**, will prevent the *home* state from being triggered.
Home mode will not be set if these entities are on. Useful if you don't want to trigger home state when your home is occupied irregularly, but you are still triggering presence on wi-fi (e.g. when you're having a street party).
default: []
selector:
entity:
domain: input_boolean
multiple: true
input_scripts_when_away:
name: AWAY state - Scripts to run when away (optional)
description: |-
Run these scripts when away mode is set.
default: []
selector:
entity:
domain: script
multiple: true
input_scripts_when_away_dark:
name: AWAY state - Additional scripts to run when away and it's dark outside (optional)
description: |-
Also run these scripts when away mode is set **and** it is dark outside.
Useful if you need to activate some specific lights, or presence simulation, as soon as you leave in darkness.
**Note:** not useful for activating lights that help you navigate your way around as you leave the house, as the away mode is triggered at least x minutes after being away (see the 'Minutes away' selector).
default: []
selector:
entity:
domain: script
multiple: true
input_scripts_when_home:
name: HOME state - Scripts to run when home (optional)
description: |-
Run these scripts when home mode is set.
default: []
selector:
entity:
domain: script
multiple: true
input_scripts_when_home_dark:
name: HOME state - Additional scripts to run when home and it's dark outside (optional)
description: |-
Also run these scripts when home mode is set **and** it is dark outside.
default: []
selector:
entity:
domain: script
multiple: true
variables:
all_monitored_devices: !input input_monitor_devices
sleep_triggers: !input input_sleep_triggers
single_activity_triggers: !input input_activity_single_event_triggers
continuous_activity_triggers: !input input_activity_continuous_state_triggers
delay_minutes: !input input_minutes_delay
trigger:
# -------------------------------------------- Activity triggers
- platform: state
entity_id: input_button.helper_activity_trigger
id: activity_single_trigger_triggered
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.helper_activity_trigger_timer
id: activity_single_trigger_timer_finished
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.helper_activity_delay_timer
id: helper_activity_delay_timer_finished
- platform: state
entity_id: input_boolean.activity_triggered
to: 'on'
id: continuous_activity_triggered
- platform: state
entity_id: input_boolean.activity_triggered
to: 'off'
id: continuous_activity_stopped
# -------------------------------------------- Sleep/wake change triggers
- platform: state
entity_id: !input input_sleep_triggers
to: 'on'
id: sleep_on
- platform: state
entity_id: !input input_sleep_triggers
to: 'off'
id: sleep_off
- platform: state
entity_id: input_boolean.primary_state_sleep
to: 'on'
id: sleeping
- platform: state
entity_id: input_boolean.primary_state_sleep
to: 'off'
id: awake
- platform: state
entity_id: input_boolean.primary_state_home
to: 'off'
id: home_left
- platform: state
entity_id: input_boolean.primary_state_home
to: 'on'
id: home_entered
- platform: state
entity_id: input_boolean.secondary_state_guest_mode
id: guest_mode_change
# -------------------------------------------- Activity state change triggers
- platform: state
entity_id: !input input_activity_single_event_triggers
not_to:
- 'null'
- 'unavailable'
- 'off'
id: activity_single_trigger
- platform: state
entity_id: !input input_activity_continuous_state_triggers
id: activity_continuous_trigger
# -------------------------------------------- Home state change triggers
- platform: state
entity_id: !input input_monitor_devices
from:
- 'home'
for:
minutes: !input input_minutes_away
id: presence_change_away
- platform: state
entity_id: !input input_monitor_devices
to:
- 'home'
id: presence_change_home
# -------------------------------------------- ACTIONS START HERE
action:
# -------------------------------------------- Delay timer changes
- if:
- condition: trigger
id:
- delays_updated
- home_entered
- home_left
- guest_mode_change
- sleeping
- awake
then:
# Evalueert verschillende statussen om de in- en uitschakeldelays in te stellen.
# Controleert tevens of de opstaan-state is ingeschakeld, en schakelt dan de slaap-state uit.
# Update ook de activity delay timer.
- service: input_number.set_value
#Set trigger delay
target:
entity_id: input_number.helper_trigger_delay
data:
value: >-
{{ iif((is_state('input_boolean.primary_state_home', 'on') and is_state('input_boolean.primary_state_sleep', 'off'))
or is_state('binary_sensor.primary_state_wakeup', 'on')
or is_state('input_boolean.secondary_state_guest_mode', 'on'), 0, delay_minutes, 0)|float}}
- service: input_number.set_value
#Set restore delay
target:
entity_id: input_number.helper_restore_delay
data:
value: >-
{{ iif((is_state('input_boolean.primary_state_home', 'on') and is_state('input_boolean.primary_state_sleep', 'off'))
or is_state('binary_sensor.primary_state_wakeup', 'on')
or is_state('input_boolean.secondary_state_guest_mode', 'on'), delay_minutes, 0, delay_minutes)|float}}
# -------------------------------------------- Sleep states
- if:
- condition: trigger
id: sleep_on
- condition: template
#only trigger if ALL sleep_triggers are ON (so the list of 'off' triggers is zero)
value_template: "{{ expand(sleep_triggers) | selectattr('state', 'eq', 'off') | list | count == 0 }}"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.primary_state_sleep
- if:
- condition: trigger
id: sleep_off
- condition: template
#only trigger if ALL sleep_triggers are OFF (so the list of 'on' triggers is zero)
value_template: "{{ expand(sleep_triggers) | selectattr('state', 'eq', 'on') | list | count == 0 }}"
then:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.primary_state_sleep
# -------------------------------------------- Guest mode changes
- if:
- condition: trigger
id: guest_mode_change
then:
#Restore activity if guest mode is deactivated,
#and force activity if guest mode is activated
- service: input_boolean.turn_{{ iif(is_state('input_boolean.secondary_state_guest_mode', 'on') or is_state('timer.helper_activity_trigger_timer', 'active') or is_state('input_boolean.activity_triggered', 'on'), 'on', 'off', 'off') }}
target:
entity_id: input_boolean.helper_activity
# -------------------------------------------- Activity trigger easing
- if:
- condition: trigger
id:
- activity_single_trigger_triggered
then:
#Activity trigger easing: wanneer SINGLE activity trigger,
#dan start timer die trigger na 1:30 weer uitschakelt,
#tenzij uitgeschakeld via andere weg, dan cancel timer.
- if:
- condition: trigger
id: activity_single_trigger_triggered
- condition: state
entity_id: input_boolean.activity_triggered
state: 'off'
then:
- service: timer.start
target:
entity_id: timer.helper_activity_trigger_timer
data:
duration: "00:01:30"
# -------------------------------------------- Evaluate activity
- if:
- condition: trigger
id:
- activity_single_trigger_timer_finished
- activity_single_trigger_triggered
- continuous_activity_triggered
- continuous_activity_stopped
- helper_activity_delay_timer_finished
- sleeping
- awake
- home_entered
- home_left
then:
# If sleep, immediately cancel activity
- if:
- condition: trigger
id: sleeping
then:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.helper_activity
- service: timer.cancel
target:
entity_id: timer.helper_activity_delay_timer
- service: timer.cancel
target:
entity_id: timer.helper_activity_trigger_timer
# If awaking or home, immediately trigger activity
- if:
- condition: trigger
id:
- home_entered
- awake
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.helper_activity
- service: timer.cancel
target:
entity_id: timer.helper_activity_delay_timer
- service: timer.start
target:
entity_id: timer.helper_activity_trigger_timer
# Start timer when NO activity, using RESTORE delay
- if:
- condition: trigger
id:
- activity_single_trigger_timer_finished
- home_left
- continuous_activity_stopped
then:
- service: timer.start
target:
entity_id: timer.helper_activity_delay_timer
data:
duration: "00:{{ '%02d' % states('input_number.helper_restore_delay')|float(0) }}:01" #+1 second, because if zero, timer will not run or finish (never (un-)triggering activity)
# Start timer when SINGLE-trigger activity, using TRIGGER delay
- if:
- condition: trigger
id:
- activity_single_trigger_triggered
- continuous_activity_triggered
then:
- service: timer.start
target:
entity_id: timer.helper_activity_delay_timer
data:
duration: "00:{{ '%02d' % states('input_number.helper_trigger_delay')|float(0) }}:01" #+1 second, because if zero, timer will not run or finish (never (un-)triggering activity)
# Cancel activity trigger timer when CONTINUOUS-trigger activity
- if:
- condition: trigger
id: continuous_activity_triggered
then:
- service: timer.cancel
target:
entity_id: timer.helper_activity_trigger_timer
# Modify activity boolean when activity delay timer actually finishes, and use the state of the activity_triggered to determine if activity should then be considered true or false.
- if:
- condition: trigger
id: helper_activity_delay_timer_finished
- condition: state
entity_id: input_boolean.secondary_state_guest_mode
state: 'off'
then:
- service: input_boolean.turn_{{ iif(is_state('timer.helper_activity_trigger_timer', 'active'), 'on', states('input_boolean.activity_triggered'), 'off') }}
target:
entity_id: input_boolean.helper_activity
# Restart running timers on trigger_delay change
- if:
- condition: trigger
id: eval_delays
- condition: state
entity_id: timer.helper_activity_delay_timer
state: 'active'
then:
- service: timer.start
target:
entity_id: timer.helper_activity_delay_timer
data:
duration: "00:{{ '%02d' % states('input_number.helper_restore_delay')|float(0) }}:01" #+1 second, because if zero, timer will not run or finish
# -------------------------------------------- Activity state changes
#activity was SINGLE triggered
- if:
- condition: trigger
id: activity_single_trigger
- condition: state
entity_id: !input input_activity_continuous_state_triggers
state: 'off'
then:
- service: input_button.press
target:
entity_id: input_button.helper_activity_trigger
#one of the CONTINUOUS activity triggers turned off
#see if activity should be set/maintained
- if:
- condition: trigger
id: activity_continuous_trigger
then:
#en-/disables the activity_triggered boolean based on more than 0 CONTINUOUS activity triggers active
- service: input_boolean.turn_{{ iif(continuous_activity_triggers | select('is_state', ['on']) | list | count > 0, 'on', 'off', 'off')}}
target:
entity_id: input_boolean.activity_triggered
# -------------------------------------------- Home state changes
#someone left home
- if:
- condition: trigger
id: presence_change_away
- condition: state
entity_id: !input dont_set_away_when
state: "off"
- condition: state
entity_id: !input input_guest_mode
state: "off"
then:
- if:
# noone's home anymore
- condition: template
value_template: "{{ expand(all_monitored_devices) | selectattr('state', 'eq', 'home') | list | count == 0 }}"
then:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.primary_state_home
- service: script.turn_on
target:
entity_id: !input input_scripts_when_away
- if:
- condition: state
entity_id: !input input_dark_outside
state: "on"
then:
- service: script.turn_on
target:
entity_id: !input input_scripts_when_away_dark
#someone returned home
- if:
- condition: trigger
id: presence_change_home
- condition: state
entity_id: !input dont_set_home_when
state: "off"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.primary_state_home
- service: script.turn_on
target:
entity_id: !input input_scripts_when_home
- if:
- condition: state
entity_id: !input input_dark_outside
state: "on"
then:
- service: script.turn_on
target:
entity_id: !input input_scripts_when_home_dark
mode: restart
max_exceeded: silent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment