Lights on AND off with multiple PIR sensors in a single automation

Hello,

I have this automation, and what I want to is that the ligts go on if one of the two PIR sensors are triggered. The light should be turned off after 30 seconds unless motion is still detected.

Is seems to work fine, but sometimes when I’m in the garage for a longer time, the light goes out and won’t turn on again.

Anyone who sees the problem?
[edited to clarify the question]

- id: garagelights
  alias: Garagelampen
  mode: restart
  trigger:
    - platform: state
      entity_id: 
        - binary_sensor.pir_sensor_garage1
        - binary_sensor.pir_sensor_garage2
  action:
    - choose:
        # IF motion detected
        - conditions:
            - condition: template
              value_template: "{{ trigger.to_state.state == 'on' }}"
          sequence:
            - service: homeassistant.turn_on
              entity_id: switch.garage_lights 
      # ELSE (i.e., motion stopped)
      default:
        - delay: 00:00:30
        - service: homeassistant.turn_off
          entity_id: switch.garage_lights

Er ! No … you joined in May 2020, have read 1 hour and only 1 minute of that recently.
Apart from the ‘taunt’ to prove our prowess why should we (or me in particular) contribute ?

You haven’t actually described your problem nor how you expect this automation to work.
Why should I guess when you have all the answers.

The one thing I will say is that ‘choose’ was soooooo 0.112 don’t you know that everyone is using blue prints now ! [That was sarcasm, you need neither]

If you don’t want to help, fin, the don’t reply.
And the numbers you’re referring to… only sums up if logged in.

1 Like

what’s the problem with the automation? looks fine to me. The only thing I would point out is that you’re using ‘homeassistant.turn_on’ when you should probably use ‘switch.turn_on’ and ‘switch.turn_off’.

does your device have any quirks? Some motion sensors can only sense motion for specific periods.

If the PIR sensor 1, is triggered, which is a sensor connected to a Wemos, the light turns on and stays on while I’m moving (geep triggering).
When the second sensor is triggered, which is a Aquara sensor, the light goes off after 30 seconds, even thou the state of the sensor is on.

Now that I’m writing this, I think is has something to do with the way that sensor communicates with HA.

Looking at your automation, it seems that you have two motion sensors in the garage. The default section of your choose block will execute when one of those motion sensors stops detecting movement.

This means in a scenario where you pass through one sensor, and then stay in the field of the second sensor, the first sensor will stop detecting motion and trigger the automation to turn the light off. The second motion sensor (that you are still triggering) is not causing any state changes, so to activate the automation again you would have to walk through the path of the first sensor, to trigger it again, causing a state change and firing the automation to turn the light on. At which point the second sensor will stop detecting motion and turn the light off again!!

My suggestion would be to remove the default section and make it another set of conditions that ensures both motion sensors are off.

This is obviously assuming that wherever you are at least one of the sensors will detect you, and that you aren’t standing completely still!

That shouldn’t happen with restart as the mode.

Exactly. When the restart mode was introduced I immediately found a good use case.

@petro were you replying to me or RuSm?

I may be misunderstanding something here, but with the automation running as restart I would imagine it flows like this:

PIR 1 Triggered - Automation triggered and turns light on

PIR 2 Triggered - Automation triggered so restarts (and turns light on again)

PIR 1 Stops detecting motion - Automation triggered and turns light off after 30 seconds

Nothing happens now as PIR 1 is not detecting any motion and PIR 2 is constantly detecting motion so no state changes are occurring to trigger the automation.

1 Like

Ah yes, that would happen. I had trouble following your explanation.

I did realise after I’d posted that it was a little hard to follow, so basically wrote the same thing, but clearer! I think that this can be solved if conditions are used to ensure both motion sensors are clear before the light turns off.

1 Like

Right! Now I understand the scenario. Good one!
Think I can fix that by adding a delay of 30 sec and the turning the lights off to the ‘on’ event, and remove the default.

The only thing is that one of the two PIR sensors has a timeout of 90 sec. (Xiaomi/Aquara).

So with what @charlyr said, this should probably get the job done:

- id: garagelights
  alias: Garagelampen
  mode: restart
  trigger:
    - platform: state
      entity_id: 
        - binary_sensor.pir_sensor_garage1
        - binary_sensor.pir_sensor_garage2
  action:
    - choose:
        # IF motion detected
        - conditions:
            - condition: template
              value_template: >
                {{ expand('binary_sensor.pir_sensor_garage1', 'binary_sensor.pir_sensor_garage2') | selectattr('state','eq','on') | list | count == 0 }} 
          sequence:
            - delay: 00:00:30
            - service: homeassistant.turn_off
              entity_id: switch.garage_lights
      # ELSE (i.e., motion stopped)
      default:
        - service: homeassistant.turn_on
          entity_id: switch.garage_lights 
5 Likes

That looks like quite an elegant solution, but it makes me think about how I write my templates.

I notice at the end of the condition you use
selectattr('state','eq','on') | list | count == 0

