Strategies for dealing with restarts in automations

I carried out the following test:

template:
  - binary_sensor:
    - name: HA recently restarted
      state: "{{ now().timestamp() - as_timestamp(states('sensor.uptime')) < 60 }}"
- alias: startup test
  trigger:
  - platform: state
    entity_id: binary_sensor.ha_recently_restarted
  action:
  - service: notify.persistent_notification
    data:
      title: "{{now().timestamp()|timestamp_custom()}}"
      message: "From: {{trigger.from_state.state}}, To: {{trigger.to_state.state}}"

On startup, there’s no notification indicating a state-change from unknown to on. The sole notification that occurs is one minute later when the binary_sensor’s state changes from on to off`.

Screenshot from 2022-03-11 13-38-06

Based on your description of the sequence of events during startup, why was the binary_sensor’s state not unknown on startup? Alternately, can you think of a better template to demonstrate the production of an initial unknown state?

FWIW, I seem to recall bdraco explaining that templated entities are evaluated on startup (i.e. independently of the listeners assigned to the template). However, I can’t find that comment now.

Ah, here’s the other piece of the puzzle I forgot to check before, automations do the same thing:

https://github.com/home-assistant/core/blob/d2e5c85429a8a258a4aeb81c029535e4dec17851/homeassistant/components/automation/__init__.py#L553-L555

If HA is starting up when they are added they add a callback to register their triggers. And since everything is asynchronous at that point we just have a race condition. Will the automation register its listeners before the template figures out its state or vice versa?

If we really want to figure this out I don’t think we can do this with an automation because of that. We’d have to look at the event table in the DB to see if there’s a state_changed event.

EDIT:

Hm, not what I’m seeing but Bdraco definitely knows this stuff. Although was it an old comment? Remember template used to ask you to list the entities you use rather then figuring it out by rendering the template. That behavior makes sense in that model but would be difficult to do that in the current model when everything might not exist yet.

I believe it was a comment made at the time when entity_id was deprecated in favor of the new system that replaced the old method of template inspection and listener assignment (I believe it was version 0.115). The new system underwent a refinement process, part of which included now() performing a template evaluation every minute (on the minute) and any template that employed a complete domain (like states.sensor) was throttled by performing periodic evaluations instead of based on state-changes of every entity in the domain (which caused processor-intensive “storms” of template evaluation when first implemented).

Or I’m misremembering his explanation. :slightly_smiling_face: