I like the idea here, but your code is poorly optimized. It would be a resource hog. There’s loops and loops and loops. With jinja, you want to take advantage of the filters because they use generators to handle the heavy load. Filters like select, reject, selectattr, rejectattr, and unique.
This replicates your code but it executes extremely fast, even with 1000s of entities and it achieves the same result.
{%- set entities = states | selectattr('domain','in', domains) | list if domains else states | list %}
{%- set ns = namespace(include=[], exclude=[]) %}
{%- for item in includes %}
{%- set ns.include = ns.include + entities | selectattr('object_id', 'search', item) | map(attribute='entity_id') | list %}
{%- endfor %}
{%- for item in excludes %}
{%- set ns.exclude = ns.exclude + entities | selectattr('object_id', 'search', item) | map(attribute='entity_id') | list %}
{%- endfor %}
{%- set entities = entities | map(attribute='entity_id') | select('in', ns.include) | reject('in', ns.exclude) | list %}
{%- set entities = (entities + add) | reject('in', rem) %}
{{ entities | unique | sort }}
Just verify it works for all your use cases, I tried it a bunch and it appeared to do what yours did. Either way, its much faster and it should be the same.
EDIT: speaking of which, found some errors. This should fix em.
{%- set entities = states | selectattr('domain','in', domains) | list if domains else states | list %}
{%- set ns = namespace(include=[], exclude=[]) %}
{%- for item in includes %}
{%- set ns.include = ns.include + entities | selectattr('object_id', 'search', item) | map(attribute='entity_id') | list %}
{%- endfor %}
{%- for item in excludes %}
{%- set ns.exclude = ns.exclude + entities | selectattr('object_id', 'search', item) | map(attribute='entity_id') | list %}
{%- endfor %}
{%- set entities = entities | map(attribute='entity_id') %}
{%- set entities = entities | select('in', ns.include) if ns.include else entities %}
{%- set entities = entities | reject('in', ns.exclude) if ns.exclude else entities %}
{%- set entities = (entities | list + add) | reject('in', rem) %}
{{ entities | unique | sort }}
Here’s what I came up with earlier. Only minor changes from what you posted before. Tested it pretty thoroughly and it appeared to work. Did I miss something?
{%- set entities = states | selectattr('domain','in', domains) | list if domains else states | list %}
{%- set ns = namespace(include=[], exclude=[]) %}
{%- for item in includes %}
{%- set ns.include = ns.include + entities | selectattr('object_id', 'search', item) | list %}
{%- endfor %}
{%- for item in excludes %}
{%- set ns.exclude = ns.exclude + entities | selectattr('object_id', 'search', item) | list %}
{%- endfor %}
{%- set entities = entities | select('in', ns.include if includes else entities ) | reject('in', ns.exclude) | map(attribute="entity_id") | list %}
{%- set entities = (entities + add | list ) | reject('in', rem) %}
{{ entities | unique | sort }}
I just tested the blueprint with only two static entities and it added absolutely all of the entities in home assistant to the group. Something’s not working.
It would be great if your blue print would allow me to create a real ‘group’ from this and keep it in ‘sync’ with the fake group sensor powercalc generates.
Is it possible to also work with friendly names instead of object IDs?
I have tons of Zigbee devices and I normally do not care their object ID, instead I simply rename them to what they should be used for instead (as any normal user would also do). But instead I use a specific naming concept in my friendly names that would be very beneficial to have such dynamic groupings.