I’m building a rule which groups two sonos devices as long as one (the sonos Roam) is on its charger. Unfortunately, this approach works in most but not all scenarios.
It appears that the rule falls down because ‘state’ Items (e.g. channel="sonos:Roam:roam:state"
) seem to be reported inconsistently - i.e. a speaker may report a state of “PLAYING” when it in fact is not playing anything (or “STOPPED” but is in reality playing etc.).
This appears to happen whenever localcoordinator speakers are ungrouped:
Scenario A - Removal of a grouped speaker which is not localcoordinator:
- Start music on
Speaker A
- Add
Speaker B
toSpeaker A
group (Speaker A
islocalcoordinator
)- Remove
Speaker B
from the group- Speaker A continues playing and Speaker B stops
a_sonos_state
reports “PLAYING”,b_sonos_state
reports “STOPPED”
Scenario B - Removal of localcoordinator from the group:
- Start music on
Speaker A
- Add
Speaker B
toSpeaker A
group (Speaker A
islocalcoordinator
)- Remove
Speaker A
from the group- Speaker A stops and Speaker B continues playing
a_sonos_state
reports “STOPPED”,b_sonos_state
reports “STOPPED”
Scenario A exhibits the expected behaviour: state
items are accurate to what’s playing.
In Scenario B, music continues to play on Speaker B
(intended behaviour) while it is reported as “STOPPED”.
I can confirm that this issue persists no matter where the command originates (openHAB rule, sonos app, Alexa command or physical buttons). It also affects the control
channel, as can be seen here:
In reality, this speaker is playing music but shows as “PAUSE” and “STOPPED”
I’ve scoured the forums for clues, including @buschif4’s excellent Multiroom Rule but I’ve not seen other reports of this. Hoping someone else has experienced this problem and found a reason/solution.
In the meantime, here are my things, items and rules in case it sheds any light:
sonos.things
Thing sonos:One:kitchen "Sonos Kitchen" @ "Kitchen" [ udn="RINCON_7828CAF3E95801400"]
Thing sonos:Roam:roam "Sonos Roam" @ "Roam" [ udn="RINCON_542A1B41B73801400"]
sonos.items
Group gSonosStates "Sonos States"
Group gSonosID "Sonos ID Group"
Group gSonosRemove "Sonos REMOVE Group"
Group gSonosAdd "Sonos ADD Group"
Group gSonosVol "Sonos Volume Group"
Group gSonos "Sonos"
//////////KITCHEN//////////
Group gSonosK
String k_sonos_zonename "ID" (gSonos, gSonosK) {channel="sonos:One:kitchen:zonename"}
Player k_sonos_control "Control [%s]" (gSonos, gsonosK) {channel="sonos:One:kitchen:control"}
Dimmer k_sonos_vol "Volume" (gSonos, gsonosK, gSonosVol) {channel="sonos:One:kitchen:volume"}
String k_sonos_add "Add [%s]" (gSonos, gsonosK, gSonosAdd) {channel="sonos:One:kitchen:add"}
String k_sonos_remove "Remove [%s]" (gSonos, gsonosK, gSonosRemove) {channel="sonos:One:kitchen:remove"}
String k_sonos_state "State" (gSonos, gsonosK, gSonosStates) {channel="sonos:One:kitchen:state"}
Switch k_sonos_master "Master" (gSonos, gsonosK, gSonosMaster) {channel="sonos:One:kitchen:localcoordinator"}
String k_sonos_groupid "Group ID" (gSonos, gsonosK, gSonosID) {channel="sonos:One:kitchen:zonegroupid"}
//////////ROAM//////////
Group gSonosR
String r_sonos_zonename "ID" (gSonos, gSonosR) {channel="sonos:Roam:roam:zonename"}
Player r_sonos_control "Control [%s]" (gSonos, gSonosR) {channel="sonos:Roam:roam:control"}
Dimmer r_sonos_vol "Volume" (gSonos, gSonosR, gSonosVol) {channel="sonos:Roam:roam:volume"}
String r_sonos_add "Add [%s]" (gSonos, gSonosR, gSonosAdd) {channel="sonos:Roam:roam:add"}
String r_sonos_remove "Remove [%s]" (gSonos, gSonosR, gSonosRemove) {channel="sonos:Roam:roam:remove"}
String r_sonos_state "State" (gSonos, gSonosR, gSonosStates) {channel="sonos:Roam:roam:state"}
Switch r_sonos_master "Master" (gSonos, gSonosR, gSonosMaster) {channel="sonos:Roam:roam:localcoordinator"}
String r_sonos_groupid "Group ID" (gSonos, gSonosR, gSonosID) {channel="sonos:Roam:roam:zonegroupid"}
Switch r_sonos_charging "Charging" (gSonos, gSonosR) {channel="sonos:Roam:roam:batterycharging"}
sonos.rules
rule "SONOS ROAM Sync 1"
when
Item r_sonos_state changed to PLAYING
then
if (r_sonos_groupid.state != k_sonos_groupid.state && r_sonos_charging.state == ON) {
Thread::sleep(500)
if (r_sonos_master.state == OFF) {
gSonosID.members.forEach[ i |
var vRoom = transform("JSONPATH", "$.slots[0].value.value", i.name.toString.split('_').get(0))
if ( i.state == r_sonos_groupid.state
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_zonename").state != "Sonos Roam"
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_zonename").state != "Kitchen"
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_master").state == ON )
org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_add").sendCommand("kitchen")
] }
else if (r_sonos_master.state == ON)
r_sonos_add.sendCommand("kitchen")
k_sonos_vol.sendCommand(r_sonos_vol.state)
}
end
rule "SONOS ROAM Sync 2"
when
Item k_sonos_state changed to PLAYING
then
if (r_sonos_groupid.state != k_sonos_groupid.state && r_sonos_charging.state == ON) {
Thread::sleep(500)
if (k_sonos_master.state == OFF) {
gSonosID.members.forEach[ i |
var vRoom = transform("JSONPATH", "$.slots[0].value.value", i.name.toString.split('_').get(0))
if ( i.state == k_sonos_groupid.state
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_zonename").state != "Sonos Roam"
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_zonename").state != "Kitchen"
&& org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_master").state == ON )
org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(vRoom + "_sonos_add").sendCommand("roam")
] }
else if (k_sonos_master.state == ON)
k_sonos_add.sendCommand("roam")
r_sonos_vol.sendCommand(k_sonos_vol.state)
}
end