Template sensors w/ triggers resolve at the same time. It’s a bit different than template entities that update based on the template themselves.
E.g. availability does not resolve before state for a triggered template entity.
Template sensors w/ triggers resolve at the same time. It’s a bit different than template entities that update based on the template themselves.
E.g. availability does not resolve before state for a triggered template entity.
Dammit. That’s what you said originally too.
(emphasis mine).
I’m basing this off what I remember, I could be wrong. I’m fairly sure it behaves this way. The order of operation is 100% correct, the this
object comments may not be correct.
So if it is a triggered template sensor the order you posted above is not valid. We can check that list for untriggered sensors by leaving out the trigger:
sensor:
- name: Test
unique_id: testytestytest
state: "{{ now() }}"
attributes:
copy_of_state: "{{ this.state }}"
That should update every minute.
easy way to test this would be…
- sensor:
- name: foo
state: "{{ now() }}"
attributes:
test: "{{ this.state }}"
EDIT: You beat me to it
Look up
Pedro, That seems to explain the test we’ve just run. And just to show that my previous solution has the same fault I’m running this.
- trigger:
- platform: time_pattern
minutes: "/1"
sensor:
- name: Test
unique_id: testytestytest
state: "{{ now() }}"
attributes:
copy_of_this_state: "{{ this.state }}"
copy_of_states: "{{ states('sensor.test') }}"
with this result:
sensor.test
Test
2023-10-11 17:01:00.152330+01:00 friendly_name: Test
copy_of_this_state: 2023-10-11 17:00:00.159356+01:00
copy_of_states: 2023-10-11 17:00:00.159356+01:00
So I’ve just changed it to an ordnary sensor as suggested.
unique_id: testytestytest
state: "{{ now() }}"
attributes:
copy_of_this_state: "{{ this.state }}"
copy_of_states: "{{ states('sensor.test') }}"
It results in
sensor.test
Test
2023-10-11 17:06:00.152369+01:00 friendly_name: Test
copy_of_this_state: 2023-10-11 17:05:00.152527+01:00
copy_of_states: 2023-10-11 17:05:00.152527+01:00
i.e. the same as with a trigger sensor-both reporting the previous value.
Looks like I’ll live with repeating the logic.
Thanls for all your help guys, your time & effort is much appreciated by this newbie!
edited to include the changed code
t
Hang on. Why is the attribute
copy_of_states: "{{ states('sensor.test') }}"
Also a minute behind?
It’s like the attributes are being resolved before the state.
Sorry! I must take more care!
Tom, it does look like it
The state machine always has the previous state, which is currently being calculated. states(
grabs from the state machine. That will not be updated until the entire state object is updated.
What surprises me is
copy_of_this_state: "{{ this.state }}"
reports 17:00:00
and not 17:01:00
.
Here’s my understanding of how it works (which now appears to be incorrect):
state
option is evaluated first so this.state
, in the state
option, refers to the previous value.this.state
, in an attribute, refers to the newly computed value.However, the results above imply my understanding is incorrect and this.state
always refers to the previous value.
I echo your puzzlement. Surely once the state value is written to the state machine it will register as a change and cause the attribute to be updated based on its new value states('sensor.test')
. This doesn’t appear to be happening. Does this mean the attributes are not re-evaluated when something they derive from changes? …but only if something the state value depends on changes?
The state is not written to the state machine until the state object is fully populated. A state object is not just the state of the sensor. It’s an object that contains all information about the entity; last_updated, last_changed, attributes, context, and the state. For template sensors, this is only added to the state machine when all the supplied templates have been resolved (state, availability, attributes, etc).
this
just holds the current state object as it’s being populated. This behavior may have changed. I personally do not use this functionality, so I cannot confirm or deny that it has changed behavior.
FWIW, I’m fine if it operates differently from the way I thought it did (whether due to my misunderstanding or its behavior changed). My version makes this.state
's behavior more complicated to use whereas the example above proves it’s far more straightforward; regardless of where this.state
is used in the Template Sensor, it always refers to what’s currently in the state machine.
Yes, I agree. It’s come up a bunch in the templating channel on discord. I’d actually use this
if it could ensure that it was the object pulled from the state machine prior to the templates execution. But historically, that hasn’t been the case. I’m 99% sure it behaved the way you (and I) described it as little as 2 months ago. It’s also possible that it could depend on how fast the system running it is.
EDIT: I want to clarify that I’m specifically talking about the population of the this
variable during template execution and not the order of template execution.
As far as I know, for trigger based template sensors it works the same as for automations.
When the trigger occurs, both the this
and trigger
objects are created.
These are then used in all templates, so also in those for the attributes and availability.
This is purely based on experience, not on evaluation of the code
I just ran few tests, and the takeaway is that I could not find an example where there was any difference between this.state
& this.attributes
compared to states()
& state_attr()
when self-referencing.
What I saw (in 2024.2.2) was the following:
this.state
nor states('sensor.self-referenced_template_sensor')
will update during the rendering of any part of the template sensor.this.attributes
and state_attr()
this
or states('sensor.this_template_sensor')
. It’s very easy to get into template loops because of this (but HA will catch it if the sensor is state-based, and you will see the loops in your log and the sensor will stop rendering; loops in trigger-based sensors overloaded and crashed my HA instance).Here’s the basic code I was testing with, but I had various flavors to test what happens if the state references an attribute and vice versa, or if the state was self-referencing, etc.
template:
- sensor:
- name: Template-state test using states
unique_id: 395526fc-87f0-43e0-bd76-f08a94c2851f
state: >
{{ states('input_number.test') }}
attributes:
first: "{{ states('sensor.template_state_test_using_states') | default(0,1) | int(0) + 1 }}"
second: "{{ state_attr('sensor.template_state_test_using_states', 'first') | default(0,1) | int(0) + 1 }}"
- name: Template-state test using this
unique_id: edf580ae-83c9-4758-a45c-64ef9a0b7ec3
state: >
{{ states('input_number.test') }}
attributes:
first: "{{ this.state | default(0,1) | int(0) + 1 }}"
second: "{{ this.attributes.first | default(0,1) | int(0) + 1 }}"
- trigger:
- platform: state
entity_id:
- input_number.test
sensor:
- name: Template-trigger test using states
unique_id: d6ffbb55-0fe4-4930-90bf-c2afbb507620
state: >
{{ states('input_number.test') }}
attributes:
first: "{{ states('sensor.template_trigger_test_using_states') | default(0,1) | int(0) + 1 }}"
second: "{{ state_attr('sensor.template_trigger_test_using_states', 'first') | default(0,1) | int(0) + 1 }}"
- name: Template-trigger test using this
unique_id: a8fe416b-7e17-40f2-9467-5fb48084fada
state: >
{{ trigger.to_state.state }}
attributes:
first: "{{ this.state | default(0,1) | int(0) + 1 }}"
second: "{{ this.attributes.first | default(0,1) | int(0) + 1 }}"
Results after beginning with all zeros, and changing the input number from 0
to 5
to 10
to 20
: