Last active
April 11, 2024 10:22
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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