Understanding self-referencing this.attributes

Hi all,

I have a template binary sensor based on a weather forecast attribute:


template:
- binary_sensor:
  - name: Regenradar
    unique_id: '202210291555'
    icon: |-
      {% set x = this.state %}
      mdi:weather-{{ 'pouring' if x is not none and x == 'on' else 'sunny' }}
    state: "{{ this.attributes.mm > 0 or this.attributes.vorhersage == 'rainy' }}"
    availability: |-
      {{ blah }}
    attributes:
      vorhersage: "{{ state_attr('weather.forecast_home_hourly','forecast')[1]['condition'] |default('N/A') }}"
      mm: "{{ state_attr('weather.forecast_home_hourly','forecast')[1]['precipitation'] |float(0) |default(0) }}"

The above state definition throws an error:


TemplateError('UndefinedError: 'homeassistant.util.read_only_dict.ReadOnlyDict object' has no attribute 'mm'') while processing template 'Template("{{ this.attributes.mm|float(0) > 0 or this.attributes.vorhersage == 'rainy' }}")' for attribute '_state' in entity 'binary_sensor.regenradar'

Whereas, the following definitions don’t throw an error:


state: "{{ this.attributes.vorhersage == 'rainy' }}"



state: "{{ this.attributes.mm is defined and this.attributes.mm > 0 }}"


Why?

Any hint is highly appreciated!

Because in one case you’re looking for an object. It throws an error on that object not existing or being ‘unavailable’ whereas your other two are templates that test in the first… Doesthis thing equal another thing and in the second is it greater than this other thing.

In both cases the absence of an object (effectively, null) does not equal ‘rainy’ it doesn’t exist. So it should return true. Also mm does not exist so it cannot be greater than 0 so I suspect that one returns false.

Thank you for your reply. I could understand it if there was no attribute mm, but mm is true (raining the whole day here).

The error is probably happening during the startup, when not all attributes are ready.

Try to add a default value for that attribute (when it is unavailable) and it probably will fix the issue:

state: "{{ this.attributes.mm | default(0) > 0 or this.attributes.vorhersage | default('unknown') == 'rainy' }}"
1 Like

Could this mean that the given defaults in the attribute itself aren’t respected? I can’t see any difference between the attributes. Both are nested attributes of weather.forecast_home_hourly, both have fallback values and both are true.

This is not what I’m saying.

The problem is that, during the start-up (when Home Assistant is starting after a boot), all those values are undefined for certain time and you might be trying to check for an attribute which is not available yet (not even with the default value).
This is a temporary condition. Probably after the start-up process your attributes will be all right, providing the default value and then no error anymore, but during the start-up it’s a special moment.

I believe it’s because a Template Sensor’s state option is processed before attributes.

Your state template refers to attributes.mm before the template in attributes.mm is processed.

Sorry that I’m asking as I was a child, but why is


{{ this.attributes.vorhersage == 'rainy' }}

throwing no error?

Sorry, I don’t know the answer.

My guess is it’s due to a timing issue (mere microseconds that make the difference). In other words, even if state and attributes are processed in parallel, there’s no guarantee which one will be ready first (arguably the more complex template will take more time to complete so the simplest template finishes first).

Nevertheless I wonder why the default value does not take effect. What is it good for then?

Makes all sense to me. Nevertheless I assumed that setting a default value is exactly for this case.

You believe the attribute is calculated when it is requested, right? But I don’t think this is the case.
So, when the attribute is calculated, the default value will be used if the value is not available, however, if you try to use that attribute before it was calculated it won’t force the calculation, it will just be unavailable.

To be precise, I expected the default value to be used even if the attribute does not (yet) exist.

It is not the case.
While the attribute doesn’t exists it simply doesn’t exists. Something that doesn’t exists doesn’t have anything, not even a default value. :stuck_out_tongue_winking_eye:

:grin:

Well, time for a FR: If there is no value, use a „fallback“ value (what would be cool)

Anyway, thank you all very much for your feedback!