Pass group or multiple entities to script

Hi,

I try to create a script and pass a field which could contain a entity, multiple entities or a group (of course with mutiple entities). Now I try to get whats passed to the field and get the first entity.

First steps but do not work:

  fields:
    mp_entity_id:
      name: Scenes Entities
      required: true
      selector:
        entity:
          domain:
            - media_player
            - group
    preset_typ:
      name: Preset Typ
      required: true
      default: 'allgemein'
      selector:
        select:
          options:
            - label: Allgemein
              value: 'allgemein'
            - label: Frühstück
              value: 'fruehstueck'
            - label: Wecker
              value: 'wecker'
            - label: Steffen
              value: 'steffen'
            - label: Petra
              value: 'petra'
  variables:
    mp_master_entity_id: >-
      {% if mp_entity_id.split('.')[0] == 'group' %}
        {{- expand(mp_entity_id)[0] -}}
      {%- else -%}
        {{- mp_entity_id[0] -}}
      {%- endif -%}
    mp_group_entity_id: # Get all entities without the first ...

Thanks for a hint to get that …

OK, a little step on the way. Now I get the master and the members:

  fields:
    mp_entity_id:
      required: true
      selector:
        entity:
          multiple: true
          domain:
            - media_player
            - group
    preset_typ:
      name: Preset Typ
      required: true
      default: 'allgemein'
      selector:
        select:
          options:
            - label: Allgemein
              value: 'allgemein'
            - label: Frühstück
              value: 'fruehstueck'
            - label: Wecker
              value: 'wecker'
            - label: Steffen
              value: 'steffen'
            - label: Petra
              value: 'petra'
  variables:
  variables:
    mp_master_entity_id: >-
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {{- expand(mp_entity_id)[0].entity_id -}}
      {% else %}
        {{- mp_entity_id[0] -}}
      {% endif %}
    mp_member_entity_id: >-
      {% set group_members = namespace(entities=[]) %}
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {% for mp_entity in expand(mp_entity_id) %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity.entity_id] %}
          {% endif %}
        {% endfor %}
      {% else %}
        {% for mp_entity in mp_entity_id %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity] %}
          {% endif %}
        {% endfor %}
      {% endif %}
      {{- group_members.entities -}}

Is this for controlling Sonos media_players and you’re trying to identify the master of a group?

Yes, I want to make a generic script to start sonos scenes. I have preset buttons and want to play a special source to a defined group. The group could be a group or some single entities and the first one is always the master.

So I do not want like now 10 differnet scripts but only one …

Steffen

  • A group entity has an attribute named entity_id. This attribute contains a list of the group’s members. The first item in that list represents the group’s master.

  • The expand filter can be used to produce a list of a group’s members. However, it produces a sorted list (sorted alphabetically). That means the first item in the sorted list may not be the master.

If you want to find the master of a group of media_players, you can’t use expand and must use the group’s entity_id attribute.

Thanks, I do not ant to find the group master from a running group I want to start a new group to play. But good to now that expand produces a sorted list because I want to first defined in the group to get the master for the new playing scene.

What is the purpose of the variable named mp_master_entity_id?

Thats to define who is the new master for the new starting Playing Scene. So now I get that:

  variables:
    mp_master_entity_id: >-
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {{- state_attr(mp_entity_id[0],'entity_id')[0] -}}
      {% else %}
        {{- mp_entity_id[0] -}}
      {% endif %}
    mp_member_entity_id: >-
      {% set group_members = namespace(entities=[]) %}
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {% for mp_entity in state_attr(mp_entity_id[0],'entity_id') %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity] %}
          {% endif %}
        {% endfor %}
      {% else %}
        {% for mp_entity in mp_entity_id %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity] %}
          {% endif %}
        {% endfor %}
      {% endif %}
      {{- group_members.entities -}}

So I can pass a group, a single entity or many entities to the script. Always the first passed is the new master and I get it to the variabel ‘mp_master_entity_id’. All the members (every without master) I get to ‘mp_member_entity_id’. Now I start to the sequence or do you think I’m wrong?

Here a little bit more so I think you can see what i want to do instead of creating a single script for every Sonos scene (combination of player and source) I normally use.

script_sonosscenes_set:
  alias: 'Sonos Szene'
  mode: single
  max_exceeded: warning
  fields:
    mp_entity_id:
      name: Scenes Entities
      description: 'Entities der Sonos Scene (erste ist Master).'
      example: 'media_player.sonos_buero'
      required: true
      selector:
        entity:
          multiple: true
          domain:
            - media_player
            - group
    preset_typ:
      name: Preset Typ
      description: 'Preset (Quelle und Lautstärke Faktor).'
      example: 'allgemein'
      required: true
      default: 'allgemein'
      selector:
        select:
          options:
            - label: Allgemein
              value: 'allgemein'
            - label: Frühstück
              value: 'fruehstueck'
            - label: Wecker
              value: 'wecker'
            - label: Steffen
              value: 'steffen'
            - label: Petra
              value: 'petra'
  variables:
    mp_master_entity_id: >-
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {{- state_attr(mp_entity_id[0],'entity_id')[0] -}}
      {% else %}
        {{- mp_entity_id[0] -}}
      {% endif %}
    mp_member_entity_id: >-
      {% set group_members = namespace(entities=[]) %}
      {% if mp_entity_id[0].split('.')[0] == 'group' %}
        {% for mp_entity in state_attr(mp_entity_id[0],'entity_id') %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity] %}
          {% endif %}
        {% endfor %}
      {% else %}
        {% for mp_entity in mp_entity_id %}
          {% if not (loop.first) %}
            {% set group_members.entities = group_members.entities + [mp_entity] %}
          {% endif %}
        {% endfor %}
      {% endif %}
      {{- group_members.entities -}}
    mp_source: >-
      {{- 'input_text.it_sonosfavcurrent_' + preset_typ -}}
  sequence:
    - service: media_player.unjoin
      data: {}
      target:
        entity_id: '{{ mp_master_entity_id }}'
    - service: media_player.media_pause
      data: {}
      target:
        entity_id: '{{ mp_master_entity_id }}'
    - service: media_player.join
      data:
        group_members: '{{ mp_member_entity_id }}'
      target:
        entity_id: '{{ mp_master_entity_id }}'
    - service: media_player.select_source
      data:
        source: >-
          {{- states('input_text.it_sonosfavcurrent_allgemein') -}}
      target:
        entity_id: '{{ mp_master_entity_id }}'

Now I must do some things with the volume, but first step is done …

Your original template employed expand so it was vulnerable to the problem I described, even for creating a new group.

Yes so now I use this:

{{- state_attr(mp_entity_id[0],'entity_id')[0] -}}
{% for mp_entity in state_attr(mp_entity_id[0],'entity_id') %}

OK or there better ways?

Steffen

In the media_player.join service call, group_members can contain all the media_players to be grouped including the master.

There’s no obligation to supply group_members with a list of media_players that doesn’t include the master. Therefore it eliminates the need for much of what your templates are doing.

OK, so I should only get the first one to set my new master. I think about this and some other points, but thank you very much for your support, I try to get some more in HA scripting …

Steffen