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!

2 Likes