Prevent template errors with entities missing required attributes

I thought I had this fixed but maybe HA was supressing the errors and now I am seeing them. The issue is I need to check all the zigbee entities to see if they have gone offline. I am using the following and I am trying to check if the attribute exists first before doing the math on it but it appears it is not working because I keep getting this error

Template variable warning: ‘homeassistant.util.read_only_dict.ReadOnlyDict object’ has no attribute ‘last_seen’ when rendering

- alias: Zigbee Device Missing Alert
  id: zigbee_device_missing_alert
  trigger:
  - platform: time
    at: '10:00'
  - platform: time
    at: '20:00'
  condition:
  - condition: template
    value_template: >
        {% set ns = namespace(break = false) %}
        {% for state in states -%}
          {%- if state.attributes.last_seen | default(false) %}
            {%- if (as_timestamp(now()) - as_timestamp(state.attributes.last_seen) > (60 * 60 * 8) ) and ns.break == false %}
              {%- set ns.break = true %}
              true
            {%- endif -%}
          {%- endif -%}
        {%- endfor %} 
  action:
  - service: notify.mobile_app_Pixel_XL
    data_template:
      message: >
          Some Zigbee devices haven't been seen lately...
          {% for state in states -%}
            {%- if (state.attributes.last_seen) and not (state.name | regex_search('linkquality|button_fan|update state|voltage|temperature|battery'))%}
              {%- if (as_timestamp(now()) - as_timestamp(state.attributes.last_seen) > (60 * 60 * 8) ) %}
                {{ ((as_timestamp(now()) - as_timestamp(state.attributes.last_seen)) / (3600)) | round(1) }} hours ago for {{ state.name }}            
              {%- endif -%}
            {%- endif -%}
          {%- endfor %}

Just as I was staring at this I see I don’t have | default(false) in the action section. Could that be it?

The states in this line:

  {% for state in states -%}

means it checks every entity you have (automations, scripts, scenes, lights, switches, sensors, etc).

It’s quite clear that most entities in your system do not have a last_seen attribute so why design a Template Trigger to monitor every entity? Why not restrict it to just the entities (or at least the domains) that have it?

1 Like

There are a lot of zigbee entities but the battery ones might be all in the sensor domain, what would be the syntax to limit it to that domain?

  {% for state in states.sensor -%}

If you have more than one domain you can do this:

  {% for state in expand(states.sensor, states.binary_sensor) -%}

Thanks I will give that a go which I am sure will help but not all sensors will have a last seen. Should the rest of what I have there work?

selectattr('attributes.last_seen', 'defined')
2 Likes

My suggestion was to reduce the amount of work performed by Home Assistant to just the minimum needed to get the job done. Then you need to select only the entities that have a defined lasr_seen attribute. Petro’s post shows how to do that with the selectattr filter and defined test.

For another example, you can refer to this one that rejects entities having a particular attribute defined:

Thanks this is what I have now. I am thinking the regex can probably be incorporated as a filter but it is working as far as I can tell. Thanks for the help!

- alias: Zigbee Device Missing Alert
  id: zigbee_device_missing_alert
  trigger:
  - platform: time
    at: '10:00'
  - platform: time
    at: '20:00'
  condition:
  - condition: template
    value_template: >
        {% set ns = namespace(break = false) %}
        {% for state in (expand(states.sensor, states.binary_sensor, states.light, states.switch) | selectattr('attributes.last_seen', 'defined')) -%}
          {%- if (as_timestamp(now()) - as_timestamp(state.attributes.last_seen) > (60 * 60 * 8) ) and ns.break == false %}
            {%- set ns.break = true %}
            true
          {%- endif -%}
        {%- endfor %} 
  action:
  - service: notify.mobile_app_Pixel_XL
    data_template:
      message: >
          Some Zigbee devices haven't been seen lately...
          {% for state in (expand(states.sensor, states.binary_sensor, states.light, states.switch) | selectattr('attributes.last_seen', 'defined')) -%}
            {%- if not (state.name | regex_search('linkquality|button_fan|update state|voltage|temperature|battery|illuminance')) %}
              {%- if (as_timestamp(now()) - as_timestamp(state.attributes.last_seen) > (60 * 60 * 8) ) %}
                {{ ((as_timestamp(now()) - as_timestamp(state.attributes.last_seen)) / (3600)) | round(1) }} hours ago for {{ state.name }}            
              {%- endif -%}
            {%- endif -%}
          {%- endfor %}