How to Apply Second Filter From an Initial List of Entities

I am trying to create a template sensor which lists and counts Zigbee devices where the current Linkquality LQI value is less than 50.

I can derive the list of all the linkquality entities from both the following 2 pieces of code:

{% for item in states.sensor|selectattr('entity_id', 'search', 'linkquality') |map(attribute='entity_id')|list %}
{{item}}
{%- endfor %}

and

{{ states
        | selectattr('entity_id', 'search', 'linkquality')
        | map(attribute='entity_id')
        | list
        | count
        }}

I am struggling to now apply the second filter against this list of entities where I only want to list and count the entities where the LQI is < 50. I tried adding a second selectattr line to read the state of the entity (based on other examples, which mostly check for state = ‘unavailable’ rather than a value) and check that it is less than 50 but I get an error message, even after trying different options around ‘state.state’

{{ states
        | selectattr('entity_id', 'search', 'linkquality')
        | selectattr('state.state'| int < 50])
        | map(attribute='entity_id')
        | list
        | count
        }}

Appreciate if someone could help point me in the right direction in applying the second filter.

Is selectattr the right function to use and it is hence a syntax issue or is selectattr the completely wrong function to use?

Is using the “for” statement as the base a better/cleaner approach?

Many thanks for any help as I’m going round in circles at the moment!

There are multiple issues with the above filter.

  • state.state is not a property of the state object, that should be state
  • Filters cannot be applied to the first argument in a selectattr function, so | int is invalid.
  • There’s an orphaned ].

One option to achieve your goal is to use the, recently added, zip function as follows:

{% set sensor_list = states.sensor | selectattr('entity_id', 'search', 'linkquality')
| selectattr('state', 'is_number') | list %}

{% set ent_list = sensor_list | map(attribute='entity_id') | list %}

{% set states_list = sensor_list | map(attribute = 'state') | map('float') | list %}

{{ zip(ent_list , states_list) | selectattr(1, 'le', 50) | map(attribute=0) | list }}

Another option is as follows:

{% set sensor_list = states.sensor | selectattr('entity_id', 'search', 'linkquality') | selectattr('state', 'is_number') | list %}

{% set state_val_list = sensor_list | map(attribute = 'state') | map('int') | select('le', 50) | map('string') | list %}

{{ sensor_list | selectattr('state', 'in', state_val_list) | map(attribute='entity_id') | list }}

One caveat to this method is that you need to check if the state strings are formatted like integers or floating point numbers so you can map to the correct datatype in the second set statement.

Both codes work well! Will now study the code to understand what you coded and how it works.

Really, really appreciate you taking time to help me out with this - many thanks!