Background: When managing a large number of similar devices (ex. lightbulbs), it can be helpful to apply labels (ex. accent vs. main) on the devices. While I understand some automations can be applied to all devices with a label, more advanced automations may or may not support lists defined by labels (ex. For Each loops).
Use-Case: For all accent lights, test if on/off. If on, change color to XYZ. If off, change color to XYZ, wait 0:02, turn back off (so that when they’re turned on next, they maintain the color).
Current Workaround: maintaining a manually defined group of “light 1”, “light 2”, etc. that I can use in a For Each loop.
Problem statement: As I reconsider which lights are accent lights vs. main lights (or any of the home’s other occupants do) or add new devices, maintaining groups requires more involvement than updating labels.
Request: A method of creating a dynamic group populated with all devices with a specified label.
Note: recognizing that a functional workaround exists for this solution, this is truly just a quality of life issue for me. It would be nice to be able to walk around with the other occupants and quickly update labels, rather than taking notes for later fiddling with groups.
Repeat For Each actions will accept a template that renders a list or dictionary, likewise groups can be created ad hoc using the group.set action. Though, for the majority of uses, labels make such groups redundant.
Well, it is a general issue that HA’s groups cannot be truly dynamic (easily). It’s possible, but “complicated” (so yeah, quality of life improvement needed) and the solutions some would say are not “performant” (although I don’t see any performance issues with my setup).
Take a look at this thread:
You can take the same approach (templated time pattern trigger) to dynamically modify group members.
Another use for this would be for 3rd party integration such as Alexa. Without a lot of needless work around, there really isn’t a way for Alexa to control a dynamic group. I use labels because it’s easier for the wife to mark certain devices with a label when she wants to move devices, like smart plugs, to a different function (such as to control plant lights). It will then be controlled by whatever automation that label uses dynamically. However, you cannot say " Alexa, plant lights on/off and she controls that same dynamic group".
I agree that in several ways, the group and labels would be redundant. But there are also many ways the usefulness would out-weigh the redundancy. Would a compromise be to enable dynamic groups with filters/ templates, much like you can do with Tom_L’s Auto-Entities?
Which is a pain in the ass for people who aren’t experts at this stuff to set up; I think that was the point the OP was making. Yes, there are ways to do it, but they aren’t necessarily intuitive for most users. Having the ability built into the group integration can save a lot of work for people
My use case is this. I have many plants that I define as plant objects. I move these plants around in real space depending on time of year and weather and such. I have a dash board for my plants that lists them all. I break out groups of them using auto entities into sections. I want one that shows me Plants that have the label “Living Room”. And then when I move a plant out to the Porch I just change the label and now it’s happily showing in a different section on the Porch dashboard. That part is achievable. However instead of listing all of the plants I want to have a status box for just the Porch room and I want it to reference all of the Plant objects with label Porch Plant. I was thinking in a Group. If all of them are happy then group status is good. If any are unhappy then group status not good and I can expand it and learn more.
In case someone finding this thread is interested in a script finding entities of a certain domain with a certain label (ID)
this script will return a list as result, which contains all the entities of a given domain that carry a given label_id.
YAML code here
sequence:
- variables:
labeled_ntts: |
{{ label_entities(label_id) }}
all_ntts: >
{{
states|selectattr('domain','eq',domain)|map(attribute='entity_id')|list
}}
found_ntts: "{{ [] }}"
- repeat:
sequence:
- alias: check the entity for the label_id
if:
- condition: template
value_template: >-
{{ ntts_with_that_label == ((repeat.item in labeled_ntts) ==
true) }}
alias: >-
if the entity is in <labeled_ntts> and we are looking for that
label_id / or the total opposite
enabled: true
- alias: "DEBUG: condition always true"
condition: template
value_template: "{{True}}"
enabled: false
then:
- alias: check if groups are include and entity is a group (has members)
if:
- alias: if entity is a new-style group
condition: template
value_template: "{{ state_attr(repeat.item, 'entity_id') != None }}"
then:
- alias: check if groups should be added to the list
if:
- condition: template
value_template: "{{ include_group_ntts }}"
alias: if true include the group entity
then:
- variables:
found_ntts: "{{ found_ntts + [repeat.item] }}"
else:
- variables:
found_ntts: "{{ found_ntts + [repeat.item] }}"
for_each: "{{ all_ntts}}"
- variables:
result:
found_ntts: "{{ found_ntts }}"
error: false
- stop: done
response_variable: result
alias: get list of labeled entities
description: >-
# get list of labeled entities
## v0.1 - preliminary version
this script will return a list as _result_, which contains all the
__entities__ of a given _domain_ that carry a given _label_id_.
Following switches are available (not required):
- *ntts_with_that_lable* (default: true)
- *include_group_ntts* (default: false)
fields:
domain:
selector:
text: null
name: domain
required: true
description: the domain the entities should be matched to label_id e.g. 'cover'
label_id:
selector:
text: null
name: label_id
required: true
description: >-
the label_id that the entities are carrying (or do not carry this label_id, see
switch <ntts_with_that_lable>) e.g. 'my_special_label'
ntts_with_that_label:
selector:
boolean: {}
name: ntts_with_that_label
description: >-
if true (default) the list will contain all entities with <label_id> / if
false it will contain all entities without <label_id>
default: true
include_group_ntts:
selector:
boolean: {}
name: include_group_ntts
default: false
description: >-
if false (default) then the list will not include new-style group entities
of given domain / if true it will include groups in the list
It can be used to create an ad-hoc group (old-style) with group.set
This is a preliminary version and if it proves helpful I will try to make it into a blueprint.
Any thoughts or feedback are appreciated.
I am new to HA and YAML, so do not expect this to be coded perfectly
if you want to find entities with a certain label then all you have to do is:
{{ label_entities(label_id) }}
This, however, does also include new-style groups, which you may not want.
Also, my application needed to exclude the entity with that label (I wanted to be able to disable an entity with the label disabled
There is no need to have a script iterate through every entity in your system just to find those that are in a certain domain, have a certain label, and aren’t a group… that can be done in one template
{% set l = label_entities(label_id) | select('match',domain) | list %}
{% if not include_group_ntts %}
{% set l = l | expand | rejectattr('attributes.entity_id', 'defined')
| map(attribute='entity_id') | list %}
{% endif %}
{% if not ntts_with_that_label %}
{% set l = states[domain]|map(attribute='entity_id')|list| difference(l) %}
{% endif %}
{{ l }}
If you need to use it in multiple places, you could set it up as a custom macro.
Macro Option
#tools.jinja
{% macro labelled_domain(label, domain,
ntts_with_that_label, include_group_ntts, returns)%}
{% set l = label_entities(label_id) | select('match',domain) | list %}
{% if not include_group_ntts %}
{% set l = l | expand | rejectattr('attributes.entity_id', 'defined')
| map(attribute='entity_id') | list %}
{% endif %}
{% if not ntts_with_that_label %}
{% set l = states[domain]|map(attribute='entity_id')|list| difference(l) %}
{% endif %}
{%- do returns(l) %}
{%endmacro%}
Then, to return the list in a script or automation you would use something like:
{% from 'tools.jinja' import labelled_domain %}
{% set l_d = labelled_domain | as_function %}
{{ l_d('plant_related', 'light',false,true) }}
{% set label_id = 'disabled' %}
{% set domain = 'cover' %}
{% set include_group_ntts = false %}
{% set ntts_with_that_label = true %}
{% set l = label_entities(label_id) | select('match',domain) | list %}
{% if not include_group_ntts %}
{% set l = l | expand | rejectattr('attributes.entity_id', 'defined')
| map(attribute='entity_id') | list %}
{% endif %}
{% if not ntts_with_that_label %}
{% set l = states[domain]|map(attribute='entity_id')|list| difference(l) %}
{% endif %}
{{ l }}
I’ve got an example of this in Fridays Party. Labels are first class citizens in my system for what looks like I suspect the same reason they are in yours. You WILL need Spook (to provide the service call). The only thing you can’t do is set the color, icon or description. But yes you can create and set and tag and untag.