How to: Broadcast message in Google Home resuming what you were listening

Problem: You are listening to Spotify, radio or anything on a Google Nest (former Google Home) and openHAB broadcasts a notification. The stream you were listening to stops and doesn’t resume after the message.

With the Chromecast binding you can send a notification to a particular Google device or to an audiogroup. Audiogroups also have a problem: there is an “elected leader” that can change, so the IP for the audiogroup changes (see Chromecast audiogroup has an "elected leader" and it keeps changing). But if there’s something playing it will stop. With the Google Assistant SDK broadcast, if there’s something playing, it will resume after the notification.

The goal is to be able to send a broadcast notification to all the Google Homes, and if there was something playing on any of them, resume it. With this tutorial you will be able to solve the audiogroup elected leader problem (thanks, @Mohammad_Chaaban) and the “stream not resuming” problem.

As a prerequisite you will need to have assigned fixed IP addresses to all your Google Homes (you will probably have done that previously, as I believe you need it to add the Chromecast audio things). Also you will need the Google TTS and Chromecast bindings. And for Home Assistant you will also need Docker and Docker Compose installed.

Make an audiogroup in the Google Home app. To find out the port of the audiogroup you will have to wait for it to be discovered by OH (or trigger a scan) and add it from MainUI. Then add the thing, click it, and click on “Show advanced”. Write down the network port.

You will need one audiogroup thing per Google Home device you have. You can keep the one you just added if you’re going the GUI way. I have everything in files, so I deleted it first:

chromecast:audiogroup:GoogleHomeAudiogroup1 "Audiogroup1" [ ipAddress="<IP OF THE FIRST GOOGLE HOME", port=<PORT YOU JUST WROTE DOWN> ]
chromecast:audiogroup:GoogleHomeAudiogroup2 "Audiogroup2" [ ipAddress="<IP OF THE SECOND GOOGLE HOME", port=<PORT YOU JUST WROTE DOWN> ]
...

You will also need a Player item for every Google Home you have. And have a “Say” item where to send the text to be spoken:

Player GoogleHome1Player { channel="chromecast:audio:GoogleHome1:control" }
Player GoogleHome2Player { channel="chromecast:audio:GoogleHome2:control" }
...

String Say

To solve the “not resuming” problem, while this issue (Integrate with Local Home SDK · Issue #102 · openhab/openhab-google-assistant · GitHub) is not implemented, we’ll use Home Assistant’s implementation (Google Assistant SDK - Home Assistant), so first you will need to install HA. With docker compose it’s very easy, you just have to create a folder (I chose /opt/ha) and a compose.yml file with this content:

version: '3'
services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - /opt/ha:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    privileged: true
    network_mode: host
    user: 1000:1000

Then run the command docker compose up -d
Connect to http://<YOUR IP>:8123 , create a user, and fill the info you want.
Click on your user on the down left corner, and in “Long-Lived Access Tokens” create one: give it a name and write it down.

Then follow this tutorial step by step to add the Google Assistant SDK integration to Home Assistant and configure it. As you already had Google TTS in OH, some of the steps were already done: Google Assistant SDK - Home Assistant

In HA, click on Settings/Devices & Services/Devices/Add device. Create one of the type “Input text (helper)”. Name it “command”.
Click on Settings/Automations & Scenes/Create automation/Create new automation. Then click on the three dots on the upper right corner and choose “Edit in YAML”. Paste this code:

alias: Google Assistant command
description: ""
trigger:
  - platform: state
    entity_id:
      - input_text.command
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: input_text.command
        state: unknown
action:
  - service: google_assistant_sdk.send_text_command
    data:
      command: "{{ states('input_text.command') }}"
  - service: input_text.set_value
    data:
      value: unknown
    target:
      entity_id: input_text.command
    enabled: true
mode: single

(I don’t know if in HA rules is there a “command received” equivalent, sorry)

Now, back in openHAB, create this rule:

rule "Say"
when 
    Item Say received command
then
    var String txt=receivedCommand.toString()
    var String audiogroup=""

    if (getThingStatusInfo("chromecast:audiogroup:GoogleHomeAudiogroup1").getStatus().toString() == 
        "ONLINE")
        audiogroup="GoogleHomeAudiogroup1"
    else if (getThingStatusInfo("chromecast:audiogroup:GoogleHomeAudiogroup2").getStatus().toString() == 
        "ONLINE")
        audiogroup="GoogleHomeAudiogroup2"

    if (GoogleHome1Player.state!=PLAY && GoogleHome2Player.state!=PLAY && 
        audiogroup!="")
        say(txt,"googletts:<YOUR GOOGLE TTS VOICE>","chromecast:audiogroup:"+audiogroup)
    else
        sendHttpPostRequest("http://<YOUR HA IP ADDRESS>:8123/api/states/input_text.command", 
            "application/json", 
            '{"state": "Broadcast: '+txt+'"}',
            newHashMap("Authorization" -> "Bearer <THE HA API TOKEN YOU WROTE DOWN>"),
            1000
        )
end

What the rule does is check which is the online audiogroup and if there is one and none is playing anything, send the broadcast to that one. Else, broadcast via Google Assistant SDK.
Why not skip the audiogroups part entirely and always use the broadcast? Because when you do this, the Google Homes say “Incoming message” before the text you send them. This way you only have to hear this if there was something playing. With the broadcast, it will resume playing.

The Google Assistant SDK can be used to send other commands, not only broadcast. For example, you can control devices than aren’t still supported by openHAB. There are limitations, thoug: GitHub - tronikos/gassist_text: A Python library for interacting with Google Assistant API via text

Hope you like it.