Answering from the same Sonos Speaker / Google Home that was used to initiate the script

When enabling scenes/scripts via Google Assistant on my Sonos speakers I wanted to respond using the same device that I talk to. There’s already amazing script by @TheFes but I couldn’t make it to work with Sonos.

The trick I’m using is to:

  1. Run script that reads the volume levels of all the speakers, save it to input_number variables
  2. Increase the volume of the current speaker by 1% via Google Assistant action
  3. Run script that compares current volume levels with ones saved in step 1, save last active speaker id as input_select variable
  4. Do whatever I need with the above information

It’s not as extensible as the solution mentioned above, but it works for me and I wanted to share it with the community. For the sake of clarity I only include 2 of my speakers, but it works for much bigger number.

Home Assistant configuration

First I need to define input variables in configuration.yaml

input_select:
  last_active_speaker:
    name: "Last active speaker"
    options:
      - media_player.salon_speakers
      - media_player.sonos_sypialnia
input_number:
  volume_salon_speakers:
    name: "Volume of Salon Speakers"
    initial: 0
    min: 0
    max: 100
  volume_sonos_sypialnia:
    name: "Volume of Sypialnia"
    initial: 0
    min: 0
    max: 100

Then I create a script (in my case called debug_script) that will be the first step in my Google Home routine:

debug_script:
  alias: Get Current Speaker Volumes
  sequence:
    - variables:
        volume_current_salon_speakers:
          "{{ state_attr('media_player.salon_speakers',
          'volume_level') }}"
        volume_current_sonos_sypialnia:
          "{{ state_attr('media_player.sonos_sypialnia',
          'volume_level') }}"
    - service: input_number.set_value
      target:
        entity_id: input_number.volume_salon_speakers
      data:
        value: "{{volume_current_salon_speakers}}"
    - service: input_number.set_value
      target:
        entity_id: input_number.volume_sonos_sypialnia
      data:
        value: "{{volume_current_sonos_sypialnia}}"

Another script is going to be called as 3rd step of the routine. In this one I need to iterate through the devices and compare their current volume level with the one saved in the corresponding input variable. In the last step I use the input_select.last_active_speaker to trigger TTS.

debug_script_2:
  alias: Determine Which Speaker Was Used
  icon: mdi:debug-step-into
  mode: single
  sequence:
    - variables:
        volume_current_salon_speakers: "{{ state_attr('media_player.salon_speakers', 'volume_level') }}"
        volume_current_sonos_sypialnia: "{{ state_attr('media_player.sonos_sypialnia', 'volume_level') }}"
        volume_previous_salon_speakers: "{{ states('input_number.volume_salon_speakers') | float }}"
        volume_previous_sonos_sypialnia: "{{ states('input_number.volume_sonos_sypialnia') | float }}"
        target: >
          {% if volume_previous_salon_speakers != volume_current_salon_speakers %}
            media_player.salon_speakers
          {% elif volume_previous_sonos_sypialnia != volume_current_sonos_sypialnia  %}
            media_player.sonos_sypialnia
          {% endif %}
    - service: logbook.log
      data:
        name: "Target speaker from template"
        message: "{{ target }}"
    - service: input_text.set_value
      target:
        entity_id: input_text.last_active_speaker
      data:
        value: "{{ target }}"
    - service: tts.cloud_say
      data:
        cache: false
        entity_id: "{{ target }}"
        message: Test

Google Home Routine

In the Google Home I create a new routine - in this case one called Debug for troubleshooting purposes. Its steps are:

  1. Enable debug_script scene
  2. Change volume by 1%
  3. Enable debug_script_2 scene
  4. Change back volume by 1%

It seems to work pretty well, let me know what you think!

3 Likes

I know what this is an old thread but just wanted to say thanks for this (and also make sure it’s included in google search results for the next person). I just set this up on 5 Sonos speakers + 1 Google Mini, and it works great. Clever idea decrementing then incrementing the volume again. End up being quite a bit of code, and makes for a more complicated routine, but I don’t have a lot that requires HA to speak directly back to the speaker, so it’s a good hack for now (until I switch to HA voice assistant, probably).

Thanks again :+1:

I know this is an even older thread than the last time someone responded to it… but I want to +1 it, and add one more tip. It does seem to work well, but you need to make sure the Google Home devices are turned on (not sure about Sonos). They don’t need to be playing anything… the “idle” or “paused” states seem to work fine… but “off” means you wont have a volume_level attribute on the Google Home devices.