Got it, thanks.
Very cool! Nice work. Any chance you mind sharing how you got the sonos images for icons?
any idea what im missing here? my media_players are named like media_player.basement.
I am getting some errors like it is not getting the entity id for some reason. Ive been starring at this trying to find where it is messing up and cant narrow it down. I believe it is in the sensor. Since your were named a little differnet im wondering if i missed a change somewhere. I have a lot of other things tied to those entity names and it would be too much to change like you have. If you have a minute to take a look it would be appreciated.
Sensor:
- platform: template
sensors:
sonos_join_speakers:
entity_id:
- input_boolean.living_room_slave
- input_boolean.bedroom_slave
- input_boolean.basement_slave
value_template: >-
{% set master = states.sensor.sonos_group_master.state %}
{% for player in states.media_player -%}
{%- set domain, device = player.entity_id.split('.') -%}
{%- set new_domain = "input_boolean" -%}
{%- set new_device = [device, "slave"]|join("_") -%}
{%- set switch = [new_domain,new_device] | join(".") -%}
{%- if is_state(switch, 'on') and player.entity_id != master -%}
{{player.entity_id}},
{%- endif -%}
{%- endfor %}
sonos_unjoin_speakers:
entity_id:
- input_boolean.living_room_slave
- input_boolean.bedroom_slave
- input_boolean.basement_slave
value_template: >-
{% set master = states.sensor.sonos_group_master.state %}
{% for player in states.media_player -%}
{%- set domain, device = player.entity_id.split('.') -%}
{%- set new_domain = "input_boolean" -%}
{%- set new_device = [device, "slave"]|join("_") -%}
{%- set switch = [new_domain,new_device] | join(".") -%}
{%- if is_state(switch, 'off') and player.entity_id != master -%}
{{player.entity_id}},
{%- endif -%}
{%- endfor %}
sonos_not_group_slaves:
friendly_name: Not Group Slaves
value_template: >-
{% for player in states.media_player if player.attributes.is_coordinator -%}
{%- if loop.last -%}{{player.entity_id}}--
{%- else -%}{{player.entity_id}};
{%- endif -%}
{%- endfor %}
sonos_group_slaves:
friendly_name: Group Slaves
value_template: >-
{% for player in states.media_player if player.state == 'playing' and not player.attributes.is_coordinator -%}
{%- if loop.last -%}{{player.entity_id}}--
{%- else -%}{{player.entity_id}};
{%- endif -%}
{%- endfor %}
sonos_group_song:
friendly_name: Group Song
value_template: >-
{% for player in states.media_player if player.state == 'playing' and not player.attributes.is_coordinator %}
{{player.attributes.media_title}}
{% endfor %}
sonos_group_master:
entity_id:
- sensor.sonos_group_song
value_template: >-
{% set group_song = states.sensor.sonos_group_song.state %}
{% for player in states.media_player if player.state == 'playing' and player.attributes.is_coordinator and player.attributes.media_title in group_song %}
{{player.entity_id}}
{% endfor %}
script:
sonos_group_speakers:
sequence:
- service: media_player.sonos_join
data_template:
master: >-
{% if is_state("input_select.master_sonos", "Living Room") %}media_player.living_room
{% elif is_state("input_select.master_sonos", "Basement") %}media_player.basement
{% elif is_state("input_select.master_sonos", "Bedroom") %}media_player.bedroom
{% endif %}
entity_id: '{%- set slaves = states.sensor.sonos_join_speakers.state -%}{{slaves[:-1]}}'
- service: media_player.sonos_unjoin
data_template:
entity_id: '{%- set slaves = states.sensor.sonos_unjoin_speakers.state -%}{{slaves[:-1]}}'
automations:
- alias: 'Set Sonos States'
initial_state: on
trigger:
- platform: state
entity_id: sensor.sonos_group_slaves
- platform: state
entity_id: sensor.sonos_not_group_slaves
- platform: state
entity_id: sensor.sonos_group_master
- platform: homeassistant
event: start
action:
- service: input_select.select_option
data_template:
entity_id: input_select.master_sonos
option: >-
{% set master = states.sensor.sonos_group_master.state %}
{% if master == "media_player.living_room"%}Living Room
{% elif master == "media_player.bedroom"%}Bedroom
{% elif master == "media_player.basement"%}Basement
{% endif %}
- service: input_boolean.turn_on
data_template:
entity_id: '{%- set slaves = states.sensor.sonos_group_slaves.state -%}{{slaves|replace("--", "_slave")|replace(";", "_slave, ")|replace("media_player", "input_boolean")}}'
- service: input_boolean.turn_off
data_template:
entity_id: '{%- set slaves = states.sensor.sonos_not_group_slaves.state -%}{{slaves|replace("--", "_slave")|replace(";", "_slave, ")|replace("media_player", "input_boolean")}}'
input_select:
master_sonos:
name: Master Sonos Player
icon: mdi:itunes
options:
- Living Room
- Basement
- Bedroom
@darbos at first glance I can’t see anything wrong. What errors are you getting? It would be helpful to see those. Also, do you plan on updating right away to 0.67 when it comes? Because there are changes coming to the Sonos component with the grouping and you’ll have to change this if you plan on updating.
lol sorry about that. I meant to include them, too much pasting in forgot
Thats good to know I appreciate it. It really depends on what is released with the new updates if I go to them. If it something useful for me then I usally do them, or Ill take a snapshot in vmware, upgrade and see how it goes then if i need to I can revert. I am on 65.6 right now, I tried 66.0 but I just had that small bug with my ecobee, I believe they fixed it in 66.1 but I havent upgraded. Now knowing that sonos will be upated in 67 Ill just hold off and upgrade to upgrade until then. Still great work here!
I do have some family and friends coming in town this weekend and was trying to show off
If you see something pop out Id appreciate it, otherwise I can hang tight I dont want to waste your time.
IndexError: list index out of range
2018-04-11 19:10:56 WARNING (MainThread) [homeassistant.components.input_select] Invalid option: (possible options: Select Master, Living Room, Basement, Bedroom)
2018-04-11 19:10:56 ERROR (MainThread) [homeassistant.core] Invalid service data for input_boolean.turn_on: Entity ID is an invalid entity id for dictionary value @ data['entity_id']. Got ''
@Darbos Ok, yeah that error came up for me too. Here’s what I suggest, if you’re interested for something this weekend. Create a custom component using the latest sonos.py
Put this in .homeassistant/custom_components/media_player/ directory. If you don’t have it, create it. This way you can stay at 65.6 but use the latest Sonos.
Then here’s my latest yaml using this update. It’s a bit simplier.
Template Sensors:
sonos_join_speakers:
entity_id:
- media_player.living_room
- media_player.bedroom
- media_player.basement
value_template: >-
{% set master = states.sensor.sonos_group_master.state %}
{% for player in states.media_player -%}
{%- set domain, device = player.entity_id.split('.') -%}
{%- set new_domain = "input_boolean" -%}
{%- set switch = [new_domain,device] | join(".") -%}
{%- if is_state(switch, 'on') and player.entity_id != master -%}
{{player.entity_id}},
{%- endif -%}
{%- endfor %}
sonos_unjoin_speakers:
entity_id:
- media_player.living_room
- media_player.bedroom
- media_player.basement
value_template: >-
{% set master = states.sensor.sonos_group_master.state %}
{% for player in states.media_player -%}
{%- set domain, device = player.entity_id.split('.') -%}
{%- set new_domain = "input_boolean" -%}
{%- set switch = [new_domain,device] | join(".") -%}
{%- if is_state(switch, 'off') and player.entity_id != master -%}
{{player.entity_id}},
{%- endif -%}
{%- endfor %}
sonos_group_master:
entity_id:
- media_player.living_room
- media_player.bedroom
- media_player.basement
value_template: >-
{%- for player in states.media_player if player.state == 'playing' and player.attributes.sonos_group %}
{% if player.attributes.sonos_group[0] == player.entity_id %}
{{player.entity_id}}
{% endif %}
{% endfor -%}
sonos_not_group_slaves:
friendly_name: Not Group Slaves
entity_id: sensor.sonos_group_slaves
value_template: >-
{% for player in states.media_player if player.attributes.sonos_group %}
{% set n = player.attributes.sonos_group %}
{%- if n|length == 1 -%}
{{player.entity_id}},
{%- endif -%}
{%- endfor %}
sonos_group_slaves:
friendly_name: Group Slaves
entity_id: sensor.sonos_group_master
value_template: >-
{%- for player in states.media_player if player.state == 'playing' and player.attributes.sonos_group %}
{%- if player.attributes.sonos_group[0] == player.entity_id %}
{%- set slaves = player.attributes.sonos_group[1:] %}
{{ slaves|join(",")|replace("media_player", "input_boolean") }}
{%- endif %}
{%- endfor %}
Use these Input Booleans instead:
living_room:
name: Living Room
basement:
name: Basement
bedroom:
name: Bedroom
Automation:
- alias: 'Set Sonos States'
initial_state: on
trigger:
- platform: state
entity_id: sensor.sonos_group_slaves
- platform: state
entity_id: sensor.sonos_not_group_slaves
- platform: state
entity_id: sensor.sonos_group_master
- platform: homeassistant
event: start
condition:
condition: and
conditions:
- condition: template
value_template: '{% if states.sensor.sonos_group_slaves.state != "" and states.sensor.sonos_group_master.state != "" %}true{%endif%}'
action:
- service: input_select.select_option
data_template:
entity_id: input_select.master_sonos
option: >-
{% set master = states.sensor.sonos_group_master.state %}
{% if "media_player.living_room" in master %}Living Room
{% elif "media_player.bedroom" in master%}Bedroom
{% elif "media_player.basement" in master%}Basement
{% endif %}
- service: input_boolean.turn_on
data_template:
entity_id: '{{states.sensor.sonos_group_slaves.state}}'
- condition: template
value_template: '{% if not is_state("sensor.sonos_not_group_slaves", "")%}true{%endif%}'
- service: input_boolean.turn_off
data_template:
entity_id: '{%- set slaves = states.sensor.sonos_not_group_slaves.state -%}{{slaves[:-1]|replace("media_player","input_boolean")}}'
Input Select:
master_sonos:
name: Master Sonos Player
icon: mdi:itunes
options:
- Living Room
- Basement
- Bedroom
Script:
sonos_group_speakers:
sequence:
- service: media_player.sonos_join
data_template:
master: >-
{% if is_state("input_select.master_sonos", "Living Room") %}media_player.living_room
{% elif is_state("input_select.master_sonos", "Basement") %}media_player.basement
{% elif is_state("input_select.master_sonos", "Bedroom") %}media_player.bedroom
{% endif %}
entity_id: '{%- set slaves = states.sensor.sonos_join_speakers.state -%}{{slaves[:-1]}}'
- service: media_player.sonos_unjoin
data_template:
entity_id: '{%- set slaves = states.sensor.sonos_unjoin_speakers.state -%}{{slaves[:-1]}}'
@Darbos and here’s the images I use for Sonos speakers. Put them in your www directory and reference them to your input_booleans in the customize section like this:
input_boolean.living_room:
entity_picture: /local/sonos_playbar.png
man your awesome. took the time to write it with my players and all, thank you very much!
Its working now I really appreciate it! I see now in the attributes it shows you sonos_group now. that is great!
Hey I was looking through the 67.0 notes and the sonos component page but dont see a mention of any changes to the grouping abilities? Did it not make it into 67? Thanks
@Darbos I looked for it too, doesn’t look like it made it into 0.67. Not sure why (I’m not the dev) but for now, you can keep running the custom component.
I appreciate it, was just curious.
@Jer78 I have been looking at this solution for some time, and now it seems that grouping capabilities made it into the 0.69 update https://github.com/home-assistant/home-assistant/pull/13553
Is there a chance that you are going to revise your scripts to incorporate this grouping scheme into this nice solution? I would be first in line to do some trying and testing
@Flemming Yes, it’s posted above…and as you mentioned since 0.69 you no longer need to use the custom component.
Aaah, I think i get it now. Sorry i’m new to all this, running hassio with not too much messing around. I will give it a shot during the coming weekend.
Thanks <3
Here’s a script for joining and unjoining speakers by voice as I promised. You’d just have to expose the scripts to Alexa, however you’d like (emulated_hue, Alexa cloud, or Node-Red)
alexa_join_living_room:
sequence:
- service: media_player.sonos_join
data_template:
master: '{{states.sensor.sonos_group_master.state}}'
entity_id: media_player.sonos_living_room
- delay:
seconds: 2
- condition: template
value_template: '{% if states.media_player.sonos_living_room.state != "playing" %}true{%endif%}'
- service: media_player.media_play
data_template:
entity_id: '{{states.sensor.sonos_group_master.state}}'
alexa_unjoin_living_room:
sequence:
- service: media_player.sonos_unjoin
entity_id: media_player.sonos_living_room
Any chance that you could post a Node-RED example in raw text if you have one? I just started dabbling with Node-RED and quite confused on how this all works. Thanks
I use the Alexa-Local plugin. Here’s the export and a pic of what it looks like…
[{"id":"577d210.567686","type":"api-call-service","z":"110d3f7c.322759","name":"Living Room Speaker On","server":"85fe7d0f.5ecf7","service_domain":"script","service":"turn_on","data":"{\"entity_id\":\"script.alexa_join_living_room\"}","x":450,"y":2040,"wires":[]},{"id":"dbeb0490.360678","type":"alexa-local","z":"110d3f7c.322759","devicename":"Living Room Speaker","inputtrigger":false,"x":120,"y":2060,"wires":[["de740a3c.c92e48"]]},{"id":"de740a3c.c92e48","type":"switch","z":"110d3f7c.322759","name":"Switch","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"on","vt":"str","case":true},{"t":"regex","v":"off","vt":"str","case":true}],"checkall":"true","outputs":2,"x":250,"y":2060,"wires":[["577d210.567686"],["39af6e4d.42311a"]]},{"id":"39af6e4d.42311a","type":"api-call-service","z":"110d3f7c.322759","name":"Living Room Speaker Off","server":"85fe7d0f.5ecf7","service_domain":"script","service":"turn_on","data":"{\"entity_id\":\"script.alexa_unjoin_living_room\"}","x":450,"y":2080,"wires":[]},{"id":"85fe7d0f.5ecf7","type":"server","z":"","name":"Home Assistant","url":"redacted","pass":"Redacted"}]
Perfect, thank you very much … I will give it a try tonight
Awesome, thanks again!