Input sensor update sometimes too slow for logic relying upon it - workaround?

I HAD a situation where someone would turn a light off on their way out of a room - and the light would go back on due to the motion sensor catching them moving before they leave the room.

I (nearly) resolved this by, every time the light is turned off MANUALLY, to immediately put that exact datetime into an input_text (I had trouble getting it to work with an input_datetime) - then any automation acting upon the motion sensor to turn the light on, now has a condition that it would only turn the light back if the current datetime was more than 5 minutes after the value held in the input_text.

Especially with a wall switch for lights near a doorway, if someone turns off the switch while they are walking out of the room - the input helper value that is seen by the automation kicked off by the motion sensor - is not updated in time - so the lights still go back on!

Regarding possible solutions:

  1. Any delay in the automation logic to turn the lights on, cannot be done because if someone is walking into a dark room, the lights need to go as closely to immediately as possible.

  2. It is not yet possible due to a variety of reasons, to switch to more expensive motion detectors upon which I could rely that would always know when there are and are not people in the room. The current less expensive motion sensors in use will detect motion immediately, and that is cleared after one minute of no motion (including when someone is sitting still - but I already have that figured out).

So what are my options here for the walking out of the room wall switch kind of issue? Any way to store a value that is pretty much instantly available (rather than available .5 seconds or whatever it is after it is updated)?

This is a great question.

Have you tried checking the switches last_updated attribute in the automation triggered by the motion sensor?

A next step is to determine order of operation between the motion sensor updating and the switch updating. What I do is use a template like this. This will then allow you to have precise timestamps as to when the updates occur. For example is the switch is reporting off after the motion detector or vice versa?

template:
  - trigger:
      - platform: state
        entity_id: binary_sensor.garage_sensor_motion_detected
        from: "off"
        to: "on"
    sensor:
      - name: "ms_garage_trigger_time"
        state: "{{now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]}}"

If it turns out that the switch is slow to report. Meaning it takes 1 second between turning it physically off and HA getting the update, Then in your automation put a condition in to not turn the switch on if it is already on.

Thank you for the compliment and thoughtful answer! I have three kinds of light switches (three different rooms) I need to investigate with this -

  1. a Wemo in-wall dimmer switch (relies upon the cloud) - I have not encountered the problem with this one but that is a room not often used,
  2. many shelly relays (behind wall switches on Wifi with static IPs which I would think would be immediate but it has happened with a couple of them) and
  3. a Leviton Decora in-wall dimmer - which by default did rely upon the cloud - that had pretty bad latency - but also now supports matter and have switched over to that in HA for this switch - and is now instant - I used to but have not seen the issue with this since but will recheck and retest

I will do a little more investigating and let you know!

A simply solution might be to put a delay on the manually turn off function.

1 Like

In Settings → Developer Tools → Templates:

{{ states.light['dining_room_chandelier_matter'].last_changed }}
{{ as_datetime(states('input_text.last_manual_off_dining_room')) }}

that displays:

2023-10-04 14:59:54.665898+00:00
2023-10-04 14:59:47.751938+00:00

which is a head scratcher as the other way around was expected…still digging!

I’m with Wally on this one. Don’t let the turn_off from the switch turn off the light but rather start a script with it.

There you have various possibilities, from starting a timer and while it’s running, the motion sensor is “disabled” up to a simple delay at the beginning, where your script just waits with turning off the light, so the motion sensor is reacting before the turn off.

I wouldn’t work with a helper here, it is, as you already noticed, way to inaccurate. You never know what is happening in the state machine at that exact microsecond.

The only way to keep it in the way you describe would be to work with a modified timestamp, where you compare the two values only down to a second and not microseconds.

Still mulling this over. Whatever resolution I try to go with, I agree I should round the granularity of any tme comparisons to at most a tenth of a second (but I believe that would have little to no effect on the resolution however). Just surprised the input_text is not only earlier than the switch itself - but by several seconds!

