How to turn light off after triggered by motion sensor?

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.

1 Like

Entity Controller from HACS does this sort of thing.

1 Like

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 have an automation which basically says:

When motion is clear for 5 minutes then turn off light.

Here is my automation (I am using the motion sensor on my front door bell for me)

alias: >-
  Lights-Turn Off Front Porch Light When Front Door Cam Motion Stops for 5
  Minutes
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.ds_hd1_cell_motion_detection
    from: "on"
    to: "off"
    for:
      hours: 0
      minutes: 5
      seconds: 0
action:
  - service: switch.turn_off
    target:
      entity_id:
        - switch.front_porch
    data: {}
mode: parallel
max: 10

I have a separate automation that turns on the lights when motion is detected.

1 Like

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.

I’m using it with 2023.10.3, no problems - I see the last update on Github was two months ago.

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:

variables:
  previous_switch_state: "{{ states('switch.aqara_switch_top_floor_bathroom_switch') }}"

Then at the end of the automation you set the switch back to its original state

      - service: switch.turn_{{previous_switch_state}}
        data: {}
        target:
          entity_id: switch.aqara_switch_top_floor_bathroom_switch

You may need to use light.turn_on or homeassistant.turn_on (or off).

1 Like

And the third, and possibly easiest option.
When the automation fires, use a condition to check if the lights are already on. If so, stop.

2 Likes

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…

This is my config:

entity_controller:
  back_yard_motion_light:
    sensors: 
      - binary_sensor.back_yard_motion_detected
      - binary_sensor.front_yard_motion_detected
    sensor_type: duration
    entities:
      - light.south_wall_lights_light
      - light.patio_string_lights
      - light.front_porch
      - light.garage_outdoor_lights
    delay: 120

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 :slight_smile:

So there were two approaches I mentioned above, the first was using a temporary scene, and the second was using variables.

The temporary scene is probably the easiest to do, and this is an example of how you might do it:

description: ""
mode: single
trigger:
  - platform: state
    entity_id:
      - binary_sensor.kitchen_motion_sensor_group
    to: "on"
condition: []
action:
  - service: scene.create
    data:
      snapshot_entities:
        - light.kitchen_light_1
        - light.kitchen_light_2
      scene_id: kitchen_lights_current_state
  - service: light.turn_on
    data:
      kelvin: 3500
      brightness: 255
    target:
      entity_id: light.kitchen_light_group
  - delay:
      hours: 0
      minutes: 5
      seconds: 0
      milliseconds: 0
  - service: scene.turn_on
    target:
      entity_id: kitchen_lights_current_state
    metadata: {}

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:

description: ""
mode: single
trigger:
  - platform: state
    entity_id:
      - binary_sensor.kitchen_motion_sensor_group
    to: "on"
condition:
  - condition: state
    entity_id: light.kitchen_light_group
    state: "off"
action:
  - service: light.turn_on
    data:
      kelvin: 3500
      brightness: 255
    target:
      entity_id: light.kitchen_light_group
  - delay:
      hours: 0
      minutes: 5
      seconds: 0
      milliseconds: 0
  - service: light.turn_off
    data: {}
    target:
      entity_id: light.all_kitchen_light_group

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.

1 Like

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
1 Like

I also found that Entity Controller has the exact same problem: Feature Request - option to disable motion trigger during timeout · Issue #40 · danobot/entity-controller · GitHub

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.