In my templates I would usually write this as selectattr('state','eq','on') | first != null

It is my understanding that first is a filter that will “short circuit” the evaluation. selectattr returns a generator, first will stop iterating the generator as soon as any entity matches the test (in this case is on). The full list of entities is only iterated through if none of them match the test.

I realise in this situation with only two entities there is no benefit to writing it my way, but out of habit I write it this way, as when there is a large list of entities you don’t need to evaluate the entire list of entities if any of them match the test the condition fails straight away.

Thanks for pointing me into the right direction @petro and @charlyr, helped a lot.
Together with the change in the automation, I found out that I can change the interval of the Xiaomi/Aquara (RTCGQ01LM) interval via Zigbee2Mqtt’s config by setting the occupancy_timeout to a custom value (10 in my case). Docs here and a lot easier than the hardware mod that can be found elsewhere.
Will test it in the upcoming days for real.

So, what did you end up using?
I want a similar setup for my bathroom as the light opens for 2 mins when triggered, but when we shower it takes more than two minutes and the lights go out… i will install a second pir to circumvent that but I have no clue how to do the code for it, and i’m quite a beginner in coding in general, so nay help would be appreciated.

thanks

I ended up with this, but not completely happy with it.
Still on the todo list: adding a delay of 1 minute before the lights turn off. The other option I have is to move the sensor so there are no blind spot anymore.

- id: gragelights
  alias: Garagelampen aan/uit
  mode: restart
  trigger:
    - platform: state
      entity_id: 
        - binary_sensor.pir_sensor_garage
        - binary_sensor.bewegingsmelder_garage_occupancy
  action:
    - entity_id: switch.garage_lampen
      service: > 
        {% if states('binary_sensor.pir_sensor_garage') == 'off' and states('binary_sensor.bewegingsmelder_garage_occupancy') == 'off' %}
          homeassistant.turn_off
        {% else %}
          homeassistant.turn_on
        {% endif %}

Is your problem now really a blindspot? These sensors have varying dead times when they detect nothing. To see that at work add your sensor to a pane in Lovelace and watch it. See how long each one takes to go from motion detected to idle and back to motion detected. My Aquaria sensors have almost 1.5 minutes where they do not detect, no matter how much motion is in front of them.

Yes it is… when I’m in the garage, and open a door of a locker, the sensor gets blocked partially.
Not so sure how to add a delay in this though. Maybe I need to split the automation of make two scripts. Working on it right now.

If it helps, here is how I deal with timing and delays… Totally different scenario.

- id: Bathroom motion
  alias: Bathroom motion
  trigger:
    - platform: state
      entity_id: binary_sensor.motion_sensor_158d0001644ca3
      from:
        - 'on'
      to:  
        - 'off'
    - platform: state
      entity_id: binary_sensor.motion_sensor_158d0001644ca3
      from:
        - 'off'
      to:  
        - 'on'
  mode: restart
  action:
    - choose:
        - conditions:
            - condition: template
              value_template: "{{ trigger.to_state.state == 'on' }}"
            - condition: time
              after: '06:00:00'
              before: '23:00:00'
            - condition: state
              entity_id: timer.bathroom_motion_short
              state: 'idle'
          sequence:
            - service: light.turn_on
              entity_id:  group.bathroom_lights
              data:
                brightness: 254
            - service: timer.start
              entity_id: timer.bathroom_motion_long
        - conditions:
            - condition: template
              value_template: "{{ trigger.to_state.state == 'on' }}"
            - condition: state
              entity_id:  timer.bathroom_heat_tag
              state: 'idle'
            - condition: state
              entity_id: input_boolean.notify_bathroom_tag
              state: 'off'
            - condition: time
              after: '23:00:00'
              before: '06:00:00'
          sequence:
            - service: light.turn_on
              entity_id:  light.bathroom_1,light.toolbox,light.sink,light.tree_top
              data:
                brightness: 15
            - service: timer.start
              entity_id: timer.bathroom_motion_short


- id: Bathroom long timer expired
  alias: Bathroom long timer expired
  trigger:
    - platform: event
      event_type: timer.finished
      event_data:
        entity_id: timer.bathroom_motion_long
  condition: 
    condition: template
    value_template: >
      {{ not is_state('timer.bathroom_heat_tag','active') }} 
  action:
  - service: light.turn_off
    entity_id: group.bathroom_lights
    
- id: Bathroom short timer expired
  alias: Bathroom short timer expired
  trigger:
    - platform: event
      event_type: timer.finished
      event_data:
        entity_id: timer.bathroom_motion_short
  action:
    - choose:
        - conditions:
            - condition: time
              after: '06:00:00'
              before: '23:00:00'
          sequence:
            - service: light.turn_off
              entity_id: group.bathroom_lights
        - conditions:
            - condition: time
              after: '23:00:00'
              before: '06:00:00'
          sequence:
            - service: light.turn_off
              entity_id: group.bathroom_lights,light.tree_top,light.sink
1 Like