Script to send actions to the right Google Home (based on voice commands)

Background

In another post I have share a script to send actions to a Google Home and resume the stream (TuneIn / Spotify) which was playing afterwards. It also restores the volume, and you can work with Google Home speakers groups.

In my home I have several Google Nest/Home speakers, and I had some scripts where a TTS would be sent which was triggered by a Google Home routine. However, I could only set it to a predefined Google Home speaker, and not to the specific speaker on which I gave the voice command.

This made me thinking, and I found a solution for this, using the ambient sounds which you can start in your routines.

So I made a new script, which can be used in cooperation with the other script, to send a TTS or other actions, like e.g. an image, or a cast of your Lovelace dashboard to specific Google Home after you ask a question to it.

The script itself relies on the other script, so make sure that script is running correctly first, including the prerequisites.

Requirements

  • Home Assistant version 2022.2 is required because the iif filter/function introduced in that version is used in templates
  • The Google Home Resume script and all its prerequisites in case you want to resume what was playing afterwards.

Most recent change

Verstion 1.6.0 - 04 August 2022

:sparkles: New feature

  • Support for Music Assistant resume

Older changes can be found here

Prerequisites

  1. Expose scripts to Google Assistant (either use Nabu Casa, or the manual setup)
  2. A separate script per TTS messsage, which will be called from the Google Home
  3. A routine in the Google Home app which starts the script (you can find your scripts under Adjust Home DevicesAdjust scenes)
    The last action in your routine should be to start the ambient sound (Play and control mediaSleep sounds → Any sound you only use for this script
  4. Define the right variables for your home in the Google Home Voice script as desribed below

How to use start script

To use the script you will need to provide the action to be performed. Like the Google Home Resume script only service calls are working. In case no service calls are entered the script will stop (it will only stop the ambient sound, but not resume the previous stream).
There is no need to provide the target, it will be added by the Google Home Voice script, based on the ambient sound playing.
In case you need to change the volume (eg for TTS) you can use the volume variable.

Example
Let’s say you have the Waze and proximity integrations set up, and want to send out a TTS message with the ETA.

The script will then be something like this:

eta_thefes:
  alias: "ETA TheFes"
  icon: mdi:car
  sequence:
    - variables:
        message: >
          {% set eta = (as_timestamp(now()) + 60 * states ('sensor.thefes_home') | float(0) | timestamp_custom('%H:%M') %}
          If TheFes leaves now, he will be home at {{ eta }}.
    - alias: "TTS for speaker voice command"
      service: script.google_home_voice
      data:
        target_conversion:
          media_player.kitchen_hub: media_player.livinghome_group
        use_resume: true
        action:
          - alias: "Send TTS message"
            service: tts.google_cloud_say
            data:
              message: "{{ message }}"
        volume: 35

Variables in service call for the script:

Variable Required Description
action Yes The title of the ambient sound as shown in developer tools > states
target_conversion No A list dictonary with target replacements when you send the voice command
use_resume No Set to false in case you don’t want to use the Google Home Resume script, and just want to send the actions
target_variable No If set to true the entity_id of the Google Home will be added as the variable voice_target so it can be used in scripts, and added under extra so the Google Home Resume script will resume it.

And finally the script itself

Link to the script on my Github config, so I don have to maintain it in two places

Explanation of variables in the script

Variable Required Example Description
check_for_title Yes Witte Ruis The title of the ambient sound as shown in developer tools > states
use_resume No false Use use_resume: false if you don’t have the Google Home Resume script. Don’t set this setting when you do want to use it, but set it in the script call instead if you need it. Default is true.

Other scripts

For other related Google Home scripst, see my Github page

Buy me a coffee

If you like this script, please feel free to buy me a coffee (I might spend it on another beverage though).
In case you decide to do so, thanks a lot!

Buy Me A Coffee

3 Likes

Excellent stuff, something that’s bugged me forever. So, am I right in saying, these scripts, use the ‘trailing’ playing of ambient sounds for us uniquely identify the speaker in that state and therefore direct the TTS back to it?

Wow, using the ambient sound to check which speaker was talked to, is a great idea! Cumbersome to integrate but very interesting!

1 Like

Hi, just wanted to say this is a brilliant idea - specifically, passing the TTS to the right Google Home

Unfortunately I am have an issue with this. I’ve gone through the debug and the issue seems to be that I am not passing a tts_volume (I would like the TTS volume to be whatever the media_player. is set to).

This is the error I am getting, which is generated on this part of the code:

Stopped because an error was encountered at January 2, 2022, 15:08:20 (runtime: 0.04 seconds)
Error rendering data template: TypeError: ‘<’ not supported between instances of ‘str’ and ‘int’

alias: Apply TTS volume
service: media_player.volume_set
target:
  entity_id: '{{ tts_target_list }}'
data:
  volume_level: '{{ tts_volume if tts_volume < 1 else tts_volume / 100 }}'

According to the debug, the tts_volume is being set as:

tts_volume: ‘’

The media player volume is being picked as

volume_old_not_playing:
  - entity_id: media_player.living_room_speaker
    volume_level: 0.05
screen_not_playing: []

I think the TTS is set correctly as per the example. But looks like it is being taken as a string where it defaults to undefined?

    - alias: "TTS"
      service: script.google_home_say
      data:
        voice_tts_target: "{{ tts_target }}"
        tts_message: "{{ tts_message }}"
        tts_volume: "{{ tts_volume if tts_volume is defined else undefined }}"

Really out of my depth here - not sure whats causing the error nor how to fix it.
Thank you in advance.

Kudos for this idea. I have wanted to do that quite some time.
Does this also work with your new script, or do I need to use the one stated in the first post?

It also works, but then you need to change the google_home_say_voice as well.

Here is the updated version.

I will change the post accordingly somewhere in the near future.

I’ve update the first post so it explains how it works with the new script (and amended the script to work with other actions besides TTS)

1 Like

Update

Version 1.0.0 - 9 February 2022

:sparkles: New feature

  • Now the new script is used, other actions besides TTS are supported

:star2: Improvements

  • Added version number as a variable to the sequence. This will make it more easy to see which changes there are since you last updated the script
  • Several improvements in the templates
  • Update of the first post of this forum topic
1 Like

Update

Version 1.1.0 - 10 February 2022

:star2: Improvements

  • No need to define speaker_groups anymore, as I found a way to define them using a template.

Update

Version 1.2.0 - 13 February 2022

:red_circle: BREAKING

  • Made several changes in how data is sent from this script to the Google Home Resume script. So if you update this script, make sure to also update the other one. However, as of this version, it is also possible to use this script without the Google Home Resume script

:sparkles: New feature

  • It is now possible to use target_conversion. This means you can give your voice command, and perform your actions on another target eg the speaker group the target belongs to.
  • By setting the use_resume variable to false you can send the actions without using the Google Home Resume script. This can be used if you for example want to start a radio stream which is not in TuneIn, and do not want to resume other streams in case that one is stopped.
  • The target determined by the ambient sound will only be used in case you omit the target in your service call. If you provide it, that target will be used. This can be useful if you also want to provide other actions, for example setting the state of an input_boolean.
  • In case you don’t have the need to use the Google Home Script at all, you can set use_resume: false in the variables of the Google Home Voice script, and it will just send the actions.

:star2: Improvements

  • Information is shared with the Google Home Resume script in a better way. This was also needed because now multiple targets or groups as target are possible, where in the old version there was always only one target.
  • Information on for the ytube_music_player integration is now also shared.
1 Like

Sorry for all the updates :slight_smile:

Update

Version 1.2.1 - 14 February 2022 :heart_decoration:

:bug: Bug fixes

  • Fix for resuming ytube_music_player after voice command

UPDATE

Version 1.3.0 - 25 February 2022

:red_circle: BREAKING

  • Changes in the way data is shared with the Google Home Resume script. So if you update this script, make sure to also update the other one. However, as of this version, it is also possible to use this script without the Google Home Resume script

:star2: Improvements

  • The ytube music player integration will now resume at the right position in the track
1 Like

Update

Version 1.3.1 - 14 March 2022

:star2: Improvements

  • Do not store unnecessary data of non playing devices

:receipt: Documentation

  • Created seperate file for older changes

Older changes can be found here

Update

Version 1.3.2 - 21 March 2022

:star2: Improvements

  • No need to for the variable primary_spotcast anymore, this will be handled by the Google Home Resume script
  • Only data of playing Spotify entities will be stored (other non playing entities were already excluded in 1.3.1)

Update

Version 1.3.3/1.3.4 - 22 March 2022

:star2: Improvements

  • Added a update of Spotify entities before data is stored, so the most recent data is used
  • Only relevant data of entities is stored (depending on state and playing app)

:bug: Bug fixes

  • (1.3.4) Template fix

Update

Version 1.3.5 - 2 April 2022

:star2: Improvements

  • Ambient sound will now be stopped after the data from the media_player is stored

Update

Version 1.3.6 - 8 April 2022

:sparkles: New features

  • Support for extra variables in service calls added. This is a new feature of the Google Home Resume script. Version 2.0.0 or higher of the Google Home Resume script is required for this. For more information see here

Hello!
I’m really thankfull for your work, but I haven’t been able to modify all the settings of both script to make them work; seems that there are a lot of scripts inside, with radios and all, lots of diferrent entities that I don’t have, and I really don’t want that. All that I really wanted was to know the entity_id of the media_player that was used to call a script, is there any way to simplify this, without thinking in youtube / spotify or any other integration for that matter? I thisnk that would be very usefull, for a lot of people, on it’s own.

For instance, I have this list of media_players, and is possible to know the “last_changed”, but that doesn’t quite work as expected:

{% set colunas = ['media_player.coluna_da_sala', 'media_player.coluna_da_cozinha', 'media_player.coluna_da_cave'] %}

{{ expand(colunas) | sort(attribute='last_changed', reverse=true) | map(attribute='entity_id') | first }}

Is there something that I could do before just to get the correct media_player ?
Thanks in advance!

The script is intended to actually send an action to the right Google Home.
The Google Home Resume script is not required, you can use this script without the Google Home Resume script if you use: use_resume: false

I don’t know what you actually mean with your template example, because it doesn’t seem related to starting an action by voice on your Google Home, and knowing which one you asked it to in Home Assistant.

What your template does is determine which media_player was changed last, which of course could be because of the question asked, but also because someone changed the volume or whatever. So that might be the reason why it doesn’t work as expected.

1 Like

I know you are right, and I’m thankfull for your approach. I will try to make both scripts work, but mainly understand the sequence to send the white noise and get the media_player from there. That’s mainly what I want.
I managed to replicate the white noise and possibly get the player, but as it goes last in the sequence in Google Home app it has to wait for it to be identified, as I understand. Don’t know any better aproach, so I will try to addapt your scrits to my entities. Thanks again.