Chromecast audiogroup has an "elected leader" and it keeps changing

A chromecast audiogroup Thing gets pointed to an ip address of one of the group members, which is the “elected leader” for that audiogroup. However, it seems that this elected leader keeps changing from one member to another. So when it changed, my audiogroup Thing stopped working.

This behaviour has also been observed by the home-assistant people here

Their solution seems to involve using the “unique_id” being provided by the device https://github.com/home-assistant/home-assistant/pull/12474

Furthermore, I’m not sure if this is related as well https://github.com/balloob/pychromecast/pull/167

2 Likes

I opened an issue #5564 for this problem

1 Like

I think this problem still exists as of 2.5.

My current solution is as follows:

  • I created multiple audiogroup things, one for each member of the audiogroup
  • I created rules to keep track of which one is online, then update a virtual item to save the name of the active one
  • Use that virtual item in say/play
Thing chromecast:audiogroup:gh_all_1 "All Google Home 1" [ ipAddress="192.168.1.1", port=42351 ]
Thing chromecast:audiogroup:gh_all_2 "All Google Home 2" [ ipAddress="192.168.1.2", port=42351 ]
Thing chromecast:audiogroup:gh_all_3 "All Google Home 3" [ ipAddress="192.168.1.3", port=42351 ]
Thing chromecast:audiogroup:gh_all_4 "All Google Home 4" [ ipAddress="192.168.1.4", port=42351 ]

from core.rules import rule
from core.triggers import when
from core.actions import Things

@rule("Track Online Audiogroup", "Keep track of which audiogroup is online")
@when("Thing chromecast:audiogroup:gh_all_1 changed")
@when("Thing chromecast:audiogroup:gh_all_2 changed")
@when("Thing chromecast:audiogroup:gh_all_3 changed")
@when("Thing chromecast:audiogroup:gh_all_4 changed")
@when("System started")
@when("Time cron 0 */5 * * * ?")
def init_audiogroup(event):
    # find the current active audiogroup
    audiogroup = ''
    for i in range(4): 
        chromecast_uid = "chromecast:audiogroup:gh_all_{}".format(i+1)
        if Things.getThingStatusInfo(chromecast_uid).toString() == "ONLINE":
            audiogroup = chromecast_uid
            break

    if audiogroup != items.Chromecast_Audiogroup.toString():
        init_audiogroup.log.info("Audiogroup ONLINE: {}".format(audiogroup))
        postUpdate("Chromecast_Audiogroup", audiogroup)

In rules that need to broadcast to audiogroup:

        Audio.playSound(items.Chromecast_Audiogroup.toString(), "defaultdoorbell.mp3")

@cweitkamp, my suggestion would be to allow the audiogroup thing to specify multiple ip addresses, and the binding can automatically pick whichever one that’s online. What do you think?

e.g.:

Thing chromecast:audiogroup:gh_all "All Google Home" [ ipAddress1="192.168.1.1", ipAddress2="192.168.1.2", ipAddress3="192.168.1.3", ipAddress4="192.168.1.4", port=42351 ]

1 Like

Hi Jim,

Thanks for catching up with this topic. Just want to let you know that I saw your message. I recently added another Google Home device to my setup and will create a group for testing as soon as I find some time for it.

I like your proposal to add a list of potential IPs for the groups. But not as configuration parameters rather introduce meta tags for them. Maybe it is possible to populate the list automatically to simplify the users life.

Keep you posted.

2 Likes

Any news for the behavior and solution?

hi Jim, i created new rule file “chrome.rules”, its giving me below error when i save the rule file:

2020-02-26 08:53:41.661 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'chrome.rules' is either empty or cannot be parsed correctly!

can u help with this… i have two google mini’s, so its two groups only, below is the rule code:

from core.rules import rule
from core.triggers import when
from core.actions import Things

@rule("Track Online Audiogroup", "Keep track of which audiogroup is online")
@when("Thing chromecast:audiogroup:gh_all_1 changed")
@when("Thing chromecast:audiogroup:gh_all_2 changed")
@when("System started")
@when("Time cron 0 */5 * * * ?")
def init_audiogroup(event):
    # find the current active audiogroup
    audiogroup = ''
    for i in range(2): 
        chromecast_uid = "chromecast:audiogroup:gh_all_{}".format(i+1)
        if Things.getThingStatusInfo(chromecast_uid).toString() == "ONLINE":
            audiogroup = chromecast_uid
            break

    if audiogroup != items.Chromecast_Audiogroup.toString():
        init_audiogroup.log.info("Audiogroup ONLINE: {}".format(audiogroup))
        postUpdate("Chromecast_Audiogroup", audiogroup)

My rule is in Jython, not RulesDSL. You’ll either need to translate it into RulesDSL or use Jython instead. See https://openhab-scripters.github.io/openhab-helper-libraries/Getting%20Started/Installation.html

