Create combinatoric groups: Including and excluding entities from other groups

Tags: #<Tag:0x00007f3f20841e10>

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:

script:
  group_set:
    alias: Create groups with enhanced include/exclude statements
    sequence:
    - service: group.set
      data_template:
        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 +               states.group[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',  states.group[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:

automation:
- alias: Create test group
  trigger:
  - platform: homeassistant
    event: start
  action:
  - service: script.group_set
    data_template:
      name: Test group
      include:
      - 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:

1 Like