This sounds like a very basic task, but I’m struggling to figure out how to do it nicely.
I have motion sensors in the front and back yard. When either one senses motion, I want to turn on all the outdoor lights (4 separate lights), only if the sun is down. That part is working fine.
Now the tricky part — when the motion sensor is clear for 2 minutes, I want these lights to turn off, but only if they were turned on by this automation. So if a light is on because someone manually switched it on, then it should remain on.
If Home Assistant offered a state attribute for “last turned on by” that would be one way to solve this. Then I could check that for each light and turn it off only if it was last turned on by the motion sensor automation.
There are a couple of other ways you could also do this.
Combine on and off in a single automation, so the automation looks something like:
Trigger if Motion
Conditiion check if sun is down
Set lights on
wait for 2 minutes
turn lights off
Or… if you want to keep on and off as a separate automations, use something like an input boolean (toggle) helper to turn on when the automation turns on the lights, and off when the lights are turned off, and use it as a condition in the off automation.
I would love to keep it tidy in a single automation, but I don’t think your example will work. With that config, the lights would all turn off after 2 minutes, even if they were switched on manually before the motion occurred.
@Stiltjack thanks! That HACS sounds like exactly what I’m looking for, although I’d prefer to do it natively. That integration says it was last tested on version 2022.7.4. So I guess I’ll have to stay several months behind release schedule if I want it to remain on the “paved path”.
Probably this could work using event trigger. I didn’t set this up in my automations but I was think recently about the same thing.
Sometimes is good to bypass automation if you want ie for light to stay on if you manually triggered the switch.
Then this is pretty easy. Use something like temporary scene to capture the state of the lights, and set the lights back to that state when the automation ends.
I do this with a bathroom automation I have.
The light is turned on when humidity reaches a certain threshold, and turns off 5 minutes later. If the light was already on before the automation runs, its returns it to that state.
You can do this either with a temporary scene, or set the value of the entity in a variable before the rest of the automation fires like so:
I tried setting this up with Entity Controller but I have a problem: If any one of the 4 lights is on when the motion triggers, Entity Controller enters blocked state and does not turn on any of the other lights. This history graph illustrates the problem. This integration looks pretty thorough so I’m guessing there is a way to achieve this, I’m still searching for it…
If you only want the automation to NOT fire if ALL the lights are already on, then create a binary sensor group with the lights in it and set the all entities slider to on, then use a simple condition to stop the automation if the binary sensor group is ‘on’.
Altermatively, if you want the automation NOT to fire if at least one light is on, don’t slide the ‘all entities’ slider to on.
I dont think you need to use the entity controller at all.
I join here with a simple request. I’m new to automation and I’m not yet capable of doing many things, so when I find interesting things I write them down and try to learn them.
This thing seems really very interesting, it would be useful in the kitchen when my wife always complains because she turns on a light but then if she doesn’t keep dancing around the house, the light turns off by itself and this makes her very angry. Unfortunately however, I am not able to do this, I have not understood where I should put these pieces. Can you paste a simple full automation that includes this capability?
I’m having a really hard time gluing the pieces together correctly and respecting all the spaces that yaml wants
This automation turns on the kitchen lights when motion is detected. But before it does anything, it records the current state of the kitchen lights.
The kitchen lights are then turned on (they may already be)
5 minutes later, they are returned to whatever state they were in before the automation ran, which again, could be to leave them on.
Another way you could do it is to check if the lights are already on when the motion sensors detects you, and if they are… do nothing, by stopping the automation with a condition:
One thing to remember tho… is that your light switch is usually in the room where the motion sensor is, so you might find you can’t manually turn on the lights before the motion sensor does it anyway. In this case, I’d take another approach, but this can get you started.
After a bunch of testing I think this is finally working using the temporary scene idea. Below is the automation I’m using now. When either sensor detects motion, it turns on all 4 lights, and then 2 minutes later restores the original state. Importantly — if the light state has changed in the last 5 seconds then it does not run.
alias: Outside - motion lights
description: >-
Turn on all outdoor lights when any camera detects motion, unless the motion
was caused by the lighting change
trigger:
- platform: state
entity_id:
- binary_sensor.front_yard_motion_detected
to: "on"
id: front
- platform: state
entity_id:
- binary_sensor.back_yard_motion_detected
to: "on"
id: back
condition:
- condition: sun
after: sunset
before: sunrise
before_offset: "01:00:00"
after_offset: "01:00:00"
- alias: Confirm string lights hasn't changed in 5 seconds
condition: or
conditions:
- condition: state
entity_id: light.patio_string_lights
state: "on"
for:
hours: 0
minutes: 0
seconds: 5
- condition: state
entity_id: light.patio_string_lights
state: "off"
for:
hours: 0
minutes: 0
seconds: 5
- alias: Confirm porch light hasn't changed in 5 seconds
condition: or
conditions:
- condition: state
entity_id: light.front_porch
state: "on"
for:
hours: 0
minutes: 0
seconds: 5
- condition: state
entity_id: light.front_porch
state: "off"
for:
hours: 0
minutes: 0
seconds: 5
action:
- service: scene.create
data:
scene_id: outside_lights_current_state
snapshot_entities:
- light.garage_outdoor_lights
- light.front_porch
- light.patio_string_lights
- light.south_wall_lights_light
alias: Save current state as temporary scene
- service: light.turn_on
data: {}
target:
entity_id:
- light.garage_outdoor_lights
- light.patio_string_lights
- light.front_porch
- light.south_wall_lights_light
alias: Turn on outdoor lights
- delay:
hours: 0
minutes: 2
seconds: 0
milliseconds: 0
- service: scene.turn_on
data: {}
target:
entity_id: scene.outside_lights_current_state
alias: Restore original state
mode: single
Just remind me why you need to check if the light was turned on (or off) in the last 5 seconds ?
Surely, because you are using the scene create function, the automation will return the lights to whatever state they were in before the automation fired ?
So if they were off before the automation fired, they will return to off (after being on for 2 minutes), and if they were already on, they will stay on after the automation ends.
I use that condition because the lights turning off/on makes the motion sensor think there was motion. So this way, if the motion sensor fires because of the lights turning on manually, the automation will not run.
This is simple. You can create this “attribute” yourself. All you need is a variable that you use to track if lights were turned on by the automation or not. So, if the lisghts were turned on by the automation you set the variable to True. Then you have a condition in your turn off logic which checks the state of this variable. If it’s True then you know you have to turn the lights off. And of course at that point you will set the variable to False.