[Templating] Find all Sonos Media Players which are the master of a group

Hello Template Ninjas,

I am looking for a way to find a list of all media players which are the master of a group … bc I only want to show those in the UI.

What I did find out … There is an easy way to find if a player is the master of a group. This is true for those being a master of a group

{{ states.media_player.ralf.attributes.group_members|first == 'media_player.ralf'}}

What is the easiest way to set up a list of players and then filter them down to those which are Master?

I must admit I am not good in templating yet to get this done.

Target is to have an auto-entity populating with all players … which are master.

Regards
Ralf

Getting there slowly …

{{ states.media_player.ralf.attributes.group_members|first == 'media_player.ralf'}}

{% for player in expand(states.media_player) | selectattr('state','eq','playing') %} | 
   {{ player.entity_id }}
   {{ state_attr(player.entity_id, 'group_members') }}
{% endfor %}

gives

True

 | 
   media_player.eltern
   ['media_player.ralf', 'media_player.eltern']
 | 
   media_player.ralf
   ['media_player.ralf', 'media_player.eltern']

when I add first into the mix like in the above example which works … I get an error

{% for player in expand(states.media_player) | selectattr('state','eq','playing') %} | 
   {{ player.entity_id }}
   {{ state_attr(player.entity_id, 'group_members') | first }}
{% endfor %}

Error is TypeError: 'NoneType' object is not iterable.

Any help still appreciated.

Yes, the first item in group_members represents the master but it’s not “grouped” unless there’s more than one item.

If you want to select the master media_player of a grouped set of media_players, the media_player’s group_members attribute should contain more than one item.

Hi Taras,

understood. Both players in this example are grouped (together). Thats why the output of {{ state_attr(player.entity_id, 'group_members') }} gives a list namely ['media_player.ralf', 'media_player.eltern'].

My expectation is adding | first will give me the first element. If you do the example without the for loop it works.

{{ state_attr('media_player.ralf', 'group_members') }}
{{ state_attr('media_player.ralf', 'group_members') | first  }}

gives

['media_player.ralf', 'media_player.eltern']
media_player.ralf

Adding first in aboves loop statement gets the error.

Unless you check if they’re actually grouped, each one will be identified as a master.

I have several media_players and some are grouped but others are not. So if you want to create a general purpose template to select the masters of grouped media_players, it needs to ensure the media_player is actually grouped (i.e. more than one item in group_members).

Please try on your side. A non grouped player has a list with one element … at least for me.

Grouped
{{ state_attr('media_player.ralf', 'group_members') }}

['media_player.ralf', 'media_player.eltern']


Nongrouped
{{ state_attr('media_player.kuche', 'group_members') }}

['media_player.kuche']

And I want to select all players which play … and if they are grouped I only want to have the master.

This should be part of the solution … but the “first” is not working.

{% for player in states.media_player | selectattr('state','eq','playing') %} | 
   {{ state_attr(player.entity_id, 'group_members') | first }}
{% endfor %}

That’s exactly what I said. If you want grouped players, you have to select the ones that have more than one item in group_members. The template you posted doesn’t do that. It simply attempts to report the first item in the list, even if there’s only one item.

True.

# from those playing
{% for player in expand(states.media_player) | selectattr('state','eq','playing') %}
# I want all of those (grouped or ungrouped) where the following is true:
   {{ state_attr(player.entity_id, 'group_members') | first == player.entity_id}}
{% endfor %}

I need help in two ways

  1. selecting the first is not working in this example. It works when specifically using the entity id. But not in the for loop with the variable. Why?
  2. how to build a group of exactly those players where the condition will evaluate true

Regards
Ralf

Copy-paste the following template into the Template Editor and confirm it produces a list containing the desired media_players.


{% set ns = namespace(players = []) %}
{% for player in states.media_player 
     | selectattr('state', 'eq', 'playing') 
     | selectattr('attributes.group_members', 'defined')
     if player.attributes.group_members[0] == player.entity_id %} 
  {% set ns.players = ns.players + [player.entity_id] %}
{% endfor %}
{{ ns.players }}

1 Like

Hello @Taras,

BIG Thank you. Confirmed! And I learned a lot about templating.

Yours sincerely.
Ralf

1 Like

Here is the full solution:

raising this from the dead just to say thanks! I was searching for something completely unrelated today and came across this. I had gone through similar trials and troubles trying to get this to work for a while and eventually gave up. I actually had the template working but didn’t know how to apply the mini-media-player to the template entity in auto-entities. So thanks very much for putting this out there! Works great for me.

Thanks. Yes. This is still running on my side and I prefer now steering my sonos setup via HA over the Sonos app.