Skip to content

Instantly share code, notes, and snippets.

@freakshock88
Last active April 24, 2024 20:29
Show Gist options
  • Save freakshock88/2311759ba64f929f6affad4c0a67110b to your computer and use it in GitHub Desktop.
Save freakshock88/2311759ba64f929f6affad4c0a67110b to your computer and use it in GitHub Desktop.
Home Assistant BluePrint to turn on light, switch, scene or script based on motion and illuminance
blueprint:
name: Turn on light, switch, scene, script or group based on motion and illuminance.
description: >
Turn on a light, switch, scene, script or group based on motion detection, and low light level.
This blueprint uses helper entities you have to create yourself for some input values, to be able to dynamically set limits.
For instructions on creating the helper entities take a look in the Home Assistant Community forum topic:
https://community.home-assistant.io/t/turn-on-light-switch-scene-or-script-based-on-motion-and-illuminance-more-conditions/257085
Required entities:
- Motion sensor (single sensor or group)
- Target entity (light, switch, scene* or script*)
(*) If you select a scene or script as your target_entity, you must also define a target_off_entity, since scenes and scripts cannot be turned off.
An example for a target_off_entity could be a light or a light group.
Optional features:
- You can set a cutoff entity of which the value determines whether the illuminance level is low and the automation needs to trigger.
- You can define a blocking entity, which blocks the automation from running when this entity's state is on.
- You can define a turn-off blocking entity, which blocks the entity from turning off after the set delay.
- Time limits can also be defined to limit the time before and after the automation should trigger.
- If you want the entity to turn off after a certain amount of minutes, you can use the Wait Time input.
- If you want another entity than the target_entity to turn off after the delay, you can define a separate Turn-off entity (also important for scenes and scripts).
- If you do not enable the optional entities the automation will skip these conditions.
Optional entities:
- Illuminance sensor (sensor in illuminance class)
- Illuminance cutoff value (input_number)
- Blocking entity (any entity with state on/off)
- Time limit before (input_datetime)
- Time limit after (input_datetime)
- Turn off wait time (input_number defining amount in minutes)
- Turn off entity (any entity_id that needs to be turned off after wait)
domain: automation
input:
motion_sensor:
name: Motion Sensor
description: This sensor will trigger the turning on of the target entity.
selector:
entity:
target_entity:
name: Target entity.
description: The light, switch, scene to turn on (or script to run) when the automation is triggered.
selector:
entity:
illuminance_sensor:
name: (OPTIONAL) Illuminance sensor
description: This sensor will be used to determine the illumination.
default:
selector:
entity:
domain: sensor
device_class: illuminance
illuminance_cutoff:
name: (OPTIONAL) Illuminance cutoff value
description: This input_number will be used to compare to the current illumination to determine if it is low.
default:
selector:
entity:
domain: input_number
blocker_entity:
name: (OPTIONAL) Blocking entity
description: If this entity's state is on, it will prevent the automation from running. E.g. sleepmode or away mode.
default:
selector:
entity:
time_limit_after:
name: (OPTIONAL) Only run after time.
description: Automation will only run when time is later than this input_datetime value.
default:
selector:
entity:
domain: input_datetime
time_limit_before:
name: (OPTIONAL) Only run before time.
description: Automation will only run when time is earlier than this input_datetime value.
default:
selector:
entity:
domain: input_datetime
no_motion_wait:
name: (OPTIONAL) Turn off wait time (minutes)
description: Time in minutes to leave the target entity on after last motion is detected. If not used entity will not auto turn off.
default:
selector:
entity:
domain: input_number
turn_off_blocker_entity:
name: (OPTIONAL) Turn-off Blocking entity
description: If this entity's state is on, it will prevent the target entity from turning off after the set delay.
default:
selector:
entity:
target_off_entity:
name: (OPTIONAL) Turn-off entity
description: If defined, this entity will be turned off instead of the default target entity. This can be helpful when using target entities of type scene or script.
default:
selector:
entity:
sunstate_condition:
name: When to trigger automation, based on the elevation of the sun. Use always when you don't want to add a condition for this.
default: 'Always'
selector:
select:
options:
- Always
- Below horizon
- Above horizon
mode: restart
max_exceeded: silent
variables:
target_entity: !input target_entity
illuminance_currently: !input illuminance_sensor
illuminance_cutoff: !input illuminance_cutoff
blocker_entity: !input blocker_entity
time_limit_before: !input time_limit_before
time_limit_after: !input time_limit_after
no_motion_wait: !input no_motion_wait
entity_domain: "{{ states[target_entity].domain }}"
turn_off_blocker_entity: !input turn_off_blocker_entity
target_off_entity: !input target_off_entity
sun_condition: !input sunstate_condition
trigger:
platform: state
entity_id: !input motion_sensor
to: 'on'
condition:
# When entity was already on because the automation ran recently, do not check illuminance because it could have increased above threshold because of a light that was just turned on.
# This check is not possible for script target_entities or fir scene target_entities that control more than 1 entity.
# This might cause the automation to turn off the target entity too soon because the illuminance check fails on restart of the automation.
- condition: template
alias: 'Check for illuminance conditions'
value_template: >
{% set illuminance_defined = illuminance_currently != none and illuminance_cutoff != none %}
{% set illuminance_defined_and_low = (illuminance_defined and (states(illuminance_currently) | int(0) < states(illuminance_cutoff) | int(0))) %}
{% set target_entity_domain_supports_on_state_check = entity_domain != 'scene' and entity_domain != 'script' %}
{% set target_entity_is_scene = entity_domain == 'scene' %}
{% set scene_target_entities = state_attr(target_entity, 'entity_id') %}
{% set singular_scene_entity_is_on = scene_target_entities is not none and scene_target_entities | count == 1 and scene_target_entities | first == 'on' %}
{{
( target_entity_domain_supports_on_state_check and states(target_entity) == 'on') or
( target_entity_domain_supports_on_state_check and states(target_entity) == 'off' and not illuminance_defined) or
( target_entity_domain_supports_on_state_check and states(target_entity) == 'off' and illuminance_defined_and_low) or
( not target_entity_domain_supports_on_state_check and illuminance_defined_and_low) or
( not target_entity_domain_supports_on_state_check and not illuminance_defined) or
( target_entity_is_scene and singular_scene_entity_is_on)
}}
- condition: template
alias: 'Check for blocker entity'
value_template: "{{ (blocker_entity == none) or (states(blocker_entity) == 'off') }}"
- condition: template
alias: 'Check for time limits'
value_template: >
{% set current_time = now().strftime("%H:%M") %}
{% if time_limit_before == none and time_limit_after == none %}
true
{% endif %}
{% if time_limit_before != none and time_limit_after == none %}
{% set current_time_is_before_limit = current_time < states(time_limit_before) %}
{{ current_time_is_before_limit }}
{% elif time_limit_before == none and time_limit_after != none %}
{% set current_time_is_after_limit = current_time > states(time_limit_after) %}
{{ current_time_is_after_limit }}
{% endif %}
{% if time_limit_before != none and time_limit_after != none %}
{% set before_limit_is_tomorrow = states(time_limit_before) < states(time_limit_after) %}
{% set current_time_is_before_limit = current_time < states(time_limit_before) %}
{% set current_time_is_after_limit = current_time > states(time_limit_after) %}
{% set time_window_spans_midnight = states(time_limit_after) > states(time_limit_before) %}
{% if time_window_spans_midnight != none and time_window_spans_midnight and before_limit_is_tomorrow %}
{{ current_time_is_after_limit or current_time_is_before_limit }}
{% elif time_window_spans_midnight != none and not time_window_spans_midnight %}
{{ current_time_is_before_limit and current_time_is_after_limit }}
{% endif %}
{% endif %}
- condition: template
alias: 'Check for sun state'
value_template: >
{# Prevent breaking when no sun condition is set in existing automations #}
{% if not sun_condition is defined %}
{% set sun_condition = 'Always' %}
{% endif %}
{# Get current sun state #}
{% set current_sun_condition = states['sun.sun'].state %}
{# Checks for current sun state #}
{% set sun_state_is_below_horizon = current_sun_condition == 'below_horizon' %}
{% set sun_state_is_above_horizon = current_sun_condition == 'above_horizon' %}
{# Check to see if a condition for sunstate is set by user #}
{% set no_sun_condition = sun_condition is defined and sun_condition == 'Always' %}
{# Check to see if the user wants automation to trigger below horizon #}
{% set sun_condition_is_below_horizon = sun_condition == 'Below horizon' %}
{# Check to see if the user wants automation to trigger above horizon #}
{% set sun_condition_is_above_horizon = sun_condition == 'Above horizon' %}
{# Checks to see if sunstate matches up with users condition #}
{% set sun_condition_below_horizon_match = sun_state_is_below_horizon and sun_condition_is_below_horizon %}
{% set sun_condition_above_horizon_match = sun_state_is_above_horizon and sun_condition_is_above_horizon %}
{% set sun_condition_matching = sun_condition_below_horizon_match or sun_condition_above_horizon_match or no_sun_condition %}
{{ sun_condition_matching }}
{# Debug values: (uncomment to check in template dev tool)
## Set at top of template: {% set sun_condition = 'Above horizon' %}
Current sun condition: {{current_sun_condition}}
Sun state is below horizon: {{ sun_state_is_below_horizon }}
Sun state is above horizon: {{ sun_state_is_above_horizon }}
Sun condition is set to always: {{ sun_condition_always }}
Sun condition is below horizon: {{ sun_condition_is_below_horizon }}
Sun condition is above horizon: {{ sun_condition_is_above_horizon }}
Sun condition is below horizon match: {{ sun_condition_below_horizon_match }}
Sun condition is above horizon match: {{ sun_condition_above_horizon_match }}
Sun condition is a match: {{ sun_condition_matching }}
#}
action:
- service: homeassistant.turn_on
entity_id: !input target_entity
- wait_for_trigger:
platform: state
entity_id: !input motion_sensor
from: "on"
to: "off"
- choose:
- alias: 'Motion wait not defined and target off entity not defined'
conditions:
- condition: template
value_template: "{{ no_motion_wait == none and target_off_entity == none }}"
sequence:
- service: homeassistant.turn_off
entity_id: !input target_entity
- alias: 'Motion wait not defined and target off entity defined'
conditions:
- condition: template
value_template: "{{ no_motion_wait == none and target_off_entity != none }}"
sequence:
- service: homeassistant.turn_off
entity_id: !input target_off_entity
- alias: 'Motion wait defined and target off entity not defined'
conditions:
- condition: template
value_template: "{{ no_motion_wait != none and target_off_entity == none }}"
sequence:
- delay:
minutes: '{{ states(no_motion_wait) | int(0) }}'
- alias: "Check if blocker entity is defined and on"
condition: template
value_template: "{{ (turn_off_blocker_entity == none) or (states(turn_off_blocker_entity) == 'off') }}"
- service: homeassistant.turn_off
entity_id: !input target_entity
- alias: 'Motion wait defined and target off entity defined'
conditions:
- condition: template
value_template: "{{ no_motion_wait != none and target_off_entity != none }}"
sequence:
- delay:
minutes: '{{ states(no_motion_wait) | int(0) }}'
- alias: "Check if blocker entity is defined and on"
condition: template
value_template: "{{ (turn_off_blocker_entity == none) or (states(turn_off_blocker_entity) == 'off') }}"
- service: homeassistant.turn_off
entity_id: !input target_off_entity
@nickdos
Copy link

nickdos commented Apr 5, 2021

I'm not able to select a datetime for time_limit_after or time_limit_before. I see a selector for entity and it only offers me an empty dropdown - see screenshot. I used the code above and initiated via the UI create automation button for this blueprint.

image

@wroadd
Copy link

wroadd commented May 10, 2021

I'm not able to select a datetime for time_limit_after or time_limit_before. I see a selector for entity and it only offers me an empty dropdown - see screenshot. I used the code above and initiated via the UI create automation button for this blueprint.

image

You need to create a date_time helper in the configuration menu, You can not define time here.

@DickSwart
Copy link

Awsome blueprint, thank you for sharing. Just one comment/suggestion/question :)

Why don't you make use of is_state() and states() methods as suggested by Home Assistant instead of working with the state object directly? Home Assistant Templating State Documentation

image

@floatiepen
Copy link

floatiepen commented May 9, 2022

I think line 187 should use int() instead of states():
minutes: '{{ int(no_motion_wait) | int(0) }}'

with states(), it always uses 0 if I give the parameter as a string ('10'), or an error if I gave it as an int (10): Error: AttributeError: 'int' object has no attribute 'lower'

@drojf
Copy link

drojf commented May 22, 2022

It looks like the "Optional Features:" list doesn't display properly when you click "preview blueprint" in home assistant. The other "Optional entities:/Required Entities:" lists display fine:

image

@kkuepper
Copy link

The changes from July 10th, broke it for me. I know created a fork with the previous version and it's working fine again.
Turning on when a motion is detected works fine but it's never turned off. I'm using a light switch (instead of a light bulb).

@drojf
Copy link

drojf commented Aug 28, 2022

It's probably due to the " (OPTIONAL) Turn off wait time (minutes)" option - if you don't set this to something, the entity will never turn off.

Time in minutes to leave the target entity on after last motion is detected. If not used entity will not auto turn off.

I think the default behavior (if the option is not set) should be to auto turn off immediately, as most motion detectors will report motion for a reasonable time by themselves (usually > 30 seconds).

@freakshock88
Copy link
Author

@kkuepper @drojf I have just tested the latest version without specifying a turn off wait time, and the target entity turns off fine when the motion sensor stops detecting motion. This is the intended behavior and it works. Please try updating the blueprint again. If it still does not work, please post your automation YAML here so I can have a look.

@drojf
Copy link

drojf commented Aug 29, 2022

@freakshock88 Ah, I updated to the latest version and it does work now. It looks like it was the older version (from around 22 May when I last posted) which had the problem.

However, please do update the description - it still says

(OPTIONAL) Turn off wait time (minutes): Time in minutes to leave the target entity on after last motion is detected. If not used entity will not auto turn off."

you should change "If not used entity will not auto turn off." to "If not used, entity will turn off as soon as last motion is detected." or something like that.

@3v1n0
Copy link

3v1n0 commented Nov 23, 2022

Please include source_url: https://gist.github.com/freakshock88/2311759ba64f929f6affad4c0a67110b so that it can be used with update scripts such as https://gist.githubusercontent.com/koter84/86790850aa63354bda56d041de31dc70

@YiEthan-W
Copy link

no_motion_wait:
name: (OPTIONAL) Turn off wait time (minutes)
description: Time in minutes to leave the target entity on after last motion is detected. If not used entity will not auto turn off.
default:
selector:
entity:
domain: input_number

Is it supposed to be "auto turn off right after no motion is detected" vs "not auto turn off"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment