Create combinatoric groups: Including and excluding entities from other groups

Tags: #<Tag:0x00007f7c5976f458>

So, I was looking for a way to create groups by combining other groups. The use case is, e.g., to turn off all lights in my flat in case all lights with a physical switch have been turned off. Or, to turn off all lights except some dim lights in the kid’s room.

Implementing this in the actual code base would probably require some sophisticated way of determining the order in which groups are created. So, I started with a pure yaml approach and I think, I will stick to it.

The first part is a script to combine groups, which is defined as follows:

    alias: Create groups with enhanced include/exclude statements
    - service: group.set
        object_id:  "{{ object_id }}"
        name:       "{{ name or object_id }}"
        icon:       "{{ icon or '' }}"
        visible:    "{{ visible or True }}"
        all:        "{{ all or False }}"
        entities: >-
          {# ENTITIES #}
          {% set ns = namespace(entities =
                          (entities.split(',') if entities is string else entities or [])) %}
          {# INCLUDE #}
          {% for group in (include.split(',')  if include  is string else include  or []) %}
          {% set ns.entities = ns.entities +     [group|regex_replace('^.*\.')].attributes.entity_id  | list %}
          {% endfor %}
          {# EXCLUDE #}
          {% for group in (exclude.split(',')  if exclude  is string else exclude  or []) %}
          {% set ns.entities = ns.entities | reject('in',[group|regex_replace('^.*\.')].attributes.entity_id) | list %}
          {% endfor %}
          {# OUTPUT #}
          {{ ns.entities|join(',') }}

It uses group.set to create the groups. You can supply most usual parameters to this service. Plus, in addition to the entities parameter, you can supply both a list of groups whose members to include in the new group as well as a list of groups whose members to exclude from the new group.

This script can then be called during the homeassistant.start event as follows:

- alias: Create test group
  - platform: homeassistant
    event: start
  - service: script.group_set
      name: Test group
      - group.kids_room
      - group.bedroom
      exclude: group.night_lights,group.decorations

Note the two different ways to provide lists to the script.

Probably, an implementation in the actual group component would be better. But until then, this workaround should work around just fine… :wink: If I come up with more ideas on this, I’ll add them here.

Hope this helps someone…

See here for a some related threads:


This is awesome. Thank you. Looks like I can learn a bunch from this single script.

I think triggering your example automation off of group reloads would be a nice improvement. I tried this, but it didn’t work. Any ideas?

      - platform: event
        event_type: group.reload

You’re welcome! :slight_smile:

And I think your improvement really is a good idea. I have no clue, why it doesn’t work though. I don’t use the reload feature at all. Also, I think it wouldn’t even work for me, because it ignores packages. And I heavily rely on those…

If you make it work, let me know. I’ll try and edit the original post then. :+1:

It looks like this may work for triggering off of group reloads: Run automation / script on restart / core / groups / automation reload

I just need to say thank you for this - this is exactly what i’ve been looking for. You clearly have an entirely different view of how to use Homeassistant!