Motion Sensors, Timers and Restoring State

I’ve a motion sensor, outdoor (colour) light and a timer configured in Home Assistant.

Basically I want the following scenario:

If motion is detected:
Record the current state of the light (colour and brightness)
Turn on the light to a specific brightness and make it white
Start a 2 minute countdown

If motion is detected whilst the existing timer is running
Reset the countdown to 2 minutes

If the countdown expires
Restore the original light state (could be a colour, or maybe off)

I have the following automation configured:

- alias: Front Garden Motion
  hide_entity: true
  initial_state: true
  trigger:
    - platform: state
      entity_id: binary_sensor.front_garden_motion_motion
      from: 'off'
      to: 'on'
  condition:
    - condition: numeric_state
      entity_id: sensor.front_garden_motion_light_level
      below: 500
  action:
    - service: timer.start
      entity_id: timer.garden_light

- alias: Front Garden Light Timer Started
  trigger:
  - platform: event
    event_type: timer.started
    event_data:
      entity_id: timer.garden_light
  action:
  - service: scene.create
    data:
      scene_id: garden_before
      snapshot_entities:
      - light.garden
  - service: hue.hue_activate_scene
    data:
      group_name: Garden
      scene_name: Bright

- alias: Front Garden Light Timer Stopped
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.garden_light
  - platform: event
    event_type: timer.cancelled
    event_data:
      entity_id: timer.garden_light
  action:
  - service: scene.turn_on
    data:
      entity_id: scene.garden_before

According to the documentation (https://www.home-assistant.io/integrations/timer/#service-timerstart) this should work fine since the timer will be restarted at its original value.

However it appears Timers are in fact broken (https://github.com/home-assistant/home-assistant/issues/12013) as when service.start is invoked on a timer it actually doesn’t restart.

To get the countdown timer to reset to 2 minutes I could instead have the following action:

  action:
    - service: timer.cancel
      entity_id: timer.garden_light
    - service: timer.start
      entity_id: timer.garden_light

But this has the downside of triggering a state change and an event which means my scene.create action where I attempt to record the original light state is now overwritten by the ‘bright’ state.

I did try introducing a condition in the ‘Brighten the Garden’ automation by ensuring the timer has remained in an idle state for 2 seconds before invoking scene.create, but this has no effect since the condition will fail as the timer will now be ‘active’.

- alias: Brighten the Garden
  hide_entity: true
  initial_state: true
  condition:
    - condition: state
      entity_id: timer.garden_light
      state: "idle"
      for:
        seconds: 2
  trigger:
    - platform: state
      entity_id: timer.garden_light
      from: "idle"
      to: "active"
  action:
    - service: scene.create
      data:
        scene_id: garden_before
        snapshot_entities:
          - light.garden
    - service: hue.hue_activate_scene
      data:
        group_name: Garden
        scene_name: Bright

So… I’m kind of stuck - I can’t implement my above scenario which stores the existing state of a scene. I can only really set the light to an explicit state at the beginning and end of a timer and call ‘cancel and start’ one after the other.

Can anyone else suggest a method to achieve the scenario outlined at the beginning?

Hmmm - after writing this, I wonder if I should set some kind of boolean during the start the garden light timer automation. A bit lilke:

  action:
    //set a temporary boolean value and clear after 10 seconds
    - service: timer.cancel
      entity_id: timer.garden_light
    - service: timer.start
      entity_id: timer.garden_light

Then in the brighten the garden automation, just check the state of that boolean value in a condition. I suppose it could be a script with a simple delay in it.

  action:
    - service: script.turn_on
      entity_id: scripts.blacklisted_garden_scene
    - service: timer.cancel
      entity_id: timer.garden_light
    - service: timer.start
      entity_id: timer.garden_light
- alias: Brighten the Garden
  hide_entity: true
  initial_state: true
  condition:
    - condition: state
      entity_id: script.blacklisted_garden_scene
      state: "off"
script:
  blacklisted_garden_scene:
    sequence:
      - delay:
          seconds: 10

This seems a little hacky - what do people suggest?

This doesn’t work either, because it needs to be allowed the first time - I wonder if I can delete the ephemeral scene that is created and use that as a condition instead - i.e. replace if it doesn’t already exist.

“…what to people suggest?”

Nodered for all automations.

1 Like

Or reading the documentation. No timers required in this example that can be modified to suit your needs:

That example doesn’t attempt to restore the existing state of the entity. So in my case, my outdoor light might be on, dim or off - it may even be a different colour.

I want it to go bright white for 2 minutes, then back to what it was. This would be significantly easier if I weren’t attempting to use the scene.create facility and just explicitly set the value of the light after the timer has finished.

That example shows how to easily implement a motion activated light. In the actions instead of on / off use the scene create / restore services you have already used above to accomplish your needs. No input boolean or timers required.

In the on / motion detected automation save your temporary scene and then adjust the lights how you want.

In the off / no motion automation restore your saved scene. Set the for: trigger to the time you want this to last.

EDIT: actually that will overwrite the before scene with the bright settings when motion repeats. You will need to set an input boolean and use it as a condition to prevent this. I’ll help you write this later, hard to do on mobile.

EDIT 2: Try this:

Input booleans:

input_boolean:
  name: scene_saved

Automations:

- alias: 'Brighten the Garden'
  trigger:
    platform: state
    entity_id: binary_sensor.front_garden_motion_motion
    to: 'on'
  condition:
    condition: state
    entity_id: input_boolean.scene_saved # prevents overwriting the before scene with the bright scene on motion repeat
    state: 'off'
  action:
  - service: scene.create
    data:
      scene_id: garden_before
      snapshot_entities:
      - light.garden
  - service: hue.hue_activate_scene
    data:
      group_name: Garden
      scene_name: Bright
  - service: input_boolean.turn_on  # to prevent overwriting the before scene with the bright scene on motion repeat
    entity_id: input_boolean.scene_saved

- alias: 'No Motion Restore Garden Lights'
  trigger:
    platform: state
    entity_id: binary_sensor.front_garden_motion_motion
    to: 'off'
    for:
      minutes: 2
  action:
  - service: scene.turn_on
    data:
      entity_id: scene.garden_before
  - service: input_boolean.turn_off  # allow saving of the before scene again.
    entity_id: input_boolean.scene_saved

This will help out with the restoration of a previous light state:

Thanks, that seems to have done the trick. Inverting the countdown from being started on motion to ‘no motion’ is the important leap.

Matches both scenarios of motion and extending duration of bright light after multiple motion events.

Whilst not quite necessary, I think I can still use timers with this approach as well - a timer will be useful if I choose to couple a doorbell, gate sensor and motion sensors together.

But I don’t have all of that just yet, so this works very elegantly - thanks for the solution!!

1 Like

Thanks for the link to the docs - my example is using the snapshot_entities facility with the scene.create service, it’s a very cool feature!

Alternatively you could put all your trigger sources in a group and use the state of the group as the before / restore automations triggers, unless you want different times per trigger source.