There is a chance to solve the problem. I use the groups to carry out alarms (doorbell, X Y calls on the cell phone, open windows …) throughout the house. But this only works sporadically at the moment. I would also be available as a tester, I have 10 Google Home, a Chromecast and an Android TV in my network.

Hi all,

Sry for coming back to you with such a delay. During my recent work on the binding I tried to figure out a solution for this problem. I did not find a solution yet but I found a workaround. In the beginning I added all my audiogroups via textual configuration file. And after a short time I experienced the same issue. I setup a separate test environment and again added all my audiogroups but this time using the auto discovery feature of the binding. And this time it was working nicely. The discovery automatically changes the IP address of my audiogroups. That is one of the supported discovery features. On the opposite the discovery is - of course - not allowed to change configuration of manually defined things.

Thanks for the tip, @cweitkamp. Is it possible to rename the thing id of the discovered audiogroup? I’d like to call it something like chromecast:audiogroup:all_speakers instead of chromecast:audiogroup:dd9d8644-c6e2-4edf-b336-51b992c4d844?

For auto discovered things it is not possible to change the thing id. What I did not test is adding the thing manually via Paper UI. I am not sure if the same discovery feature is applied for them. But then you have the change to rename the thing id.

I know that it is easier for humans to have a meaningful thing id but the framework does not care. Rule and Item files can be change by find & replaced in a second.

Unfortunately the autodiscovered audiogroup isn’t working reliably for me.

I’ve just tried adding the autodiscovered audiogroup thing. At first, it was online, and all was good. Then I tried removing it, then re-discovered it and re-added it as a thing. I did this a few times. Then eventually I stumbled on a problem. The autodiscovered audiogroup, once added as a thing, is OFFLINE. Its ip address is pointing to the offline member indeed.

I have 4 google home devices that are all members of the “All Speakers” audiogroup: 192.168.1.200, .203, .208 and .165. The one that seems to be elected most of the time is the .208.

However, the discovered audiogroup when added as a thing, kept having the ip address of .200 and hence it is OFFLINE. I tried deleting this autodiscovered thing and re-adding, and it now kept reverting to that .200 and therefore stays OFFLINE. I have not changed its ip address manually.

facing this issue in Jan 2021 :frowning: I auto discovered the audio group using OH3 UI and the IP address and port did change after a few days:


I encountered the same problem, on OH3.

I have been observing this problem with OH 2.x for quite some time. I assign a fixed IP address for my Chromecasts and the port for the audio group changes from time to time. It is not understandable for me.
Apps like BubbleUPnP, Audials or PowerAmp have no problem to work with the changed port of the Chromecast audio group. This is a very very annoying thing …

1 Like

It’s always been like that, I’ve been using Chromcast for 3 years and I’m annoyed about it. Unfortunately in OH there is no way to enter all IP addresses of the group. While looking for an old discussion on the topic, I just discovered this discussion
https://community.openhab.org/t/solved-oh2-chromecast-binding-audio-output-on-multiple-google-home-mini-at-the-same-time/36737
and will test it right away.

Okay, that doesn’t help either, there is also overlooked that the IP changes after a day or two.

Easy guys… make a simple rule to track which channel is online and this will be the group ip address… i did this long time and its working perfectly… im abt to sleep now… ill post the rule tomorrow

Can you please post your rule?

Thanks!

1 Like

hi guys, below example for two google mini, u can add as much as u want… please set fixed ip for the google mini’s from the router… google it… fixed ip per mac address

things

Thing chromecast:chromecast:Ghome_LR      "Google home Livingroom"     [ ipAddress="192.168.0.20", port=8009]
Thing chromecast:chromecast:Ghome_BR      "Google home Bedroom"        [ ipAddress="192.168.0.21", port=8009]
Thing chromecast:audiogroup:Ghome_Group1  "Audio group 1"              [ ipAddress="192.168.0.20", port=42648]
Thing chromecast:audiogroup:Ghome_Group2  "Audio group 2"              [ ipAddress="192.168.0.21", port=42648]

Items

Player	 ChromecastAudioControl_LR 				"Google mini livingroom Control"																								   {channel="chromecast:chromecast:Ghome_LR:control"}
Dimmer   ChromecastVolume_LR       				"Livingroom Volume [%d %%]"																							   			   {channel="chromecast:chromecast:Ghome_LR:volume"}

Player	 ChromecastAudioControl_BR 				"Google mini Bedroom Control"																									   {channel="chromecast:chromecast:Ghome_BR:control"}
Dimmer   ChromecastVolume_BR       				"Bedroom Volume [%d %%]"																							   			   {channel="chromecast:chromecast:Ghome_BR:volume"}

