I have a list consisting of usr_id, person.xxx and device.tracker
I want to convert the usr_id to person (empty if no person found) and save the result in a list.
I then intend to clean up the list of duplicates
Here’s what I’ve managed to do
{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"]
%}
{%- for result in results %}
{%- if states.person | selectattr("attributes.user_id", "==", result) | first != null %}
person.{{ states.person
| selectattr("attributes.user_id", "==", result)
| map(attribute="attributes.id")
| first }}
{%- elif 'person' in result or 'device_tracker' in result %}
{{result}}
{%- endif %}
{%- endfor %}
Returns the following result. The second entry in the list was not found as usr_id, so it is deleted
To extract data out of a loop you would use a namespace, but I would avoid the loop altogether for this case since the two “types” are easily distinguishable.
{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"] %}
{% set non_id = results | select('match', 'person|device_tracker') | list %}
{% set id = results | reject('search', '\.') | list %}
{% set id_people = states.person
| selectattr('attributes.user_id', 'in', id)
| map(attribute='entity_id') | list %}
{{ (non_id + id_people) | unique | list }}
Namespace version... if you just prefer loops
{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"] %}
{% set ns = namespace(people=[]) %}
{%- for result in results %}
{%- if states.person | selectattr("attributes.user_id", "==", result) | first != null %}
{% set person = states.person | selectattr("attributes.user_id", "==", result)
| map(attribute="entity_id") | first %}
{% set ns.people = ns.people + [person] %}
{%- elif 'person' in result or 'device_tracker' in result %}
{% set ns.people = ns.people + [result] %}
{%- endif %}
{%- endfor %}
{{ ns.people | unique | list }}
Your method is much more elegant. Generating several clean lists and then assembling them is so much cleaner than working on the original list with a loop.
Thanks to your help, here’s the finished template. This is a brick for targeting the device or person to be notified
{# Si vide, extraction de tout les mobile_app #}
{% if personnes == '' or personnes is not defined %}
{{ integration_entities('mobile_app')
| select('match','device_tracker')
| list }}
{% else %}
{# Convertion chaine en liste #}
{% if personnes.entity_id is string %}
{% set personnes = { 'entity_id': [personnes.entity_id]} %}
{% endif %}
{# Récupération des person et device_tracker en liste #}
{% set non_id = personnes.entity_id | select('match', 'person|device_tracker') | list %}
{# Conversion des usr_id en person #}
{% set id = personnes.entity_id | reject('search', '\.') | list %}
{% set id_people = states.person
| selectattr('attributes.user_id', 'in', id)
| map(attribute='entity_id') | list %}
{# Définition liste de person et device_tracker sans doublon #}
{{ (non_id + id_people) | unique | list }}
{% endif %}
It processes a list randomly composed of usr_id, person and device_tracker
If the list is empty, all notifiable devices are extracted
I use the person and device_tracker objects to evaluate the distance to a zone
To notify them, I use another part of the template
Info: {{cible_tmp}} is one of the elements in the {{cible}} list
{# Conversion de person en mobile_app #}
{% if 'person.' in cible_tmp %}
{{ expand(cible_tmp)
| map(attribute='attributes.source')
| list
| join
| replace('device_tracker.', 'mobile_app_') }}
{# Conversion de device_tracker avec GPS en mobile_app #}
{% elif 'device_tracker.' in cible_tmp and (state_attr(cible_tmp,'gps_accuracy') or 0 ) > 0 %}
mobile_app_{{ state_attr(cible_tmp,'friendly_name') | slugify }}
{# Déjà un mobile_app #}
{% elif 'mobile_app_' in cible_tmp %}
{{ cible_tmp }}
{# Les autres cas sont ignoré #}
{% endif %}