What I didn’t mention before was that I have a timer that when it is (re)started, that turns the light on, and when the timer is finished or canceled, that turns the light off. The switch going on or off also r(re)starts or cancels the timer. For scenario #2 above (shelly relay behind an old fashioned switch set to “edge” mode) that is required to make it function properly - but required for all three above in that when the timer is finished (and nobody is around) then the lights properly go off.

Also, the motion (re)starting the timer is required to avoid the scenario where people are still in the room while the lights go off (when they are sitting still or not moving because I have cheapo motion sensors).

This might not work either but I still have to dig and test to determine… the original sugggestion from @PeteRage to not turn on the lights if they are already on (even though they were just turned off but not reported that way in the system yet for a short time due to a delay) - I may consider some logic that is based upon the current time remaining on the related timer* - to avoid (re)starting the timer to turn the lights back on… seems a goofy approach however but might work!

*This complicates the investigation - I’ll have to check to see if there is a way to turn on verbose logging for automation in the syslog, but not sure if even that would help since I am also running into issues like this.

Sheesh!

I’m not convinced that’s true. Unless you are running on a super slow computer.

For my lights with motion I use the following:

  • Triggers - what are the trigger to automatically turn on the light. Could be a door sensor, a motion sensor or both.

  • Occupancy - what are the occupancy sensors - as you may have multiple of them. Typically I configured the motion sensor to have a 5 minute hold time.

  • Delay - how long to wait after occupancy

From there I create two automations (actually I have a program that writes the yaml based on an input definition) One that run off the triggers to turn the lights on and the second that runs off the occupancy clearing. You could certainly add the switch changing state in the last 5 minutes to your occupancy template.

- id: basement_light ms on
  alias: basement_light ms on
  mode: single
  max_exceeded: silent
  trigger:
    - platform: state
      entity_id: binary_sensor.workshop_motion_motion_detected
      to: "on"
      from: "off"
      id: workshop_motion
    - platform: state
      entity_id: binary_sensor.basement_sensor_motion_detected
      to: "on"
      from: "off"
      id: basement_sensor
    - platform: state
      entity_id: binary_sensor.workshop_door_open
      to: "on"
      from: "off"
      id: workshop_door
  condition:
    condition: and
    conditions:
      - "{{ states('input_boolean.lt_basement_light_control_enable') == 'on' }}"
      - "{{ states('sensor.basement_luminance')|int(100) <= states('input_number.lt_basement_light_lux_low')|int(0) }}"
      - "{{ is_state('binary_sensor.away_mode','off') }}"
      - "{{ is_state('switch.basement_light_1','off') or is_state('switch.basement_light_2','off') }}"
  action:
    - service: input_text.set_value
      data_template:
        entity_id: input_text.lt_basement_light_status
        value: "{{ 'on: ' + trigger.id + ' ' + now().strftime('%H:%M:%S.%f')[:-3] }}"
    - service: script.rs_basement_light_1_switch_turn_on
    - service: script.rs_basement_light_2_switch_turn_on
- id: basement_light ms off
  alias: basement_light ms off
  trigger:
    - platform: template
      value_template: "{{ is_state('binary_sensor.basement_sensor_motion_detected','off') and is_state('binary_sensor.ms_basement_cam','off') }}"
      for: "00:01:00"
  condition:
    condition: and
    conditions:
      - "{{ is_state('binary_sensor.away_mode','off') }}"
      - "{{ states('input_boolean.lt_basement_light_control_enable') == 'on' }}"
      - "{{ is_state('switch.basement_light_1','on') or is_state('switch.basement_light_2','on') }}"
  action:
    - service: input_text.set_value
      data_template:
        entity_id: input_text.lt_basement_light_status
        value: "{{ 'off: no occupancy '}}"
    - service: script.rs_basement_light_1_switch_turn_off
    - service: script.rs_basement_light_2_switch_turn_off
1 Like

Very clever, combining camera, motion sensor, luminance and whether or not lights are on or off.

It probably is slow - as it is an RPI4 - even though running on an SSD, connected only via ethernet, with the CPU normally around 10% and the memory only 30% - there may be I/O latency with regards to numerous automations happening at the same time (even though the vast majority of them are set to parallel mode)