I had to do so much google-fu to figure this script out that I decided to share my learnings.
For context, this script allows me to make a Sonos in my house (I have 9) join the largest group already playing. When I walk into a room, I can push a button and have the Sonos automatically join the largest Sonos group (usually what I want to listen to).
The challenge I had was identifying the largest group of Sonos in the house. I struggled with jinja2, specifically, how to use groupby
as a filter. The next thing I struggled with was how to create a script variable that creates a dictionary from a template (using dict.from_keys
).
Format disclaimer: I use both the visual and YAML editor modes. The visual mode mangles the template code. I apologize for how messy it looks.
Here it is:
alias: Sonos - Join Largest Group playing something
fields:
sonos:
name: sonos
description: entity ID of the Sonos media player to have join the group
advanced: false
required: true
example: media_player.kitchen
default: media_player.downstairs_portable
variables:
largest_group: >
{% set ns = namespace(max_count=0, members=[], master='') -%} {%- for
group_item in expand(integration_entities("sonos") | select("match",
"media_player")) | groupby('attributes.group_members', default=[]) |
map(attribute='grouper') -%}
{%- if group_item | length > ns.max_count -%}
{%- if is_state(group_item | first, 'playing') -%}
{%- set ns.max_count = group_item | length -%}
{%- set ns.members = group_item -%}
{%- set ns.master = group_item | first -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%} {{ dict.from_keys([('members', ns.members), ('master',
ns.master)]) }}
sequence:
- service: system_log.write
enabled: false
data:
message: >-
group members: {{largest_group.members}} and master:
{{largest_group.master}}
- service: media_player.join
data:
group_members: "{{sonos}}"
target:
entity_id: "{{largest_group.master}}"
mode: single