State History as condition in automations

Is it possible to set historical state changes as conditions in automations?
Say i.e. that i want to trigger an automation when a light turns on, but I only want the automation to run if the light has been off for at lest 30min prior to being turned on.
How can I do that?

This checks it’s currently off and hasn’t changed for more than 1800 seconds. Assumes it doesn’t go unknown or unavailable.

condition:
  - condition: state
    entity_id: light.your_light
    state: 'off'
  - "{{ now()|as_timestamp - states.light.your_light.last_changed|as_timestamp(0) > 1800 }}"

The other way would be to make a trigger-based template sensor that records the current time when the light switches off and compare that in the condition instead: that’d be more robust to dropped connections, restarts etc.

Excellent - thank you so much!! :blush::+1:

@Troon why do these templates come out with incorrect values:

If i subtract 23 - 15 = 8 which is an 8 hour time difference. While the template in line 6 calculates this to nearly 7 hours. There’s almost an hour missing?

Timezones. Look at the end of the results for lines 3 and 4.

Of course - how stupid of me!
But how should that be understood - does it mean that now() is aware of my TimeZone while last_changed is not?

Correct — I should have realised this when I made my suggestion above, but I’m in a UTC timezone at the moment. If you’d asked in the summer I might have realised :smiley: . Try utcnow() instead:

{{ utcnow()|as_timestamp - states.light.your_light.last_changed|as_timestamp(0) > 1800 }}

https://www.home-assistant.io/docs/configuration/templatin

1 Like

We’re getting there. What happens now, is that my automation is triggered by the entity Persons changing to Home. Then immediately followed by a conditional test as you so helpfully described. But your test always returns False since the state obviously just changed. What I want to test is not the last_changed but the one before last (if you understand what I mean).
So the duration of the state-1 should be more than 30 minutes.
Is that possible?

1 Like

OK: with the original setup I’d assumed that the automation was going to turn the light on, not that it was triggering from the light.

I’d do what you want with a trigger-based template sensor to record the time when your entity went to whatever you’re calling the “off” state, to record the “state-1” time — then use that in your condition.

Example, with assumptions on your entity ID and state definition:

template:
  - trigger:
      - platform: state
        entity_id: group.persons
        to: not_home
    sensor:
      - name: "Persons not home"
        state: "{{ now() }}"
        device_class: timestamp

Based on your input I tried this approach - but it doesnt’ work. The sensor never updates (?)

template:
  - binary_sensor:
      - name: "persons_away"
        state: >
          {% if is_state('group.persons', 'away') %}
            {{ on }}
          {% endif %}
        delay_on:
          minutes: 30

So many things wrong with that. Try:

template:
  - binary_sensor:
      - name: "persons_away"
        state: "{{ is_state('group.persons', 'not_home') }}"
        delay_on:
          minutes: 30

Your attempt checks for the state away, which I’m pretty sure the group will never be — check on the states page. If it is away, then output the undefined variable on, otherwise… nothing. :crazy_face:

You could also use the home zone if you’ve defined it: its state is the number of people in the zone. If it’s working properly, you could use:

        state: "{{ is_state('zone.home', '0') }}"

EDIT: I thought so:

1 Like

Yes, I found that.The strange thing is that when I check the history as well as the state value in the developers page, they both list the value as away and home

image

It doesn’t say not_home so intuitively I assumed that the docs were just outdated.

The actual state is shown in the state table on Developer Tools / Template: it’s that one you want, rather than the “sanitised”, friendly-but-incorrect version shown elsewhere:

Aha, I see. Many thanks. Is this a case of inconsistency, or just by (good?) design, I wonder… :blush:

Oh, by the way - it works now! Thank you ever so much for your valuable help.

Question, is this possible to do with Zones aswell?

I’ve got an issue where one of my zones is quite small, but using condition such as below doesnt work, the trace shows “Wanted_state: 0”

  - condition: state
    entity_id: zone.lidl
    state: "0"
    for:
      hours: 0
      minutes: 30
      seconds: 0

This is how the issue looks like when having a smaller zone at the shop

image

What’s the trigger? That condition should pass if there has been no-one in zone.lidl for 30 minutes.

This is the entire automation:

Triggers are state based ones ( as zones didnt work for me, dont know why… But zones never really liked me )

That’ll never work. You’re triggering off Philippe entering Lidl or Citygross zones (assume this is working or you wouldn’t have a trace).

Your condition block then needs all of the following to be true:

  • Nikoline at home
  • No-one in Lidl for the last 30 minutes
  • No-one in Citygross for the last 30 minutes

Because of your trigger, you’re guaranteeing that one of the last two conditions is false: Philippe is in one of those zones. The evaluation is done after the trigger has fired.

Describe exactly what you’re trying to achieve and we’ll have a go at helping.