Quantcast
Channel: Configuration - Home Assistant Community
Viewing all articles
Browse latest Browse all 102831

Template optimisation question for last_seen datetime sensor

$
0
0

@123 I wonder if you could help me with a template question please? I’ve been trying to follow a lot of your excellent template examples and experimenting with them in the template editor, but I’m stuck trying to count the number of entities that have a datetime attribute longer than x hours.

I have the following working template using for loops at the moment (along with associated automation for completeness)

template:
  - sensor:
      - unique_id: z2m_last_seen_entities
        name: "Z2M Last Seen Entities"
        state: >
          {% set lapsed_hours = 24 %}
          {% set ns = namespace(count=0) %}
          {% for state in states.sensor | selectattr('entity_id', 'search', '.*_last_seen$')  %}
            {% if states(state.entity_id) == 'unavailable' or ((as_timestamp(now()) - as_timestamp(states(state.entity_id))) > ((lapsed_hours | int) * 60 * 60)) %}
              {% set ns.count = ns.count + 1 %}
            {% endif %}
          {% endfor %}
          {{ ns.count }}     
        attributes:
          devices: >
            {% set lapsed_hours = 24 %}
            {% set result = namespace(sensors=[]) %}
            {% for state in states.sensor | selectattr('entity_id', 'search', '.*_last_seen$') %}
              {% if states(state.entity_id) == 'unavailable' or ((as_timestamp(now()) - as_timestamp(states(state.entity_id))) > ((lapsed_hours | int) * 60 * 60)) %}
                {% set result.sensors = result.sensors + [state.name | regex_replace(find='_last_seen', replace='') ~ ' (' ~ relative_time(strptime(states(state.entity_id), '%Y-%m-%dT%H:%M:%S%z', 'unavailable')) ~ ')'] %}
              {% endif %}
            {% endfor %}
            {{ result.sensors | join(', ') }}

automation:
  - alias: Offline Zigbee Devices
    id: offline_zigbee_devices
    description: Sends notification for offline Z2m devices
    trigger:
      - platform: time
        at: '20:00'
    condition:
      - condition: template
        value_template: '{{states(''sensor.z2m_last_seen_entities'')|int > 0}}'
    action:
      - service: notify.signal_justme
        data:
          title: Low battery alert
          message: '{% set phrase = ''s are '' if states(''sensor.z2m_last_seen_entities'')|int > 1 else '' is '' %} 
                    The following sensor{{ phrase }}missing: {{ state_attr(''sensor.z2m_last_seen_entities'', ''devices'') }}'

The problem though is that this gives me the following errors when rebooting HA, which I assume is because the data isn’t ready straight away:

2022-04-27 11:42:27 WARNING (MainThread) [homeassistant.helpers.template] Template warning: 'as_timestamp' got invalid input 'unknown' when rendering template '{% set lapsed_hours = 24 %} {% set result = namespace(sensors=[]) %} {% for state in states.sensor | selectattr('entity_id', 'search', '.*_last_seen$') %}
  {% if states(state.entity_id) == 'unavailable' or ((as_timestamp(now()) - as_timestamp(states(state.entity_id))) > ((lapsed_hours | int) * 60 * 60)) %}
    {% set result.sensors = result.sensors + [state.name | regex_replace(find='_last_seen', replace='') ~ ' (' ~ relative_time(strptime(states(state.entity_id), '%Y-%m-%dT%H:%M:%S%z', 'unavailable')) ~ ')'] %}
  {% endif %}
{% endfor %} {{ result.sensors | join(', ') }}' but no default was specified. Currently 'as_timestamp' will return 'None', however this template will fail to render in Home Assistant core 2022.1
2022-04-27 11:42:27 ERROR (MainThread) [homeassistant.helpers.event] Error while processing template: Template("{% set lapsed_hours = 24 %} {% set result = namespace(sensors=[]) %} {% for state in states.sensor | selectattr('entity_id', 'search', '.*_last_seen$') %}
  {% if states(state.entity_id) == 'unavailable' or ((as_timestamp(now()) - as_timestamp(states(state.entity_id))) > ((lapsed_hours | int) * 60 * 60)) %}
    {% set result.sensors = result.sensors + [state.name | regex_replace(find='_last_seen', replace='') ~ ' (' ~ relative_time(strptime(states(state.entity_id), '%Y-%m-%dT%H:%M:%S%z', 'unavailable')) ~ ')'] %}
  {% endif %}
{% endfor %} {{ result.sensors | join(', ') }}")
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/homeassistant/helpers/template.py", line 407, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/lib/python3.9/site-packages/homeassistant/helpers/template.py", line 1820, in _render_with_context
    return template.render(**kwargs)
  File "/usr/lib/python3.9/site-packages/jinja2/environment.py", line 1291, in render
    self.environment.handle_exception()
  File "/usr/lib/python3.9/site-packages/jinja2/environment.py", line 926, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 2, in top-level template code
TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'

What I would like to do is optimise the code and avoid these errors with something like the following examples, but I can’t figure out what the code should be to manipulate the datetime state from the Zigbee2MQTT *_last_seen entity (see screenshot below)

        https://community.home-assistant.io/t/turn-off-all-light-on-from-3hours-not-using-group/345013/6?u=jarrah
        This template lists all lights that have been on for more than 3 hours.
        {{ states.light | selectattr('state', 'eq', 'on')
           | selectattr('last_changed', 'lt', now() - timedelta(hours=3)) 
           | map(attribute='entity_id') | join(', ') }}

        {%- set threshold = 40 -%}
        {{ states.sensor | selectattr('entity_id', 'search', '^(?!.*energy).*_power$')
                  | map(attribute='state') | map('int', 0) | select('<', threshold) | list | count }}

        https://community.home-assistant.io/t/improvement-to-sensor-template-with-for-loop/360550/12?u=jarrah
        {{ state_attr('weather.kmrb_hourly', 'forecast') 
          | selectattr('datetime', '<=', today_at('21:00').isoformat())
          | map(attribute='temperature')
          | max }}

I can count the total number of entities found like so:

{{ states.sensor | selectattr('entity_id', 'search', '.*_last_seen$')  | map(attribute='entity_id') | list | count }}

However, the following gives an error that says TypeError: '<' not supported between instances of 'str' and 'datetime.datetime', so I assume it’s because the state value is a string rather than datetime object?

        {{ states.sensor | selectattr('entity_id', 'search', '.*_last_seen$') 
            | selectattr('state', 'lt', now() - timedelta(hours=3)) 
            | map(attribute='entity_id') | list | count }}

Thanks in advance.

3 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 102831

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>