Template: attribute filtering for multiple sensors

Hello guys, I need a piece of advice about filtering in templates. I have defined multiple input datetime sensors in the list object. I can’t handle the maximum value of the timestamp attribute.

{% set sensors = [
  states.input_datetime.bathroom_sensor_motion_last_motion,
  states.input_datetime.hall_sensor_motion_last_motion,
  states.input_datetime.kids_room_sensor_motion_last_motion,
  states.input_datetime.kitchen_sensor_motion_last_motion,
  states.input_datetime.main_room_sensor_motion_last_motion]
  |reject('none')|list %}

This doesn’t work probably because it is a list object:

{{ sensors | map(attribute='timestamp') | max }}

Result:

UndefinedError: 'homeassistant.helpers.template.TemplateState object' has no attribute 'timestamp'

I can get the attribute timestamp for an individual sensor in the loop:

{%- for sensor in sensors %}
  {{ sensor }}
  ---> {{ sensor.name }}, {{ sensor.attributes.timestamp }} <---
{% endfor %}

Result of the first step:

 <template TemplateState(<state input_datetime.bathroom_sensor_motion_last_motion=2020-12-07 01:48:19; editable=False, has_date=True, has_time=True, year=2020, month=12, day=7, hour=1, minute=48, second=19, timestamp=1607302099.0, friendly_name=Last Motion Bathroom, icon=mdi:motion-sensor @ 2020-12-07T01:55:49.212502+01:00>)>
---> Last Motion Bathroom, 1607302099.0 <---

I feel like a fool but how do I get the maximum value of the timestamp attribute using a filter?

This should report the largest timestamp value.

{{ sensors | map(attribute='attributes.timestamp') | max }}

The limitation of this approach is it will report only the largest timestamp value and not which entity has it.

Let me know if you need the entity_id. It will require a second template that searches for the entity using the largest timestamp value found by the first template.

Yah but you can get around that

{% set sensors = [
  states.input_datetime.bathroom_sensor_motion_last_motion,
  states.input_datetime.hall_sensor_motion_last_motion,
  states.input_datetime.kids_room_sensor_motion_last_motion,
  states.input_datetime.kitchen_sensor_motion_last_motion,
  states.input_datetime.main_room_sensor_motion_last_motion]
  |reject('none')|list %}
{% set target = sensors | map(attribute='attributes.timestamp') | max %}
{% set target = sensors | selectattr('attributes.timestamp', 'eq', target) | list | first %}
{{ target.name }}, {{ target.attributes.timestamp }}

Yup, that’s what I meant when I wrote:

second template that searches for the entity using the largest timestamp value found by the first template

1 Like

didn’t see that

What?!

{{ sensors | map(attribute='attributes.timestamp') | max }}

I would put my hand in the fire, that I also tried this variant :smiley:
Thanks a lot, you save me a lot of wasted time. And as I said, I feel like a fool.

@petro Thank you for the complete solution. :+1:

1 Like

After some time, I noticed that the time of the last seen value does not correspond to any time of the filtered sensors. Each time the HA is restarted, the timestamps attributes has a different value than the value displayed in input_datetime sensors.

An example

List of all input_datetime sensor times:

Generated last seen sensor generated:

All attributes of the kitchen sensor (timestamp has a strange value):

<template TemplateState(<state input_datetime.kitchen_sensor_motion_last_motion=2021-03-29 08:27:32; editable=False, has_date=True, has_time=True, year=2021, month=3, day=29, hour=8, minute=27, second=32, timestamp=1617002972.0, friendly_name=Last Motion Kitchen, icon=mdi:motion-sensor @ 2021-03-29T08:32:27.085519+02:00>)>

{{ 1617002972 | timestamp_custom('%H:%M %d.%m.', true)  }} ==> 09:29 29.03.

Does anyone know what the problem is?

After a restart, last changed is set to the restart time because that’s the last time the sensor was changed.

Ah… the reason I used temporary input_datetime sensors was because I thought this sensor would keep the datetime without affecting by the restart :frowning:

After a restart, the input_datetime’s state value remains the same but its last_changed value is set to the current time (i.e. the startup time). All entities behave this way and it’s the subject of a long-standing complaint:

This is an unfortunate feature and is not mentioned in the documentation (or I didn’t notice). The HA is an excellent application but I definitely lack the ability to easily store variables and constants unaffected by the restart.

I really liked the filtering method from @petro in this post, but it can’t be used when the input data is not valid. What a shame. So, I’m going to look for another way.

You may have misunderstood what I wrote because that statement is false. I use various Helper entities (input_datetime, input_boolean, input_text, input_number) to store data that survives a restart.

What you are referring to is an entity’s last_changed property. That is not something you can “store” anything in because it is automatically set by the system (when the entity’s state changes).

If you want to store a time and/or date value, use an input_datetime.

But I described my problem specifically for input_datetime. And I also use the timestamp attribute, which is recommended in many posts on this forum. Therefore, I understand filtering max value of timestamp is unreliable because of restart issue.

So, I understand that the correct way is to filter state (value of inputbox) not the timestamp. Right?

Edit:
I mean the attribute timestamp replace by value (state):

{% set sensors = [
  states.input_datetime.bathroom_sensor_motion_last_motion,
  states.input_datetime.hall_sensor_motion_last_motion,
  states.input_datetime.kids_room_sensor_motion_last_motion,
  states.input_datetime.kitchen_sensor_motion_last_motion,
  states.input_datetime.main_room_sensor_motion_last_motion]
  |reject('none')|list %}
{% set target = sensors | map(attribute='attributes.timestamp') | max %}
{% set target = sensors | selectattr('attributes.timestamp', 'eq', target) | list | first %}
{{ target.name }}, {{ target.attributes.timestamp }}

Edit as follows:

{% set sensors = [
  states.input_datetime.bathroom_sensor_motion_last_motion,
  states.input_datetime.hall_sensor_motion_last_motion,
  states.input_datetime.kids_room_sensor_motion_last_motion,
  states.input_datetime.kitchen_sensor_motion_last_motion,
  states.input_datetime.main_room_sensor_motion_last_motion]
  |reject('none')|list %}
{% set target = sensors | map(attribute='state') | max %}
{% set target = sensors | selectattr('state', 'eq', target) | list | first %}
{{ target.name }}, {{ target.state }}

I may not see other related problems, but it seems like a solution

i changed your example to experiment with the state value and how to access.

      test_template:
        unique_id: test_template
        value_template: >
          {% set sensors = states.sensor | list %}
          {% set target = sensors | map(attribute='entity_id') | max %}
          {% set target = sensors | selectattr('entity_id', 'eq', target) | list | first %}
          {{ target.name }}, {{ target.attributes }}

this seems to result in the following state:

Z-Wave JS UI Version, {'friendly_name': 'Z-Wave JS UI Version'}

which seems to have 2 parts to the state value. how would i access each value individually?

thank you.