Advanced Automation for PIR triggering on with timed turning off

Hey all,

Have been an on and off Home Assistant user for a couple of years, but now I’m going to really get into it :slight_smile:

I have a few smart plugs and bulbs around my house, which are set up through SmartLife app - I’ve set up Tuya and can see them in my set up.

I recently bought a PIR sensor that I want to set up in my porch - to turn the lights on. I could understand how I would do this, but I need a bit more complex config. Rather than me poking and hacking my way through, I thought I would seek advice of seasoned “professionals” in the best way of approaching this.

My porch lights are smart bulbs and are currently programmed to come on at 3:30 and go off at 11. I will be changing this to turning on 80 minutes before sunset soon.

I would like the PIR to sit in the porch and, if triggered, turn on the porch lights. I then want them to turn off after 5 minutes. However, I don’t want this to happen if they were already on. Ideally, I also don’t want this to happen if they were supposed to turn on just after they were triggered, but I can live with this if this is the case.

WHat is the best way of doing this?

To summarise:

  • Turn on when the PIR is triggered
  • Turn off 5 minutes after the PIR turned them on
  • Come on at 80 minutes before sunset
  • Turn off at 11.

I would assume I could have the turn on/turn off timed and then have those times reversed as an exception to the PIR triggering. The main thing I’m struggling with is the turning off after 10 minutes.

Would prefer to do it all through the GUI if possible.

Hope this all makes sense!

I don’t use Hass.io, so not quite sure what you can do ‘through the gui’. I assume you can modify config files?

Either way, I’ll explain what I do so you should be able to replicate in the gui, then I’ll show some configs I use to handle it. Here are the steps I did for my own lights:

First, create a script that turns the lights on and off for X minutes. I use a script rather than a wait_condition in the action, but either could work. I like the script so I can manually turn on the outdoor lights for X minutes with other automations or buttons easily without duplicating the actions.

Next, create an automation for the PIR as the trigger with a conditional that the lights are off. If this fires, it runs the script. The conditional makes it so if the lights were already on, the script wont run and turn them off after X minutes.

Then you have one more automation looking at sunset and turning on the lights, and one more automation looking at time and turning them off.

Create a script similar to this (name it whatever you want and update the entity_ids to match)

# Turns on the outdoor_lights for 10 minutes,
# then turns them back off.
yard_lights_on_for_10_mins:
  sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.outdoor_lights
    - delay:
        minutes: 10
    - service: switch.turn_off
      data:
        entity_id: switch.outdoor_lights

(If you want to get fancy, create the script to take input variables so you can call it with any amount of delay from various automations)

Now I just call this in automations.

- alias: Auto Porch Light
  trigger:
    - platform: state
      entity_id: binary_sensor.porch_pir_entity_id
      to: 'on'
  condition:
    condition: state
    entity_id: switch.outdoor_lights
    state: 'off'
  action:
    service: script.yard_lights_on_for_10_mins

This will only turn the lights off if the lights were off to begin with.

Finally, turn on at sunset and off at 11 pm. I actually picked 1 hour after sunset so it’s actually a little dark, but you don’t need the offset.

Also, when this condition fires, it will cancel the 10 minute timer script if that is running so it wont auto shut off in the event there was motion within 10 minutes of sunset.

- alias: Porch light on sunset
  trigger:
    - platform: sun
      event: sunset
      offset: "-01:00:00"
  action:
    - service: switch.turn_on
      entity_id: switch.outdoor_lights
    - condition: 
        condition: state
        entity_id: script.yard_lights_on_for_10_minutes
        state: 'on'
    - service: homeassistant.turn_off
      entity_id: script.yard_lights_on_for_10_minutes

Turn off at 11 pm.

- alias: Porch light off at night
  trigger:
    - platform: time
      at: "23:00:00"
  condition:
    condition: state
    entity_id: switch.outdoor_lights
    state: 'on'
  action:
    service: switch.turn_off
    entity_id: switch.outdoor_lights
