State trigger with 'for' clause

In the documentation I see this example:

automation:
  trigger:
    platform: state
    entity_id: device_tracker.paulus, device_tracker.anne_therese
    # Optional
    from: 'not_home'
    # Optional
    to: 'home'

    # If given, will trigger when state has been the to state for X time.
    for:
      hours: 1
      minutes: 10
      seconds: 5

but if I try to do something similar, like:

- id: water_level
  initial_state: true
  alias: Water level
  trigger:
    - platform: state
      entity_id: binary_sensor.water_level
      for:
        seconds: 60
  action:
    service: notify.pushbullet
    data:
      message: Water level sensor state {{ binary_sensor.water_level.state }}

I got this error:

Invalid config for [automation]: dependency violation - key “for” requires key “to” to exist @ data[‘trigger’][0]. Got None.

But in the example above, both from and to clause are optional. Where is my mistake?
My goal is to trigger an action whenever the state changes to any value for at least 60 seconds.

you need to add to: above: or below:

The documentation doesn’t say so, but perhaps there’s something wrong there.

Anyway, I don’t think it’s what I want. I want to trigger an action when a state remains stable to any value for some time. Using to: above: or below: I have to create a lot of triggers. There isn’t a way to do this automatically?

Example:

state = ‘on’ for 2 seconds - nothing
state = ‘off’ for 45 seconds - nothing
state = ‘unavailable’ for 65 seconds - send notification
state = ‘off’ for 15 seconds - nothing
state = ‘on’ for 200 seconds - send notification

The same would apply for a numeric value: I want a notification only if the value is stable for some time.

you aren’t providing a state via to or from, and @PeteCondliffe is mixing up the numerical state trigger with the state trigger.

To is only optional when you are optional when not using for. To is not optional when you use for. The state is needed so that the trigger knows what to create a listener for.

Pulled directly from the documentation, Note the comment inside the example code says # If given, will trigger when state has been the to state for X time

STATE TRIGGER

Triggers when the state of a given entity changes. If only entity_id is given trigger will activate for all state changes, even if only state attributes change.

automation:
  trigger:
    platform: state
    entity_id: device_tracker.paulus, device_tracker.anne_therese
    # Optional
    from: 'not_home'
    # Optional
    to: 'home'

    # If given, will trigger when state has been the to state for X time.
    for:
      hours: 1
      minutes: 10
      seconds: 5

So the answer is: it’s not possible to do what I’m asking. Right?

Why not just reset a timer every time the value changes and trigger the automation only when the timer runs out?

@reef-actor yes, it’s a feasible workaround! It would be even easier if one could use the ‘for’ clause without specifying the ‘to’ one.

1 Like

It is, but you have to list a trigger for all the states you want to have a for…x. If that’s not what you want, you can use the timer method.

Trigger method

  trigger:
    - platform: state
      entity_id: device_tracker.paulus, device_tracker.anne_therese
      to: 7
      for:
        hours: 1
    - platform: state
      entity_id: device_tracker.paulus, device_tracker.anne_therese
      to: 7
      for:
        hours: 1
    - platform: state
      ... etc....

Timer method

Create a bootleg script timer. Start the timer only when the state changes are different. reset the timer each time the state changes. The timer waits a minute, if nothing stops it from restarting, then the state hasn’t changed and do your action:

- id: water_level
  initial_state: true
  alias: Water level
  trigger:
    - platform: state
      entity_id: binary_sensor.water_level
  condition:
    - condition: template
      value_template: "{{ trigger.from_state.state != trigger.to_state.state }}"
  action:
    - service: script.turn_off
      data:
        entity_id: script.water_level_timer
    - service: script.water_level_timer

script.water_level_timer:

sequence:
  - delay: "00:00:60"
  - service: notify.pushbullet
    data_template:
      message: "Water level sensor state {{ states('binary_sensor.water_level') }}"

I tried the Timer method, but it doesn’t do what I meant. It just send the notification one minute after the last state change. This happens even if the state changes for a while to another. Instead if the state changes back to the initial one before the timer timeouts no notification should be send.

