A while back, Google removed groups. I had more or less quit using them due to their instability in the firstplace, and thought they had been automatically removed.
However, when I installed the app, they were discovered on the initial run. This reminded me that they were even there. Since they were not being used, I went into the Home app and removed the groups.
However, they STILL show in the discovery section of the app. Is there any way we can clean that list up? (Refresh devices doesn't do it either)
Current Device Listing - These groups do not actually exist anymore
I didn't know anything about these groups but did a little searching and it sounds like they might be getting cached somewhere on a device or router
If a deleted group still appears, it is a "ghost group" caused by your router or physical speakers caching old network configurations. The Google Home app may have deleted the group on its servers, but your local network hardware is still broadcasting the old data.
The fix was to basically reboot everything but 1 other thing which is easy enough to try is Hey Google, sync my devices(assuming it's a voice assistant device)
We have actually had several power outages since then (Two tornados within 5 miles and one severe straight line wind storm that did more damage than the tornados - Gotta love Maryland weather). Although I run a battery backup, I shut everything down when the outage is longer than an hour. Two of the three outages were > 4 hours. So, not only a shut down, but a rather cold start after being down for 3ish hours on two occaisons.
That's how I understand it - although I've never tested it. Just in case I can't reproduce, send me hubitat logs (enable debug logging in the app) since they usually reveal useful info too.
I'll make a note to try it myself though when I get time
I ran the logs through AI and got a valid? issue which it fixed.. but the last line doesn't seem overly optimistic either.. I did push the update though to HPM - 1.0.9
What the logs show
The restore ran, it just restored the wrong thing:
- 00:03:30.303 — LAUNCH CC1AD845 (DMR) — launching it evicts Spotify (00:03:30.861 peer CLOSE from c3a4f4e0…, Spotify's transport)
- 00:03:30.732 — TTS: begin → the restore snapshot is taken here, after the launch
- 00:03:33.135 — restore LOAD of "spotify:track:2noGBukdFPCt7m5ZXnDKor" → 00:03:33.304 LOAD_FAILED
- 00:03:36.154 — SEEK with mediaSessionId:2 → INVALID_MEDIA_SESSION_ID (that session was the finished announcement)
...
The part that won't be fixed by this
Spotify still won't start playing again, and no Cast sender can make it. Launching the DMR for the announcement destroys the Spotify
session, and its contentId is an app-private handle — there's no protocol path back. What the driver does now is the honest best
effort: relaunch the app so it's back on screen and the phone/Spotify Connect can re-attach, with a clear log line saying playback
won't restart on its own. (Google's own broadcasts duck-and-resume through a privileged firmware path that isn't in the Cast
protocol.) True resume works only for content this driver cast itself — an http URL through the DMR — and that path is now correct,
including the seek position.
Broadcast is something the driver defined and will call speak() on all of the child devices
the other methods (play, speak, annouce, etc) that you see in the driver are automatically added because of the capabilities the driver lists. For example, SpeechSynthesis gives the play() method in the driver.
I asked Claude and copied the full answer below. Not much difference between speak and playText IMO but there is a slight difference:
All three funnel into the same TTS pipeline — `announce()` at `google-chromecast-plus-driver.groovy:254`. What differs is **which device you call** and **what happens after the speech ends** (the `mode` argument).
## Speak vs. Play Text — the `mode` argument
Both are on the child device; the only difference is cleanup:
| Command | mode | Volume default |
| ----------------------------- | ----------- | ---------------- |
| `speak` (`:205-207`) | `"restore"` | `ttsVolume` pref |
| `playText` (`:213-214`) | `"none"` | `ttsVolume` pref |
| `playTextAndRestore` (`:215`) | `"restore"` | arg only |
| `playTextAndResume` (`:216`) | `"resume"` | arg only |
What the modes do in `finishTts()` (`:429-470`):
- **`"none"`** — fire and forget. The volume the announcement set stays where it is, and whatever was playing before is *not* brought back. If `stopAfterTts` is on, this is the path that tears the session down so a Nest Hub drops back to its photo frame.
- **`"restore"`** — puts the pre-announcement volume back (only if the announcement actually changed it — a no-op `SET_VOLUME` makes the device chirp), and reloads the previously cast content **from the beginning**.
- **`"resume"`** — identical, except the reload carries the saved position so playback picks up where it left off.
Caveat on restore/resume: it can only truly resume content *this driver* cast (`appId == APP_DMR` and an http(s) `contentId`). For a third-party app like Spotify, it can only relaunch the app best-effort — playback won't restart on its own (`:456-460`).
So `speak(text)` ≡ `playTextAndRestore(text)`, just with `ttsVolume` applied as the default. `deviceNotification` (`:212`) is also an alias for `speak`.
## Broadcast — a different device entirely
`broadcast` (`google-chromecast-plus-parent-driver.groovy:116`) is a custom command on the **parent** device, not the children. It loops over `getChildDevices()` and calls each child's `speak(...)`, so every Chromecast announces at once, each with its own volume/lead-in settings and its own `"restore"` cleanup.
The parent also implements `speak()` as an alias for `broadcast` (`:111-113`), which is the point: you can pick the parent as a single Speak/Notification target in a rule and get "speak to all" without enumerating devices. The extra `broadcast` command exists only to expose an explicit volume argument, since the bare capability command is `speak(text)`.