1 Like

That is perfect, thank you.

I’ll have a proper read through when I’m next at my computer, but seems to do everything that I need it to :+1:

Thanks again!

Hi! I tried to do as you described above but for some reason the automation works only once and after 10 minutes the light turns off even though the PIR sensor is triggered, and the script does not start counting time again! Or am I doing something wrong?

Script
'1579430418417':
  alias: led_bedroom_on_10_minuts
  sequence:
  - device_id: 11582a2a3c7a4ec68b3d524f713b43cf
    domain: switch
    entity_id: switch.sonoff_basic_relay
    type: turn_on
  - delay: 00:10:00
  - device_id: 11582a2a3c7a4ec68b3d524f713b43cf
    domain: switch
    entity_id: switch.sonoff_basic_relay
    type: turn_off
automations
- id: '1579431333123'
  alias: Light on PIR
  description: ''
  trigger:
  - entity_id: binary_sensor.pir_sensor
    platform: state
    to: 'on'
  condition:
  - condition: state
    entity_id: switch.sonoff_basic_relay
    state: 'off'
  - after: '17:58:00'
    before: '21:00:00'
    condition: time
  action:
  - data: {}
    entity_id: script.1579430418417
    service: script.turn_on

You only have 1 automation that says “if there is motion and the light is off, turn on the script”.

A few things:

  1. This will not reset the script timer if it were to fire again.

  2. This wont ever fire again because the switch.sonoff_basic_relay is going to be on for those 10 minutes. Thus, the condition that the switch be off will stop it from executing the script again.

If you want a light that will turn on as long as there is motion, you don’t need the fancy scripts. Just do a single automation that waits to see if the motion sensor has been ‘off’ for X minutes.

Make sure you look up how often the motion sensor triggers. Some will only trigger once every X minutes to save battery!

- id: '999999999999'
  alias: 'Light off no Motion'
  description: 'Turns of the lights if no motion for some time'
  trigger:
  - entity_id: binary_sensor.pir_sensor
    platform: state
    to: 'off'
    for:
      minutes: 15
  action:
    service: switch.turn_off
    entity_id: switch.sonoff_basic_relay

This 2nd automation will wait for no motion for 15 minutes. Every time the motion detector gets triggered, it will essentially reset this 15 minute timer.

So, one automation to turn on the lights with motion, and this one to turn them off.

- id: '1579431333123'
  alias: Light on PIR
  description: ''
  trigger:
  - entity_id: binary_sensor.pir_sensor
    platform: state
    to: 'on'
  condition:
  - condition: state
    entity_id: switch.sonoff_basic_relay
    state: 'off'
  - after: '17:58:00'
    before: '21:00:00'
    condition: time
  action:
    service: switch.turn_on
    entity_id: switch.sonoff_basic_relay
1 Like

Thanks. I will try the last time I did similar automation but I had the same effect so I noticed that you have made a script! But perhaps not correctly understood!

No problem.

The script I wrote will turn the lights on for 10 minutes always, then turn it off.

Then, if there is another motion event, it will happen again. It’s good for a security light type things, but not very useful for indoors lights where you might want the off timer to reset!

I set up an input_select for all of my motion-activated lights like this:

input_select:
  family_lamps:
    options:
      - Turn-on
      - Turn-off
      - Motion-night
      - Motion-always
  office_desk:
    options:
      - Turn-on
      - Turn-off
      - Motion-night
      - Motion-always

Then I use lovelace switches, automations, scripts etc. to change the input variable.

I use Node-RED for logic. Whenever the PIR is violated, check the value of the input_select and act accordingly (night is determined by lat-long). Whenever the input_select is changed, act accordingly. If you are interested in Node-RED, I could post my flow.

Your option is interesting! Please publish it.

Import this into Node RED. You’ll need to add node-red-contrib-stoptimer node if you’re not already using it.

