How can I determine which entity is active within a domain?

Hi all, I want to create an automation which figures out which media_player (Google Home device) is currently either ‘idle’ or ‘playing’, rather than ‘off’. The reason is so the automation can send a TTS to the currently active device. In the morning we often say ‘Hey Google, good morning’ which initiates the standard Google routine to tell us the weather, news and any calendar events we have. I want to also get it to run a script to play a TTS of how many days are left until certain events that are entered into HA using this python_script.

The problem is that we sometimes call this Google routine from the bedroom, other times from the kitchen, so I need the automation to figure out which Google Home to send the TTS to. I figure it would generally be the only one that is either ‘idle’ or ‘playing’ at the time since the others in the house would be ‘off’. How would I write a template to figure out which media_player entity_id to send to the TTS script?

Try this out in your dev tools template editor. I adapted it from a couple of other posts and it seems to work as intended.

data_template
  entity_id: >
   {% set on_states = ['idle','playing'] %}
   {{ states | selectattr('domain','in', 'media_player') | selectattr('state','in',on_states) | map(attribute='entity_id') | join(', ') }} 

Awesome! That seems to work in the dev panel. Now to see if I can get the entire script to work as I want. Thanks heaps for that template

It will generate an error if there are no media players that are idle or playing. However as you initiate it using a voice prompt there should always be one.

I like this…

Is there a way to extend it to check whether any of the returned entities have a specific attribute with a specified value? For example (off the top of my head - and obviously this doesn’t work and nor do any of the other tries guesses I’ve had):

   {% set on_states = ['idle','playing'] %}
   {{ states | selectattr('domain', 'in', 'media_player') | 
               selectattr('state', 'in', on_states) | 
               selectattr('shuffle', 'in', 'True') | 
               map(attribute='entity_id') | join(', ') }} 

shuffle being the attribute which can be true or false. (I don’t have use for this specifically, it is just an example).

The way you have the added filter won’t work.

it’s looking for a value (shuttle) to be in a list of possibilities (True). Since “True” isn’t a list (or at least it’s an empty list) it will always be empty so your final list will be empty.

you might be able to do this:

{% set on_states = ['idle','playing'] %}
   {{ states | selectattr('domain', 'in', 'media_player') | 
               selectattr('state', 'in', on_states) | 
               selectattr('shuffle', 'eq', 'True') | 
               map(attribute='entity_id') | join(', ') }} 

then it will look for items in the prior lists that will also only have the shuffle attribute equal to True.

I think…:wink:

EDIT: I’m not sure now. I just tried it and it’s not working for me in the template editor. I need to play some more…

EDIT 2: this is how it’s done: No it’s not…see below…

{% set on_states = ['idle','playing'] %}
   {{ states | selectattr('domain', 'in', 'media_player') | 
               selectattr('state', 'in', on_states) | 
               selectattr('attributes.shuffle', 'eq', 'True') | 
               map(attribute='entity_id') | join(', ') }} 
1 Like

That doesn’t seem to work for me…

image

If you start the template with:

