How to make Home-Assistant groups dynamic and user-manageable through Lovelace

Groups of entities are great if the same state change should be applied to multiple entities.
But what if the list of entities in the group should change according to different factors in Home-Assistant or by user preferences?
This can have many use-cases and it is possible to some extent, but such use of groups is poorly documented in the official documentation. So I will in this post explain how the groups can be managed trough service calls, and also how you can set up a intuitively dashboard to manage this in real-time

Groups and service calls

Create a group

To make a permanent group, add it in groups.yaml, formatted like this:

group_name:
  name: "Group friendly Name"

This will be how the group appears when Home-Assistant starts, and it is how groups usually are made.
The group itself and all its properties can also be made trough service calls as I will show below, but these settings are not saved and will not survive a reboot. Therefore the group should be set up in yaml as it should appear at startup. More info about this configuration can be found here: https://www.home-assistant.io/integrations/group/

Service calls

Add one or more entity to a group:

service: group.set
data:
  object_id: name_of_group
  add_entities: domain.entity_a, domain.entity_b

Replace all entities in a group with one or more entities:

service: group.set
data:
  object_id: name_of_group
  entities: domain.entity_a, domain.entity_b

Remove all entities from a group:

service: group.set
data:
  object_id: name_of_group
  entities: []

From what I have found, there is no solution to delete only some entities from the group. It is all or nothing.

Lovelace dashboard

So, how can we create an easy way for end-users to manage this? In my opinion we need three elements:

  • A way to add entities to the group
  • A way to remove entities from the group (In this case all, because of he service call limitations)
  • A way to see which entities that is currently in the group

Below is a screenshot of my proof of concept, organized by Vertical Stack and Horizontal Stack cards:

Explanation of used cards

A

On top there is three normal light entities, just for individual control.

type: light
entity: light.lamp_1

B

Blow are three button cards, these correspond to the entity above. The button is doing a service call to add entity light.lamp_1 to group test_group.

type: button
tap_action:
  action: call-service
  service: group.set
  service_data:
    object_id: test_group
    add_entities: light.lamp_1
  target: {}
name: Add to Group
show_name: true
show_state: false
show_icon: false
hold_action:
  action: none

C

Same kind of button card as above, but just one of them. And this one is removing all entities from the group by using entities: insted of add_entities: (replace insted of add). The value of entities: are set to [] because this represent “none”, an empty value will not work (invalid service call).

type: button
tap_action:
  action: call-service
  service: group.set
  service_data:
    object_id: test_group
    entities: []
  target: {}
show_name: true
show_icon: false
name: Remove all entities from group
hold_action:
  action: none

D

The markdown card is a way we can show the user which entities that are currently in the group. This markdown card with Jinja2 code will display the name off all entities in group.test_group.

type: markdown
content: |-
  **Entities currently in this group:**
  {{ expand('group.test_group')|map(attribute='name')|list|join(', ') }}

E

As a bonus here is also another way to show which entities that are currently in the group. This one is using a custom card, lovelace-auto-entities.
https://github.com/thomasloven/lovelace-auto-entities

It will display entities that are member of the group test_group.

type: custom:auto-entities
card:
  type: entities
filter:
  include:
    - group: group.test_group
  exclude: []
sort:
  method: none

F

At the end a simple entities card with the test_group group, just to control it.

type: entities
entities:
  - entity: group.test_group
    name: Group
show_header_toggle: false
state_color: false

Demonstration

Here is a GIF-animation demonstration of the dashboard in use. As you can see the entities are added to he group, removed from the group, and can be controlled as a group.

The code

At the and, here is the full code for my proof of concept dashboard

type: vertical-stack
cards:
  - type: horizontal-stack
    cards:
      - type: light
        entity: light.lamp_1
      - type: light
        entity: light.lamp_2
      - type: light
        entity: light.lamp_3
  - type: vertical-stack
    cards:
      - type: horizontal-stack
        cards:
          - type: button
            tap_action:
              action: call-service
              service: group.set
              service_data:
                object_id: test_group
                add_entities: light.lamp_1
              target: {}
            name: Add to Group
            show_name: true
            show_state: false
            show_icon: false
            hold_action:
              action: none
          - type: button
            tap_action:
              action: call-service
              service: group.set
              service_data:
                object_id: test_group
                add_entities: light.lamp_2
              target: {}
            name: Add to Group
            show_name: true
            show_state: false
            show_icon: false
            hold_action:
              action: none
          - type: button
            tap_action:
              action: call-service
              service: group.set
              service_data:
                object_id: test_group
                add_entities: light.lamp_3
              target: {}
            name: Add to Group
            show_name: true
            show_state: false
            show_icon: false
            hold_action:
              action: none
  - type: button
    tap_action:
      action: call-service
      service: group.set
      service_data:
        object_id: test_group
        entities: []
      target: {}
    show_name: true
    show_icon: false
    name: Remove all entities from group
    hold_action:
      action: none
  - type: markdown
    content: |-
      **Entities currently in this group:**
      {{ expand('group.test_group')|map(attribute='name')|list|join(', ') }}
  - type: custom:auto-entities
    card:
      type: entities
    filter:
      include:
        - group: group.test_group
      exclude: []
    sort:
      method: none
  - type: entities
    entities:
      - entity: group.test_group
        name: Group
    show_header_toggle: false
    state_color: false

The question is, how can this be useful in a real scenario? I guess this can open up for a lot of cool automations and Interfaces.

Sources

Share