I apologize for my English, perhaps I’m not good to explain what I’m trying to do.

Basically, you can see this like a very slow debouncing. Let’s suppose the state is “off”. If it changes to “on” and within 1 minute it comes back to “off” again it must not send a notification. Only if the new state is stable for more than a minute.

In a common application it would a very easy task, i.e. metacode:

  1. save the current state as old state
  2. when the state changes (re)start a timer
  3. if the state changes again: if the new state is the old state, stop the timer and go to point 1 else go to point 2
  4. if the timer expire send the notification and go to point 1

But I don’t know how to do this in HA!!!

That’s what the timer method should be doing.

Every state change it starts a timer, if the state changes inside the minute, the timer is reset. Can you post the yaml you used?

I just ran this automation and it works. It uses two triggers to monitor the binary_sensor’s two states, on and off.

  • Upon plugging in my phone, it must remain plugged in for at least 5 seconds and then the kitchen light toggles.
  • Upon disconnecting the phone’s power, it must remain disconnected for at least 5 seconds before the kitchen light toggles.

In automations.yaml:

- id: two_triggers
  alias: Two Triggers
  trigger:
    - platform: state
      entity_id: binary_sensor.phone_power
      to: 'on'
      for:
        seconds: 5

    - platform: state
      entity_id: binary_sensor.phone_power
      to: 'off'
      for:
        seconds: 5

  action:
    service: light.toggle
    entity_id: light.kitchen

1 Like

Yeah problem is, this is a water heater. So if he wanted to program every state, he’d have to program every temperature at the resolution his sensor outputs. So if it outputs every 0.1 degree change, he’d have to make every trigger from x to x in point 0.1 increments. Yaml would be huge.

Oops! I misunderstood the requirements. I thought it was just for on/off.

Hi guys! Thank you very much for your support.
Well, there are two different cases here. The one I’m currently working on is the binary state. My code:

binary_sensor:
  - platform: mqtt
    name: "Water level"
    state_topic: "home/waterlevel/sensor/1"
    availability_topic: "home/waterlevel/availability"
    payload_available: "online"
    payload_not_available: "offline"

- id: water_level
  alias: Water level
  trigger:
  - entity_id: binary_sensor.water_level
    platform: state
  condition:
  - condition: template
    value_template: "{{ trigger.from_state.state != trigger.to_state.state }}"
  action:
  - service: script.turn_off
    data:
      entity_id: script.water_level_timer
  - service: script.water_level_timer
  initial_state: true

script:
  water_level_timer:
    sequence:
    - delay: "00:00:60"
    - service: notify.pushbullet
      data_template:
        message: "Water level sensor state {{ states('binary_sensor.water_level') }}"

The actual problem is: my WiFi sensor is pretty far from the router so it disconnected quite often from the network but it rejoins in a couple of seconds. But with this method every time is disconnects (i.e. the state changes to unavailable) and then comes back to off or on, it sends me a notification after a minute.

As said, if the change is less than a minute it should ignore it.

@123 I could try your solution but I have to add another state to handle the unavailable one. But what happens if you have the lights ‘on’, you turn off them for 2 seconds (so the state is off but the action is not triggered) and then turn on again? I guess it will trigger because it sees a new transitions to ‘on’ this time for more than 5 seconds… Are you sure this is the expected behavior of your toggling?

The second scenario is about what @petro said: I would like to apply this solution to any value: integer of floating point. If my readings are not stable I don’t want to trigger anything. Only when the readings are stable for a given amount of time. Of course if it changes from say 21.2, 21.3, 21.2 within that time it must not trigger! Because the value hasn’t actually changed! It came back to the initial one. You may think it in terms of “noise” I want to filter out.

If you look closer at the meta-code I’ve posted above you should understand what I’m trying to explain with words (badly…).

Thanks again!

Can you prove that it’s not working as intended? I used this method for over a year a opening door and it behaved the way you described. Are you 100% sure that it’s changing state inside the minute?