[{"id":"c83c319f.4b525","type":"server-state-changed","z":"3f92b85e.3e3788","name":"Media PIR","server":"2bcf671a.f2b3c8","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.1_media_pir","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"Violated","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":false,"x":160,"y":1080,"wires":[["90e22b2b.ced778"],[]]},{"id":"18542eb6.37db31","type":"api-call-service","z":"3f92b85e.3e3788","name":"Media Counter","server":"2bcf671a.f2b3c8","version":1,"debugenabled":false,"service_domain":"switch","service":"{{payload}}","entityId":"switch.shelly_17","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1260,"y":1020,"wires":[[]]},{"id":"c074a420.7931c8","type":"time-range-switch","z":"3f92b85e.3e3788","name":"If Dark","lat":"33.955","lon":"-84.45487","startTime":"dusk","endTime":"dawn","startOffset":"-60","endOffset":"+60","x":610,"y":1020,"wires":[["713dc12b.b0db9","62a4246e.34cf0c"],[]]},{"id":"24d81bfa.cd2274","type":"stoptimer","z":"3f92b85e.3e3788","duration":"120","units":"Second","payloadtype":"str","payloadval":"","name":"Timed Off","x":1020,"y":1160,"wires":[["18542eb6.37db31"],[]]},{"id":"713dc12b.b0db9","type":"change","z":"3f92b85e.3e3788","name":"turn_on","rules":[{"t":"set","p":"payload","pt":"msg","to":"turn_on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":1020,"wires":[["18542eb6.37db31"]]},{"id":"255276e2.49bb3a","type":"change","z":"3f92b85e.3e3788","name":"Stop Timer","rules":[{"t":"set","p":"payload","pt":"msg","to":"stop","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":1160,"wires":[["24d81bfa.cd2274"]]},{"id":"62a4246e.34cf0c","type":"change","z":"3f92b85e.3e3788","name":"turn_off","rules":[{"t":"set","p":"payload","pt":"msg","to":"turn_off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":1060,"wires":[["24d81bfa.cd2274"]]},{"id":"f986117c.e73a1","type":"server-state-changed","z":"3f92b85e.3e3788","name":"Media Mode","server":"2bcf671a.f2b3c8","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_select.media_counter","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":270,"y":1140,"wires":[["d3d0cc92.11978","255276e2.49bb3a"]]},{"id":"d3d0cc92.11978","type":"switch","z":"3f92b85e.3e3788","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"Turn-on","vt":"str"},{"t":"eq","v":"Turn-off","vt":"str"},{"t":"cont","v":"Motion","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":710,"y":1100,"wires":[["713dc12b.b0db9"],["d0c1ab2d.ac7418"],["d0c1ab2d.ac7418"]]},{"id":"d69d39f9.c144d8","type":"switch","z":"3f92b85e.3e3788","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"Motion-night","vt":"str"},{"t":"eq","v":"Motion-always","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":430,"y":1080,"wires":[["c074a420.7931c8"],["713dc12b.b0db9","62a4246e.34cf0c"]]},{"id":"90e22b2b.ced778","type":"api-current-state","z":"3f92b85e.3e3788","name":"Mode","server":"2bcf671a.f2b3c8","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_select.media_counter","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":310,"y":1080,"wires":[["d69d39f9.c144d8"]]},{"id":"d0c1ab2d.ac7418","type":"change","z":"3f92b85e.3e3788","name":"turn_off","rules":[{"t":"set","p":"payload","pt":"msg","to":"turn_off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":1100,"wires":[["18542eb6.37db31"]]},{"id":"2bcf671a.f2b3c8","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Thank you very much!

Thanks, @RichardU - I prefer NodeRed, so easy to troubleshoot that automation.

I’ve since upped my PIR game with a bunch of triggered lights (motion and otherwise) that go on when I want, stay on when I want, and not when I don’t, and can be controlled by voice, dashboard, or light switch.