Hi All,
I have a simple question where I just cant find or figure out the answer to. It must be a simple thing that I am just missing, so sorry in advance
I am searching for a selectattr or rejectattr that results in just my Sonos rooms/entities. The idea (among other things) is that I afterwards want to make a select on source, so once a speaker has the same source (say radio channel), it will be joined instead of playing on itâs own.
Look at the attributes listed for your Sonos media_player entity in Developer Tools > States. Those are the only attributes accessible to a template.
The first thing youâll notice is that manufacturer is not included in the list of available attributes.
If you wish, you can add a custom attribute that indicates the entityâs integration is sonos. Once thatâs done, a template can easily report all media_players whose integration attribute is sonos.
In this example I called the custom attribute integration but you can choose whatever name you want (provided it isnât identical to an existing attributeâs name).
Or depending on how your Sonos devices entity_ids are named you could use this:
{{states.media_player | selectattr("entity_id", "search", "sonos") | map(attribute='entity_id') | list }}
All of mine contain the string âsonosâ (âmedia_player.sonos_diningroomâ, âmedia_player.sonos_kitchenâ, âmedia_player.sonos_livingroomâ).
you wonât need the extra customization step that way.
yeah, I knew where that was going. I could see it a mile away.
I have several media players and some of them are in the same room so I need to differentiate those media players from each other so I donât have two (or more) âmedia_player.livingroomâ entities. If Iâm already differentiating I may as well maintain a consistent naming method to help keep it all straight without needing to look in the entity attributes to see which entity is a Sonos speaker or which is an Echo device or my living room tv, etc.
and I donât also now have to keep track of another bit of code that I had to create to do the customization. Itâs all self contained in the entity_id.
Iâm not against customizations if they are useful and not redundant. Itâs a âtwo birds with one stoneâ thing.
Iâve actually used that exact method of creating customizations for all of my zwave devices with a âintegration: zwavejsâ attribute since the entity naming didnât lend itself to differentiating the other way.
I assume you are using the Alexa Media Player integration? That would explain why your Echo devices appear as media_player entities.
If the room has both a Sonos and an Echo then you have more than one similarly named media_player and therefore need to differentiate them. I understand how, in this situation, adding sonos to the object_id becomes mandatory.
In my case, I am not using Alexa Media Player for my âAlexa-enabledâ devices; only the Sonos speakers are represented as media_players. Iâve developed the habit of adding a custom integration attribute to most entities. It makes it easier for me to differentiate sensors for example (Homekit? MQTT? Tasmota?).
Hmmm, I first read it on my phone and mixed some posts.
But looking at the computer, I think Iâll look further since there is a relation between manufacturer and device/entity as shown in the example. Looking at the level HA is at the moment, itâs hard to imagine that it is not possible to just list all devices of a certain manufacturer.
Maybe the way to go is to create an array output of the PoC
{% for state in states.media_player -%}
{%- if is_device_attr(state.entity_id, 'manufacturer', 'Sonos') %} {{ "\n"}}- {{ state.name }} {% endif -%}
{%- endfor %}
Renaming my entities isnât my preferred choice either, then I guess I will just create a group with the entities in it. Probably the most CPU friendly way too.
Thanks all for your replies and Iâll report back once I have a nice solution.
I keep forgetting about the new device-oriented functions that were recently added to Home Assistant.
Youâre correct, itâs now possible for a template to access more information than what is shown in Developer Tools> States (by referencing its associated device).
If youâre interested, hereâs a shorter way to get a list of all Sonos media_player entities:
{% set ns = namespace(player=[]) %}
{% for state in states.media_player if is_device_attr(state.entity_id, 'manufacturer', 'Sonos') %}
{% set ns.player = ns.player + [state.entity_id] %}
{%- endfor %}
{{ ns.player }}
Yes, a group would be the most efficient. To reference the groupâs members in a template, just use the expand function.
If you wish, you can create a dynamic group; create an automation triggered on startup (and Reload Group) that uses your template to construct a group. Should you ever add another Sonos speaker, executing Reload Group, or restarting Home Assistant, will automatically add it to the group.
However, if you donât foresee that you will be adding many new speakers, a statically defined group is simpler to implement.
Thatâs exactly what I did.
Referring to your improvement, thanks for that. Besides that itâs shorter, what I like, Itâs better too cause mine has an empty element that I had to remove using the -1 in {{ Sonos.player.split(',')[0:-1] }}.
Iâm following a similar method to group all Sonoâs speakers in the house. What i canât figure out is how to set one of the discovered entities (speakers) as Master. In your case, after joining the speakers, do you set one as Master? If so, what code is used to complete the task?
If you are referring to the sonos.join service call, the master must be defined at the moment the join is performed (not afterwards).
FWIW, I have several predefined groups (upstairs, downstairs, all, etc) where the first group member represents the master. Therefore the first item (zeroth index) in the groupâs entity_id attribute is the master speaker (and supplied as the value for the master option of a sonos.join service call).
Whatâs important is that you have to reference it directly from the list in the groupâs entity_id attribute and not by expanding the group. When you use expand, the list it produces is sorted alphabetically, so whatever you had as the first item may no longer be first (and you can no longer be certain which one represents the groupâs master).
@123; yes, I am referring to the sonos.join service call (should have explained that!).
I have a couple of Sonoâs units which are used on a patio. Sometimes theyâre not turned on so predefining groups doesnât seem to be an option. Iâm looking for a way of determining determining which units are online then joining those units into a group. I understand the master must be defined at the time the join command is issued. Iâm thinking of using the first item in the array list as the master. What I cannot figure out is how to use information collected in the array to setup the group. How do I know how many speakers are defined in the group. The array.length function seems like it will provide a count on the number of active speakers. How do I use this information to create a group with the first item in the array set as the master?
Maybe itâs best to create a new topic so other users with the same question are able to find it (in the future) as-well. If the question is clear, the solution isnât likely to be very complicated. Now the solution might remain unseen because this topic already has a solution.
I just ran into a problem where I needed a quick way to get all of the Sonos media players.
This worked for me and leverages the new integration_entities filter that was added in the last few months Templating - Home Assistant
{{ integration_entities("sonos") | select("match", "media_player") | list }}
The additional select is required because integration_entities returns additional entities like sensor.move_battery for my Sonos Move and binary_sensor.living_room_microphone for my Sonos Arc. If you donât have a Move or Arc, it might not be necessary.