WTH can't automations see it's variables previous state when running

When creating automations, I often make variables that simplify my conditions/actions a lot. I would love to be able to access the previous state of those variables when the automation runs. This way, I could make “stable” decisions without having to create extra helpers.

For example, I have a text sensor that can have one of three states: good, average and bad. Based on the sensor state, I take a few actions. What I would like to do is only take an action when the state stabilizes on a given value (that is, it isn’t changed for let’s say 5 minutes).

With a helper I can store the “previous” state of the sensor, and prefer that state as long as the sensor is not stable for 5 minutes. However, I don’t like to create helpers for various internal automation states.

trigger:
  - platform: state
    entity_id: input_text.sergio_leone
    to: 'bad'
    for: 
      minutes: 5

Hmm, I should have given more information about the total automation; it also takes other sensor states into account. Those sensors have simple state triggers, so the actions might be executed if the “problematic” sensor is “bad” for only a minute.

And it’s that what I can’t figure out to do without helpers at this moment using only variables or action conditions :thinking: .

If you want all the triggers to be AND logic you have to also include them all as conditions (with the for stipulation if they have one).

trigger:
  - platform: state
    entity_id: input_text.sergio_leone
    to: 'bad'
    for: 
      minutes: 5
  - platform: state
    entity_id: input_booelan.clint_eastwood
    to: 'on'
condition:
  - condition: state
    entity_id: input_text.sergio_leone
    state: 'bad'
    for: 
      minutes: 5
  - condition: state
    entity_id: input_booelan.clint_eastwood
    state: 'on'

Another way is to use variables. Here is a good example how to implement this

1 Like

You can get all the previous states and attributes from the trigger object in templates.

Thanks for thinking along with me :slight_smile: . However, I’m not sure I can use those as a solution. Let me paste my automation below for clarity;

- id: ventilation_auto
  alias: "Ventilation auto"
  mode: single
  max_exceeded: silent
  trigger:
    - platform: state
      entity_id:
        - binary_sensor.showering
        - sensor.vindriktning_air_quality
        - climate.panasonic_upstairs
        - binary_sensor.aqara_door_door_mbr_contact
        - binary_sensor.master_bed_occupancy
      to: null
    - platform: state
      entity_id: binary_sensor.showering
      to: "off"
      for:
        minutes: 15
    - platform: state
      entity_id: sensor.vindriktning_air_quality
      to:
        - "Good"
        - "Average"
        - "Bad"
      for:
        minutes: 10
  condition:
    - condition: state
      entity_id: input_boolean.ventilation_manual
      state: "off"
  action:
    - variables:
        showering: "{{ is_state('binary_sensor.showering', 'on') or (as_timestamp(now()) - as_timestamp(states.binary_sensor.showering.last_changed) <= 895) }}"
        air_quality: >-
          {% if (as_timestamp(now()) - as_timestamp(states.sensor.vindriktning_air_quality.last_changed)) <= 595 %}
            {% set air_quality = states('input_text.ventilation_air_quality') %}
          {% else %}
            {% set air_quality = states('sensor.vindriktning_air_quality') %}
          {% endif %}
          {% if air_quality not in ['Good', 'Average', 'Bad'] %}
            {% set air_quality = 'Good' %}
          {% endif %}
          {{ air_quality }}
        airco_upstairs: "{{ is_state('climate.panasonic_upstairs', 'cool') and is_state('binary_sensor.aqara_door_door_mbr_contact', 'on') }}"
        sleeping: "{{ is_state('binary_sensor.master_bed_occupancy', 'on') }}"
    - service: input_text.set_value
      target:
        entity_id: input_text.ventilation_air_quality
      data:
        value: "{{ air_quality }}"
    - service: fan.set_percentage
      entity_id: fan.ventilation
      data:
        percentage: >-
          {% if airco_upstairs %}
            0
          {% elif showering %}
            100
          {% elif sleeping %}
            33
          {% elif air_quality == 'Bad' %}
            100
          {% elif air_quality == 'Average' %}
            66
          {% else %}
            33
          {% endif %}

As you can see, the level of my ventilation is decided by the vindriktning_air_quality (which is Good, Average or Bad), along a lot of other sensors.

As per my understanding of @tom_l 's suggestion, this would indeed trigger if the sensor would be bad for 5 minutes, but would also trigger if the other sensor (let’s say the airco panasonic_upstairs) is turned on at which point it’s hard to figure out for how long the sensor is already in the state it’s in. In this case, I won’t be able to get the previous state of the vindriktning_air_quality either as far as I understand.

The current implementation seems to be working as expected, but use a helper. It would be nice if I could just see what the air_quality variable was the last time the automation ran. Another option could be that the automation could “register” a child helper that was exclusively for the automation (and would be created by the automation and would be cleaned up if the automation would ever be deleted again).

Off course, if there would be cleaner or better alternatives for my use-case, I’m certainly interested :slight_smile: .

You can use for on conditions too. So tom’s point is still valid.

- condition: state
  entity_id: sensor.vindriktning_air_quality
  state: Good
  for:
    minutes: 5

You can also get this information by looking at last_updated or last_changed on the entity itself and compare the times to the current time.

If the automation triggers because the shower is on, I can figure out whether the air quality is let’s say “good” for 5 minutes. However, if that’s not the case, the current state might already be “good”, but only since 2 minutes, so I should use the previous state, which I don’t know at this moment if I understand it correctly.

the condition is only true (and is executed instantly after the trigger) if the last 5 minutes of states are equal to good.

Given I have multiple triggers and assuming another trigger triggered (e.g. shower turned on), and this condition is not met (let’s say the air quality was average, and is only good for 2 minutes). At this moment, I know the air quality is not yet good for 5 minutes (as the condition fails), and I can also see the air quality is currently good for 2 minutes (by looking at the current state and the last changed). How can I know that the previous air quality is average, as that is what I want to take in account at this point.

In my current implementation I do that using a helper, but I don’t see how I can figure this out by only a trigger and/or condition