Yes I can :slightly_smiling_face:
Here the log of a try of few minutes ago. I did the following:

  1. powered on the WiFi sensor and left in the state ‘on’ for more than 1 minute - notification received (OK)

  2. then quickly (< 1 sec) switched several times between states ‘off’ and ‘on’

  3. left in the state ‘on’ for more than 1 minute - notification received (WRONG!!!)

  4. powered off, it went in state ‘not available’ and then powered on in few seconds

  5. left in the state ‘on’ for more than 1 minute - notification received (WRONG!!!)

    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Water level turned off
    2:01 PM Water level turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Water level has been triggered
    2:01 PM Water level turned off
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Water level has been triggered
    2:01 PM Water level turned on
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Water level has been triggered
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level turned on
    2:01 PM Water level has been triggered
    2:01 PM Water level has been triggered
    2:01 PM Water level turned off
    2:01 PM water_level_timer turned on
    2:01 PM Water level turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:01 PM Water level has been triggered
    2:01 PM Water level has been triggered
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned off
    2:01 PM Water level turned off
    2:01 PM Water level has been triggered
    2:01 PM Garden turned on
    2:01 PM Water level turned on
    2:01 PM water_level_timer turned on
    2:01 PM Water level has been triggered
    2:01 PM Garden turned off
    2:01 PM Water level turned off
    2:00 PM water_level_timer turned off
    1:59 PM ESP-03E172 is at home
    1:59 PM water_level_timer turned on
    1:59 PM Water level has been triggered
    1:59 PM Garden turned on
    1:59 PM Water level turned on

How is 3 and 5 wrong when you left it in the on state for more than a minute… that’s exactly what step 1 is doing but step 1 is right in your mind?

I think you meant to say “what happens if you have the phone plugged in …”. In the experiment, the kitchen light is simply an indicator, it’s the phone’s power connection that is being monitored.

I repeated the experiment using the conditions you mentioned, namely plug the phone in for 2 seconds then disconnect it for 2 seconds, then plug it in again for 2 seconds, then disconnect it, etc. The goal is to determine if state-changes, less than 5 seconds in duration, are effectively ignored (i.e. the kitchen light never toggles).

The good new is that’s precisely what I observed; the kitchen light never toggled while I repeatedly put extra mileage on my phone’s micro-USB connector by repeatedly connecting/disconnecting it! :slight_smile:

This works but, as @petro pointed out, it’s impractical for monitoring a wide range of numeric state-changes. You’d need a boatload of triggers and it, self-evidently, indicates the approach is a ‘brute force’ solution.

BTW, somewhere in this thread I believe you used the word ‘hysteresis’ and that jogged my memory. For a brief moment I thought the Threshold Binary Sensor might be useful but, no. Your use-case isn’t looking for the value to settle within a desired range, just to stabilize.

FWIW, while creating a driver for a HAI Omnistat/2 thermostat, I noticed the reported indoor humidity value was ‘nervous’. It fluctuated in 0.1 increments and reported far too many readings. Ultimately I chose to store the previously reported value so I could do some simple math:

If the absolute value of current value minus previous value is greater than one then report the current value.

if abs(current_value - previous_value) > 1 then
   report current_value
   previous_value = current_value
   etc

That served to quiet down the reported readings but, effectively, only possible if one is willing to forego an order of precision (i.e. measurements are in 0.1 but reported in whole integer values). Probably not suitable for your application but just an example of smoothing out ‘nervous’ measurements.

I think you could use something like this to filter out the “noise”:

or possibly:

How is 3 and 5 wrong when you left it in the on state for more than a minute… 
that’s exactly what step 1 is doing but step 1 is right in your mind?

Nope. Step 1 comes from “power up”, hence before this the state was unavailable for a long period of time. So it’s correct that step 1 will send a notification. Instead step 3 and 5 are not really state changes, because in few second its value comes back to the initial one (like a “noise”, or a switch bouncing). I don’t know how to explain it better, sorry.