{{ states.media_player

instead of:

{{ states

it allows you to eliminate selectattr('domain', 'in', 'media_player').

1 Like

Just out of curiosity, try this template and see how the shuffle attribute is presented.

   {{ states.media_player | selectattr('state', 'eq', 'paused') | list }} 

shuffle=False

I have already tried False, false, True and true

I also tried ‘volume_level’
selectattr('attributes.volume_level', 'eq', '0.4')

It is presented as
volume_level=0.4

But that didn’t work either

I’m unable to be of much further help because I have no media_players available to test. However, I do have some binary_sensors with an attribute called hidden and I’ve had the same lack of success as you have trying to use selectattr() to filter on attributes.hidden (can’t match any variation of true or false).

After the last few posts saying that the tests for ‘eq’ to some attribute wasn’t working for some reason when I knew it was working for me I’ve been playing and doing some testing. I’m pretty sure I’ve got it worked out. Pardon the resulting wall of text…

As a baseline for reference running this in the template editor:

{{ states | selectattr('domain', 'in', 'media_player') | join(', ') }}

results in this:

<template state media_player.basement_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T22:27:08.362695-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=False, friendly_name=Basement Dot, supported_features=56253 @ 2019-10-20T01:24:31.620621-04:00>, <template state media_player.big_room_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:18:36.161143-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=False, friendly_name=Big Room Dot, supported_features=56253 @ 2019-10-20T01:24:31.625131-04:00>, <template state media_player.browser_mod_ae20a518_c1d40858=unavailable; volume_level=1, is_volume_muted=False, media_content_id=, type=browser_mod, deviceID=ae20a518-c1d40858, supported_features=21005 @ 2019-10-20T20:18:02.004933-04:00>, <template state media_player.browser_mod_c504add7_eda09c09=idle; volume_level=1, is_volume_muted=False, media_content_id=, type=browser_mod, deviceID=c504add7-eda09c09, supported_features=21005 @ 2019-10-20T23:47:27.469141-04:00>, <template state media_player.chromecastaudio1984=off; friendly_name=Livingroom Cast Audio, supported_features=21389 @ 2019-10-20T03:49:46.138632-04:00>, <template state media_player.computer_room_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:40:56.720371-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=False, friendly_name=Computer Room Dot, supported_features=56253 @ 2019-10-20T01:24:31.616608-04:00>, <template state media_player.garage_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:24:08.370505-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=False, friendly_name=Garage Dot, supported_features=56253 @ 2019-10-20T01:24:31.601384-04:00>, <template state media_player.kitchen_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:45:43.846097-04:00, source=Local Speaker, source_list=['Local Speaker', "Jeff's GS5"], available=True, last_called=False, friendly_name=Kitchen Dot, supported_features=56253 @ 2019-10-20T01:24:31.596867-04:00>, <template state media_player.livingroom_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:33:45.512348-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=False, friendly_name=Livingroom Dot, supported_features=56253 @ 2019-10-20T01:24:31.629507-04:00>, <template state media_player.master_bedroom_dot=standby; is_volume_muted=False, media_content_type=standby, media_position_updated_at=2019-10-20T23:45:25.508480-04:00, source=Local Speaker, source_list=['Local Speaker'], available=True, last_called=True, friendly_name=Master Bedroom Dot, supported_features=56253 @ 2019-10-20T01:24:31.592372-04:00>

It seems that for some reason the jinja test for “equal to” doesn’t like comparing things to a boolean (true/True/false/False).

this works in narrowing down the output of the above because 'browser_mod" is a string not a boolean:

{{ states | selectattr('domain', 'in', 'media_player') | selectattr('attributes.type', 'eq', 'browser_mod') | map(attribute='entity_id') | join(', ') }}

and results in this:

media_player.browser_mod_ae20a518_c1d40858, media_player.browser_mod_c504add7_eda09c09

but this doesn’t yield any results because “True” is a boolean:

{{ states | selectattr(‘domain’, ‘in’, ‘media_player’) | selectattr(‘attributes.available’, ‘eq’, ‘True’) | map(attribute=‘entity_id’) | join(’, ') }}

But jinja assumes that if there is no test given that you are trying to test for a boolean.

So this actually works because the “available” attribute is a boolean value (True):

{{ states | selectattr('domain', 'in', 'media_player') | selectattr('attributes.available') | map(attribute='entity_id') | join(', ') }}

And results in this:

media_player.basement_dot, media_player.big_room_dot, media_player.computer_room_dot, media_player.garage_dot, media_player.kitchen_dot, media_player.livingroom_dot, media_player.master_bedroom_dot

And if you wanted to be explicit in the test that you want to run then this is the way to write it (notice there is no quotation marks around True to prevent turning it into a string):

{{ states | selectattr('domain', 'in', 'media_player') | selectattr('attributes.available', 'eq', true) | map(attribute='entity_id') | join(', ') }}

and results in the same output as above:

media_player.basement_dot, media_player.big_room_dot, media_player.computer_room_dot, media_player.garage_dot, media_player.kitchen_dot, media_player.livingroom_dot, media_player.master_bedroom_dot

So finally to get the entity_id’s of all all media players whose states are either idle or playing and that has the shuffle attribute as true then this is what you would use:

{% set on_states = ['idle','playing'] %}
{{ states | selectattr('domain', 'in', 'media_player') | 
               selectattr('state', 'in', on_states) | 
               selectattr('attributes.shuffle', 'eq', true) | 
               map(attribute='entity_id') | join(', ') }} 

I don’t have any media players that have the shuffle attribute so please test it and let me know if it works.

1 Like

Firstly no apology needed for the ‘wall of text’, that was a very good explanation.
Secondly, yes! It works.

Thank you very much, this whole technique is going to be very useful.

I seem to have picked the wrong entity to experiment with because my attempts to match a boolean completely failed for a binary_sensor’s hidden attribute.

Here’s what I mean:

The following binary_sensor’s hidden attribute is set to false. It also happens to be the only one in my home whose state is currently on.

Screenshot%20from%202019-10-21%2008-20-25

Here are the results of three templates.

  1. Produces a result based on state==‘on’
  2. Produces a result based on attributes.friendly_name==‘Laundry Lock’
  3. Produces no result based on attributes.hidden==false

This test is what led me to state, in my previous post, that no variation of true/false (false, False, ‘false’, ‘False’) was giving me success. However, it would appear that my choice of test subject is what led to failure.

I’ve repeated the experiment using groups and filtering on their auto attribute (and hidden attribute) using true and false. That was successful. Yet a binary_sensor’s hidden attribute remains an anomaly that cannot be tested for its state.

The only clue to this behavior is that, if you look at the object produced (see above), it doesn’t list hidden=false. :man_shrugging:

To display a list of the volume levels of the playing speaker, you need to do this

{{ states | selectattr('domain', 'in', 'media_player') | selectattr('state', 'in', 'playing')| map(attribute='attributes.volume_level') |join (',') }}

Текст на русском (Text in Russian)

Чтобы вывести список уровней громкости играющей колонки, нужно сделать так

{{ states | selectattr('domain', 'in', 'media_player') | selectattr('state', 'in', 'playing')| map(attribute='attributes.volume_level') |join (',') }}