So, what I want is: When I open the door, the light turns on, and 1 minute after I close the door the light turns off unless it was already on before I opened the door.
Im using this automations below:
- alias: ligar sala estar quando abrir porta sala a partir do por do sol
trigger:
platform: state
entity_id: binary_sensor.porta_sala
to: 'on'
condition:
- condition: state
entity_id: sun.sun
state: "below_horizon"
- condition: state
entity_id: light.sala_estar
state: "off"
action:
- service: input_boolean.turn_on
entity_id: input_boolean.porta_sala
- service: light.turn_on
entity_id: light.sala_estar
- alias: desligar sala estar 1 minuto apos fechar a porta se a automaĆ§Ć£o anterior foi ativada
trigger:
platform: state
entity_id: binary_sensor.porta_sala
to: 'off'
for:
minutes: 1
condition:
condition: state
entity_id: input_boolean.porta_sala
state: 'on'
action:
- service: input_boolean.turn_off
entity_id: input_boolean.porta_sala
- service: light.turn_off
entity_id: light.sala_estar
I created a input_boolean in configuration.yaml
input_boolean:
porta_sala:
name: porta sala
so that, when the first automation is activated, the input_boolean turns on
Also, I used a condition to only activate the first automation if the light is off
- condition: state
entity_id: light.sala_estar
state: "off"
and in the second one, I used a condition to only activate when the input_boolean is on.
condition:
condition: state
entity_id: input_boolean.porta_sala
state: 'on'
So, in theory, if I turn on the light before I open the door, the first automation wouldnt activate because of the condition that the light should be off, and then the input_boolean wouldnt turn on and that wouldnt activate the second automation.
But, the light still goes off even when I turn it on before opening the door.
Couldnāt this be done without the use of a boolean at all?
trigger: door opens
condition: light is off
action:
- turn on light
- wait 1 minute
- turn light off
this way, the automation only runs if the light is off. If the light is already on, this automation never runs so the light doesnāt turn off after a minute.
I think the easiest way to do this is using the old method.
- alias: ligar sala estar quando abrir porta sala a partir do por do sol
trigger:
platform: state
entity_id: binary_sensor.porta_sala
to: 'on'
condition:
- condition: state
entity_id: sun.sun
state: "below_horizon"
- condition: state
entity_id: light.sala_estar
state: "off"
action:
- service: script.turn_off_light
- service: light.turn_on
entity_id: light.sala_estar
I honestly donāt like doing this method (or yours) after dealing with this issue for 5 years. Hereās what Iāve ran into over the years:
No matter what, the light will turn off after the first door open. What happens when I open the door and keep it open for 2 minutes? It STILL turns off after 1 minute.
What if you have a color bulb or the light is on at 50%? Wouldnāt you want to brighten the area to 100% with a āwhiteā and then return to the previous state?
What happens if I donāt have lights on and I now want to keep them on? I have to wait a minute for them to turn off, then I have to turn them back on. Super annoying.
What happens when you have multiple lights attached to a single door. I want to keep 1 on, the other off or vice versa?
Iāve solved all these problems, however the automation will probably scare you. If youāre up for the challenge, Itās posted below in the collapsed area:
EDIT: This might not work for you. I just realized it uses utility sensors I created with MQTT, so this method wonāt work unless you integrate that. Either way, you have the code above that should work based on your requirements.
Click to see automation!
Main Automation - Handles the door illumination.
The metadata section is the configuration for doors. It also has notes on how to properly add a door to the configuration. Those were my notes to myself, but Iāll try to explain it here. Basically, youāll be adding the following configuration to the metadata section of this automation. It requires a list of lights or switches and the duration the light will be on. The section name will be the door sensor that triggers it. You also need to add the triggering door sensor to the trigger list.
E.g. Your door sensor is binary_sensor.porta_sala, your light is light.sala_estar, and your duration is 60. I also left input_boolean.test_door and itās accompanying switches in the automation so you can see what it looks like with multiple triggering entities.
- alias: Doors - Illuminate Door
id: illuminate_doors_when_open
mode: parallel
trigger:
- platform: state
entity_id:
# - input_boolean.test_door
- binary_sensor.porta_sala
from: 'off'
to: 'on'
variables:
# This is the metadata used to set all params for Illuminate door.
# When you add an entity to the entities list for each door, you need to create
# an accompanying script with the name `resume_{domain}_{object_id}: *resume_scene_after_duration`.
# This script handles each 'timer' for each entity that is turned on. Doing this gives
# us the ability to cancel each 'resume' with a trigger of some sort (like double tap).
# You also need to add the entity to the trigger in cancel_scheduled_resume_state.
metadata:
binary_sensor.porta_sala:
entities:
- light.sala_estar
duration: 60
input_boolean.test_door:
entities:
- input_boolean.test_switch
- input_boolean.test_switch_2
duration: 10
valid: >
{{ trigger | default(none) is not none and trigger.to_state is defined and trigger.from_state is defined }}
source: >
{%- if valid %}
{{ trigger.to_state.entity_id }}
{%- endif %}
timestamp: >
{%- set datetime = datetime | default(now()) %}
{{ as_timestamp(datetime) | timestamp_custom("%Y-%m-%dT%H:%M:%S.%f+00:00", datetime.tzinfo == 'UTC') }}
object_id: >
{{ source.split('.')[-1] }}
sensor: >
sensor.{{ object_id }}_last_opened
script: >
script.resume_{{ object_id }}
last_opened: >
{{ states(sensor) | default('') }}
# Make entities object for scene
current: >
{%- if valid and source in metadata %}
{{ metadata[source] }}
{%- endif %}
snapshot_entities: >
{{ current.entities | default([]) }}
action_data: >
{%- macro kvp(k, v) %}{{ '"{}"'.format(k) }}: {{ '"{}"'.format(v) if v is string and not (v.startswith('{') or v.startswith('['))else v }}{% endmacro %}
{%- macro coll(item, t='curly') %}{{ '{}{}{}'.format('{' if t == 'curly' else '[',item | join(', ') if item is iterable and item is not string else item, '}' if t == 'curly' else ']') }}{% endmacro %}
{%- set ns = namespace(entities=[], scene_ids=[], scripts=[]) %}
{%- set brightness = current.brightness | default(255) %}
{%- for entity in snapshot_entities %}
{%- set ns.scripts = ns.scripts + [ '"script.resume_{}"'.format(entity.replace('.','_'))] %}
{%- set ns.scene_ids = ns.scene_ids + [ '"{}"'.format(entity.replace('.','_'))] %}
{%- if entity.startswith('light.') %}
{%- set ret = [kvp('state', 'on'), kvp('brightness', brightness)] %}
{%- else %}
{%- set ret = kvp('state', 'on') %}
{%- endif %}
{%- set ns.entities = ns.entities + [ kvp(entity, coll(ret)) ] %}
{%- endfor %}
{%- set ret = [ kvp('entities', coll(ns.entities | join(','))), kvp('scripts', coll(ns.scripts | join(','), 'list')), kvp('scene_ids', coll(ns.scene_ids | join(','), 'list'))] %}
{{ coll(ret) }}
duration: >
{{ current.duration | default(0)}}
delta: >
{%- set last = as_timestamp(last_opened) %}
{%- if last is not none %}
{{ as_timestamp(timestamp) - as_timestamp(last_opened) }}
{%- else %}
{{ duration + 1 }}
{%- endif %}
in_duration: >
{{ delta < duration }}
condition: &sun_door_condition
- condition: template
value_template: "{{ valid }}"
- condition: state
entity_id: sun.sun
state: "below_horizon"
action:
- choose:
- conditions:
- condition: template
value_template: "{{ not in_duration }}"
sequence:
- repeat:
count: "{{ action_data.scene_ids | length }}"
sequence:
- service: scene.create
data:
scene_id: "{{ action_data.scene_ids[repeat.index - 1] }}"
snapshot_entities: "{{ snapshot_entities[repeat.index - 1] }}"
- service: scene.apply
data:
entities: "{{ action_data.entities }}"
- wait_template: "{{ is_state(source, 'off') }}"
- repeat:
count: "{{ action_data.scripts | length }}"
sequence:
- event: illuminate_door
event_data:
service: "{{ action_data.scripts[repeat.index - 1] }}"
duration: "{{ duration }}"
scene_id: "{{ action_data.scene_ids[repeat.index - 1] }}"
Door event handler
This handles everything so that itās async. Meaning, you can add other doors to the previous automation and itāll still work without waiting for other door ātimersā. You donāt need to configure anything here. Itāll just run in the background.
This automation allows you to cancel the turn off events by just using the switch. If you have a switch that supports double tap actions, change the trigger to a double tap trigger. I do not have switches that support this, so I have to turn the light off then on in order for it to stay on.
- alias: Doors - Cancel Scheduled Resume State
id: cancel_scheduled_resume_state
mode: parallel
trigger:
- platform: state
entity_id:
- light.sala_estar
# - input_boolean.test_switch
# - input_boolean.test_switch_2
variables:
valid: >
{{ trigger | default(none) is not none and trigger.to_state is defined and trigger.from_state is defined }}
source: >
{%- if valid %}
{{ trigger.to_state.entity_id }}
{%- endif %}
script: >
{{ 'script.resume_{}'.format(source.replace('.','_')) }}
condition: *sun_door_condition
action:
- service: script.turn_off
target:
entity_id: "{{ script }}"
Scripts
Unfortunately, this method requires a script for every light. Without it, the duration doesnāt work and the automations will sit and wait until the lights turn off. We donāt want them to wait, we want the automations to continue (remember async). The script needs to be named resume__<object_id>. So if your entity_id is light.sala_estar, then the script name will be resume_light_sala_estar. The nice thing is, if you can use anchors to duplicate the script with a single line. Thatās shown below with the test switches and the script for your light.
# Script 1: The 'anchor'
resume_light_sala_estar: &resume_scene_after_duration
mode: restart
fields:
duration:
description: Duration that we have to wait before sending the notification
example: 60
scene_id:
description: Id of the scene
example: scene_a_or_b
sequence:
- delay: "{{ duration }}"
- service: scene.turn_on
target:
entity_id: scene.{{ scene_id }}
# Script 2: Using the 'anchor'
resume_input_boolean_test_switch: *resume_scene_after_duration
# Script 3: Using the 'anchor' again
resume_input_boolean_test_switch_2: *resume_scene_after_duration
You can checkout the automation in my github. Itās essentially the same however it manages 3 doors.
Sooooo, through all the time that Ive been trying to make this work, my dad failed to mention that he had a scene to turn that light off via ewelink
My automation works perfectly, and so does all the othersā¦
Anyway, I really didnt need all the trouble with the input_boolean, like @atomicpapa said, so I kept it simple, now that everything works the way it should.
- alias: ligar sala estar quando abrir porta sala a partir do por do sol
trigger:
platform: state
entity_id: binary_sensor.porta_sala
to: 'on'
condition:
- condition: state
entity_id: sun.sun
state: "below_horizon"
- condition: state
entity_id: light.sala_estar
state: "off"
action:
- service: light.turn_on
entity_id: light.sala_estar
- delay:
minutes: 1
- service: light.turn_off
entity_id: light.sala_estar
Im so sorry for the trouble and thank you guys for your time!