Player	 ChromecastAudioControl_Group1			"Google mini group Control"																										   {channel="chromecast:audiogroup:Ghome_Group1:control"}
Dimmer   ChromecastVolume_Group1   				"Google mini group Volume [%d %%]"																								   {channel="chromecast:audiogroup:Ghome_Group1:volume"}

Player	 ChromecastAudioControl_Group2			"Google mini group Control"																										   {channel="chromecast:audiogroup:Ghome_Group2:control"}
Dimmer   ChromecastVolume_Group2    			"Google mini group Volume [%d %%]"																								   {channel="chromecast:audiogroup:Ghome_Group2:volume"}

Number   music_track                            "Track [%d]"								   <player>
Number   music_control                          "Music control [%d]"						   <player>
String   audio_sink                             "Speaker [%s]"								   <player>
String   audio_sink_v                           "Speaker [%s]"								   <player>
Dimmer   ChromecastVolume_Group_v    			"Group Volume [%d %%]"

rule

rule "check things online"
when
	Thing "chromecast:audiogroup:Ghome_Group1" changed or
	Thing "chromecast:audiogroup:Ghome_Group2" changed
then
	var Ghome_Group1_status = getThingStatusInfo("chromecast:audiogroup:Ghome_Group1").getStatus()
	var Ghome_Group2_status = getThingStatusInfo("chromecast:audiogroup:Ghome_Group2").getStatus()
	if (audio_sink_v.state == "Ghome_G1") {
		if(Ghome_Group1_status.toString() == 'ONLINE') audio_sink.postUpdate("chromecast:audiogroup:Ghome_Group1")
		else if(Ghome_Group2_status.toString() == 'ONLINE') audio_sink.postUpdate("chromecast:audiogroup:Ghome_Group2")
	}
end

rule "Select Active audio group"
when
	Item audio_sink_v received command
then
	var Ghome_Group1_status = getThingStatusInfo("chromecast:audiogroup:Ghome_Group1").getStatus()
	var Ghome_Group2_status = getThingStatusInfo("chromecast:audiogroup:Ghome_Group2").getStatus()
	switch(receivedCommand) {
        case "Ghome_LR"  			: {
										audio_sink.postUpdate("chromecast:chromecast:Ghome_LR")
										audiocontrol=ChromecastAudioControl_LR
									  }
		case "Ghome_BR"  			: {
										audio_sink.postUpdate("chromecast:chromecast:Ghome_BR")
										audiocontrol=ChromecastAudioControl_BR
									  }
		case "Ghome_G1"  			: if(Ghome_Group1_status.toString() == 'ONLINE') {
										audio_sink.postUpdate("chromecast:audiogroup:Ghome_Group1")
										audiocontrol=ChromecastAudioControl_Group1
									  }
									  else if(Ghome_Group2_status.toString() == 'ONLINE') {
										audio_sink.postUpdate("chromecast:audiogroup:Ghome_Group2")
										audiocontrol=ChromecastAudioControl_Group2
									  }
	}	
end

rule "google home group volume"
when
	Item ChromecastVolume_Group_v received command
then
	if (audio_sink.state == "chromecast:audiogroup:Ghome_Group1") ChromecastVolume_Group1.sendCommand(ChromecastVolume_Group_v.state.toString)
	else if (audio_sink.state == "chromecast:audiogroup:Ghome_Group2") ChromecastVolume_Group2.sendCommand(ChromecastVolume_Group_v.state.toString)	
end

rule "music control"
when
    Item music_control received command
then
    switch(receivedCommand) {
        case 0  : playStream(audio_sink.state.toString, null)
		case 1  : sendCommand(audiocontrol, PAUSE)
		case 2  : sendCommand(audiocontrol, PLAY) 
    }
	music_control.postUpdate(3)
end

rule "Select music track"
when
    Item music_track received command
then
    switch(receivedCommand) {	  
        case 3  : playStream(audio_sink.state.toString, "http://192.168.0.10:8080/static/media/slow_music.mp3")
        case 4  : playStream(audio_sink.state.toString, "http://192.168.0.10:8080/static/media/movie.mp3")
    }
end

sitemap

Text label="Multimedia" icon="player" {
			Switch item=music_control label="Music control []" mappings=[
				0="Off",
				1="Pause",
				2="Play"
			]
			Selection item=audio_sink_v  mappings=[
				"Ghome_LR"="Livingroom speaker",
				"Ghome_BR"="Bedroom speaker",
				"Ghome_G1"="Group speakers"
			]
			Selection item=music_track label="Track selection" mappings=[
				3="Slow music",
				4="Movie"
			]
			Frame {
				Slider    item=ChromecastVolume_LR icon=soundvolume
				Slider    item=ChromecastVolume_BR icon=soundvolume
				Slider    item=ChromecastVolume_Group_v icon=soundvolume
			}
		}
1 Like