after there is no nice and smooth way to control my raumfelds, i started with a rule - and it grows - but i will post it, maybe it helps someone
p.s. bugs are made to find them
setup:
- raumserver at
http://192.168.1.205:8080
- 4 RFs named
AUD_K
,AUD_B
, … - HABPanel
- OpenHAB 2.3
scope:
- activate/deactivate RFs in seperate zones or multiroom with less clicks
- set a fav-internetstations
- change volume
what you get:
- click on station, click on the first RF and the RF will play the station (1)
- click on the next RF and the RF will play also the same station (multiroom) (2)
- click on an other station and click on the 3rd RF, this RF will play the new station (2+1)
- doubleclick on station, all RFs will play them same station (3)
section::declaration
var Integer nPHYS_DEVICES = 4 // number of physical devices
var deviceName = newArrayList()
var guiVolumeItem = newArrayList()
var guiActiveItem = newArrayList()
var guiStateItem = newArrayList()
var Integer AUD_K_Index = 0 // change this section
var Integer AUD_WZ_Index = 1
var Integer AUD_B_Index = 2
var Integer AUD_WC_Index = 3
var Boolean debug = false
var Boolean deviceStateOK = false
var Integer volumeStep = 2
var deviceState = newArrayList('','','','')
var String delimiter = ";"
var String actionDelimiter = "#"
var String errorString = "failed"
var String actionQueueON = "speakerON"
var String actionQueueOFF = "speakerOFF"
var String actionZone = "zoneMod"
var getRequest = newArrayList('','','','')
var rsURL = "http://192.168.1.205:8080/raumserver/controller/" // put in your raumserver-url
var Integer changeDelay = 1000
var Integer noChangeDelay = 1001
var Integer requestDelay
var Integer timeOut = 15000
var Timer requestTimer
var String safe_GLOBAL_INT_stationURI = ""
section::init
rule "GM_init"
when
System started
then
postUpdate (GLOBAL_AUD_runningCycle, 0) // number
logInfo ("AUD","init::started ...")
postUpdate (GLOBAL_INT_updateRF, OFF) // switch
Thread::sleep (5000)
postUpdate (GLOBAL_AUD_actionQueue, "") // string
safe_GLOBAL_INT_stationURI = GLOBAL_INT_stationURI.state.toString
guiVolumeItem.add (K_INT_speakerVolume) // number
guiActiveItem.add (K_INT_speakerActive) // switch
guiStateItem.add (K_INT_speakerState) // string
deviceName.add ("AUD_K") // rename it as your RFs
guiVolumeItem.add (WZ_INT_speakerVolume)
guiActiveItem.add (WZ_INT_speakerActive)
guiStateItem.add (WZ_INT_speakerState)
deviceName.add ("AUD_WZ")
guiVolumeItem.add (BAD_INT_speakerVolume)
guiActiveItem.add (BAD_INT_speakerActive)
guiStateItem.add (BAD_INT_speakerState)
deviceName.add ("AUD_B")
guiVolumeItem.add (WC_INT_speakerVolume)
guiActiveItem.add (WC_INT_speakerActive)
guiStateItem.add (WC_INT_speakerState)
deviceName.add ("AUD_WC")
Thread::sleep (changeDelay)
postUpdate(GLOBAL_INT_updateRF, ON)
logInfo ("AUD","init::done")
section::getDeviceState
rule "GM_getDeviceStates"
when
Item GLOBAL_INT_updateRF changed to ON
then
while (GLOBAL_INT_updateRF.state == ON)
{
postUpdate (GLOBAL_AUD_runningCycle, (GLOBAL_AUD_runningCycle.state as DecimalType) + 1)
val tempDeviceState = newArrayList()
var tempSortedDeviceState = newArrayList()
var String zoneConfigRequest = sendHttpGetRequest(rsURL + "getZoneConfig")
if ((zoneConfigRequest !== null) && (transform ("JSONPATH","$.error", zoneConfigRequest) == "false") && (zoneConfigRequest.contains ('name')))
{
var Integer nRooms = Integer::parseInt(transform("JSONPATH","$.data.zoneConfig.$.numRooms", zoneConfigRequest).toString)
if (zoneConfigRequest.contains ("zones"))
{
var Integer nActiveZones = Integer::parseInt(transform("JSONPATH","$.data.zoneConfig.zones[0].zone.length()", zoneConfigRequest).toString)
var iZone = -1
while ((iZone=iZone+1) < nActiveZones)
{
var Integer nRoomsInZone = Integer::parseInt(transform("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].room.length()", zoneConfigRequest).toString)
var String zone = transform("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].$.udn", zoneConfigRequest)
var iRoom = -1
while ((iRoom=iRoom+1) < nRoomsInZone)
{
var String roomName = transform("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].room[" + iRoom.toString + "].$.name",zoneConfigRequest).toString
var String roomUDN = transform("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].room[" + iRoom.toString + "].$.udn",zoneConfigRequest).toString
var String powerState = transform ("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].room[" + iRoom.toString + "].$.powerState", zoneConfigRequest)
var deviceIndex = -1
while (((deviceIndex=deviceIndex+1) < nPHYS_DEVICES) && (roomName != deviceName.get(deviceIndex).toString)) {}
var Integer roomsInState = Integer::parseInt(transform ("JSONPATH","$.data.zoneConfig.zones[0].zone[" + iZone.toString + "].room.length()", zoneConfigRequest).toString)
var String rendererStateRequest = null
if (!powerState.contains ("AUTOMATIC_STANDBY") && !powerState.contains ("MANUAL_STANDBY"))
{
rendererStateRequest = sendHttpGetRequest(rsURL + "getRendererState?id=" + roomName)
} else {
tempDeviceState.add (deviceIndex.toString + delimiter + roomName + delimiter + powerState + delimiter + "null" + delimiter + "STOPPED" + delimiter + "null" + delimiter + "null" + delimiter + "1")
}
if ((rendererStateRequest !== null) && (transform ("JSONPATH", "$.error", rendererStateRequest) == "false") && (rendererStateRequest.contains ('name') && (rendererStateRequest.contains('RoomVolumes'))))
{
var thisRoom = -1
while (((thisRoom=thisRoom+1) < roomsInState) && (transform ("JSONPATH","$.data[0].rooms["+thisRoom.toString+"].name", rendererStateRequest).toString.contains(deviceName.get(deviceIndex).toString) == false)) {}
var String transportState = transform ("JSONPATH","$.data[0].TransportState", rendererStateRequest)
var String currentTrackURI = transform ("JSONPATH","$.data[0].CurrentTrackURI", rendererStateRequest)
var String volumeState = transform ("JSONPATH","$.data[0].RoomVolumes", rendererStateRequest).toString
var String roomVolume
if (volumeState.contains (roomUDN))
{
val roomVolumes = volumeState.split(",")
var iVolume = -1
while (((iVolume=iVolume+1) < roomVolumes.length) && (!roomVolumes.get(iVolume).toString.contains(roomUDN))) {}
roomVolume = roomVolumes.get(iVolume).toString.replace(roomUDN,'').replace('=','')
var Integer vol = Integer::parseInt(roomVolume.toString)
val volItem = guiVolumeItem.get(deviceIndex) as NumberItem
if (((volItem.state as DecimalType).intValue != vol) && (vol > 0) && (transportState == "PLAYING") && (requestDelay == noChangeDelay)) postUpdate (volItem, vol)
} else {
roomVolume = "-1"
}
tempDeviceState.add (deviceIndex.toString + delimiter + roomName + delimiter + powerState + delimiter + zone + delimiter + transportState + delimiter + currentTrackURI + delimiter + roomVolume + delimiter + roomsInState.toString)
} else {deviceStateOK = false}
}
}
}
if ((tempDeviceState.size < nRooms) && (zoneConfigRequest.contains ('unassignedRooms')))
{
var Integer nUnassignedRooms = Integer::parseInt(transform("JSONPATH","$.data.zoneConfig.unassignedRooms[0].room.length()", zoneConfigRequest).toString)
var iRoom = -1
while ((iRoom=iRoom+1) < nUnassignedRooms)
{
var String roomName = transform("JSONPATH","$.data.zoneConfig.unassignedRooms[0].room[" + iRoom.toString + "].$.name", zoneConfigRequest).toString
var String powerState = transform("JSONPATH","$.data.zoneConfig.unassignedRooms[0].room[" + iRoom.toString + "].$.powerState", zoneConfigRequest).toString
var deviceIndex = -1
while (((deviceIndex=deviceIndex+1) < nPHYS_DEVICES) && (roomName != deviceName.get(deviceIndex).toString)) {}
tempDeviceState.add (deviceIndex.toString + delimiter + roomName + delimiter + powerState + delimiter + "null" + delimiter + "STOPPED" + delimiter + "null" + delimiter + "null" + delimiter + "1")
}
}
if (tempDeviceState.size == nPHYS_DEVICES)
{
var i = -1
while ((i=i+1) < nPHYS_DEVICES)
{
var j = -1
while ((j=j+1) < nPHYS_DEVICES)
{
var str = tempDeviceState.get(j).toString
if (str.substring(0,1) == i.toString) tempSortedDeviceState.add (str.substring(2,str.length))
}
}
deviceStateOK = true
} else {deviceStateOK = false}
} else {deviceStateOK = false}
if (deviceStateOK)
{
var n = -1;
while ((n=n+1) < nPHYS_DEVICES)
{
if (deviceState.get(n).toString.contains(tempSortedDeviceState.get(n).toString) == false) {logInfo ("AUD",tempSortedDeviceState.get(n).toString)}
val stateItem = deviceState.get(n).toString.split(delimiter)
if (stateItem.length >= 3)
{
val gStateItem = guiStateItem.get(n) as StringItem
var String powerState = stateItem.get(1).toString
var String zone = stateItem.get(2).toString
var String transportState = stateItem.get(3).toString
var String shortZone
if (zone.contains ("-"))
{
var tempZone = zone.split ("-")
shortZone = tempZone.get(0).toString
} else {
shortZone = "uuid:--------"
}
postUpdate (gStateItem, powerState + ", " + transportState + ", " + shortZone)
}
}
deviceState = tempSortedDeviceState
}
Thread::sleep(1000)
}
end
section::speakerON
rule "GM_speakerON"
when
Item GLOBAL_AUD_actionQueue changed
then
if (GLOBAL_AUD_actionQueue.state.toString.length > 0)
{
var Integer i = -1
val action = GLOBAL_AUD_actionQueue.state.toString.split (delimiter)
if ((action.length > 0) && (action.get(0).toString.contains(actionQueueON)))
{
requestDelay = changeDelay
var iState = 0
while (((iState=iState+1) < (timeOut / requestDelay)) && (deviceStateOK == false))
{
logInfo ("AUD","speakerON::waiting for deviceStateOK ...")
Thread::sleep (100)
}
postUpdate (GLOBAL_AUD_actionQueue, "!" + GLOBAL_AUD_actionQueue.state.toString.substring (1, GLOBAL_AUD_actionQueue.state.toString.length))
logInfo ("AUD","speakerON::started action ..." + action.get(0).toString)
val items = action.get(0).toString.split (actionDelimiter)
var Integer ID = Integer::parseInt(items.get(1).toString)
val volItem = guiVolumeItem.get(ID) as NumberItem
var Integer safeVol = (volItem.state as DecimalType).intValue
logInfo ("AUD","speakerON::deviceState: " + deviceState.get(ID).toString + ", safeVol: " + safeVol.toString)
var String newStationURI = items.get(2).toString
var Integer zoneMatchIndex = -1
val stateItem = deviceState.get(ID).toString.split(delimiter)
var String powerState = stateItem.get(1).toString
var String zone = stateItem.get(2).toString
var String transportState = stateItem.get(3).toString
var String uri = stateItem.get(4).toString
if ((transportState != "PLAYING") || (powerState != "ACTIVE"))
{
var Integer nRoomsInZone = Integer::parseInt(stateItem.get(6).toString)
var String matchTransportState = ""
var String matchUri = ""
var String matchZone = ""
i = -1
while (((i=i+1) < nPHYS_DEVICES) && (zoneMatchIndex == -1))
{
val stateItem = deviceState.get(i).toString.split(delimiter)
matchTransportState = stateItem.get(3).toString
matchUri = stateItem.get(4).toString
matchZone = stateItem.get(2).toString
if ((matchUri == newStationURI) && (matchTransportState == "PLAYING")) {zoneMatchIndex = i}
}
if (zoneMatchIndex != -1) // zone found
{
logInfo ("AUD","speakerON::add " + deviceName.get(ID) + " to Zone " + matchZone)
sendHttpGetRequest(rsURL + "addToZone?id=" + deviceName.get(ID) + "&zoneID=" + matchZone)
var i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (zone != matchZone))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
zone = stateItem.get(2).toString
logInfo ("AUD","speakerON::waiting for add " + deviceName.get(ID).toString + " to zone " + matchZone + " (" + zone + ")")
Thread::sleep (requestDelay)
}
sendHttpGetRequest(rsURL + "setVolume?value=" + safeVol.toString + "&id=" + deviceName.get(ID) + "&scope=room")
} else { // no zoneMatch
if (zone == "null") // no zonematch and no zone
{
sendHttpGetRequest (rsURL + "createZone?id=" + deviceName.get(ID))
var i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (zone == "null"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
zone = stateItem.get(2).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " to get a own zone (" + zone + ")")
Thread::sleep (requestDelay)
}
if (powerState != "ACTIVE")
{
sendHttpGetRequest (rsURL + "leaveStandby?id=" + deviceName.get(ID))
var i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (powerState != "ACTIVE"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
powerState = stateItem.get(1).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " to wakeup (" + powerState + ")")
Thread::sleep (requestDelay)
}
}
sendHttpGetRequest(rsURL + "setVolume?value=" + safeVol.toString + "&id=" + deviceName.get(ID) + "&scope=room")
} else { // no zonematch and into other zone
if (nRoomsInZone > 1) // with other rooms inside
{
sendHttpGetRequest (rsURL + "dropFromZone?id=" + deviceName.get(ID))
var i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (zone != "null"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
zone = stateItem.get(2).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " to get dropped from zone (" + zone + ")")
Thread::sleep (requestDelay)
}
sendHttpGetRequest (rsURL + "createZone?id=" + deviceName.get(ID))
i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (zone == "null"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
zone = stateItem.get(2).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " to get a own zone (" + zone + ")")
Thread::sleep (requestDelay)
}
} else {
if (powerState != "ACTIVE")
{
sendHttpGetRequest (rsURL + "leaveStandby?id=" + deviceName.get(ID))
var i = 0
while (((i=i+1) < (timeOut / requestDelay)) && (powerState != "ACTIVE"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
powerState = stateItem.get(1).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " to wakeup (" + powerState + ")")
Thread::sleep (requestDelay)
}
}
}
}
logInfo ("AUD","speakerON::load " + newStationURI + " to " + deviceName.get(ID))
sendHttpGetRequest(rsURL + "loadUri?id=" + deviceName.get(ID) + "&value="+newStationURI)
}
i = -1
transportState = stateItem.get(3).toString
while (((i=i+1) < (timeOut / requestDelay)) && (transportState != "PLAYING"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
transportState = stateItem.get(3).toString
logInfo ("AUD","speakerON::waiting on " + deviceName.get(ID).toString + " for PLAYING-state ... (" + transportState + ")")
Thread::sleep (requestDelay)
}
logInfo ("AUD","speakerON::" + deviceName.get(ID).toString + " -> " + transportState)
} else {logInfo ("AUD","speakerON::transportState == PLAYING ... nothing to do ... done!")}
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString.replace ("!" + action.get(0).toString.substring(1,action.get(0).toString.length) + delimiter,''))
requestDelay = noChangeDelay
}
}
end
section::speakerOFF
rule "GM_speakerOFF"
when
Item GLOBAL_AUD_actionQueue changed
then
if (GLOBAL_AUD_actionQueue.state.toString.length > 0)
{
var Integer i = -1
val action = GLOBAL_AUD_actionQueue.state.toString.split (delimiter)
if ((action.length >0) && (action.get(0).toString.contains(actionQueueOFF)))
{
requestDelay = changeDelay
var iState = 0
while (((iState=iState+1) < (timeOut / requestDelay)) && (deviceStateOK == false))
{
logInfo ("AUD","speakerON::waiting for deviceStateOK ...")
Thread::sleep (100)
}
postUpdate (GLOBAL_AUD_actionQueue, "!" + GLOBAL_AUD_actionQueue.state.toString.substring (1, GLOBAL_AUD_actionQueue.state.toString.length))
val items = action.get(0).toString.split (actionDelimiter)
var Integer ID = Integer::parseInt(items.get(1).toString)
val stateItem = deviceState.get(ID).split (delimiter)
var String transportState = stateItem.get(3).toString
var String powerState = stateItem.get(1).toString
logInfo ("AUD","speakerOFF::deviceState: " + deviceState.get(ID).toString)
if ((transportState == "PLAYING") && (powerState == "ACTIVE") && (transportState != "NO_MEDIA_PRESENT"))
{
var Integer nRoomsInZone = Integer::parseInt(stateItem.get(6).toString)
var String zone = stateItem.get(2).toString
logInfo ("AUD","speakerOFF::started action ..." + action.get(0).toString)
if (nRoomsInZone > 1)
{
logInfo ("AUD","speakerOFF::drop " + deviceName.get(ID) + " from Zone " + zone)
sendHttpGetRequest (rsURL + "dropFromZone?id=" + deviceName.get(ID) + "&zoneId=" + zone)
} else {
logInfo ("AUD","speakerON::stop " + deviceName.get(ID))
sendHttpGetRequest (rsURL + "stop?id=" + deviceName.get(ID))
}
i = -1
while (((i=i+1) < (timeOut / requestDelay)) && (transportState != "STOPPED"))
{
val stateItem = deviceState.get(ID).toString.split(delimiter)
transportState = stateItem.get(3).toString
logInfo ("AUD","speakerOFF::waiting on " + deviceName.get(ID).toString + " for STOPPED-state ... (" + transportState + ")")
Thread::sleep (requestDelay)
}
logInfo ("AUD","speakerOFF::" + deviceName.get(ID).toString + " -> " + transportState + " ... done!")
} else {logInfo ("AUD","speakerOFF::transportState != PLAYING or not ACTIVE... nothing to do ... done!")}
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString.replace ("!" + action.get(0).toString.substring(1,action.get(0).toString.length) + delimiter,''))
requestDelay = noChangeDelay
}
}
end
section::HABPanel
rule "K_INT_speakerActive"
when
Item K_INT_speakerActive changed
then
if (K_INT_speakerActive.state == ON)
{
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueON + actionDelimiter + AUD_K_Index.toString + actionDelimiter + GLOBAL_INT_stationURI.state.toString + delimiter)
} else {
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueOFF + actionDelimiter + AUD_K_Index.toString + delimiter)
}
end
rule "WZ_INT_speakerActive"
when
Item WZ_INT_speakerActive changed
then
if (WZ_INT_speakerActive.state == ON)
{
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueON + actionDelimiter + AUD_WZ_Index.toString + actionDelimiter + GLOBAL_INT_stationURI.state.toString + delimiter)
} else {
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueOFF + actionDelimiter + AUD_WZ_Index.toString + delimiter)
}
end
rule "BAD_INT_speakerActive"
when
Item BAD_INT_speakerActive changed
then
if (BAD_INT_speakerActive.state == ON)
{
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueON + actionDelimiter + AUD_B_Index.toString + actionDelimiter + GLOBAL_INT_stationURI.state.toString + delimiter)
} else {
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueOFF + actionDelimiter + AUD_B_Index.toString + delimiter)
}
end
rule "WC_INT_speakerActive"
when
Item WC_INT_speakerActive changed
then
if (WC_INT_speakerActive.state == ON)
{
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueON + actionDelimiter + AUD_WC_Index.toString + actionDelimiter + GLOBAL_INT_stationURI.state.toString + delimiter)
} else {
postUpdate (GLOBAL_AUD_actionQueue, GLOBAL_AUD_actionQueue.state.toString + actionQueueOFF + actionDelimiter + AUD_WC_Index.toString + delimiter)
}
end
rule "K_INT_volumeButtons"
when
Item K_INT_volumeButtons received update
then
if (K_INT_volumeButtons.state == ON)
{
sendHttpGetRequest (rsURL + "volumeUp?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_K_Index).toString + "&scope=room")
} else {
sendHttpGetRequest (rsURL + "volumeDown?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_K_Index).toString + "&scope=room")
}
end
rule "WZ_INT_volumeButtons"
when
Item WZ_INT_volumeButtons received update
then
if (WZ_INT_volumeButtons.state == ON)
{
sendHttpGetRequest (rsURL + "volumeUp?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_WZ_Index).toString + "&scope=room")
} else {
sendHttpGetRequest (rsURL + "volumeDown?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_WZ_Index).toString + "&scope=room")
}
end
rule "BAD_INT_volumeButtons"
when
Item BAD_INT_volumeButtons received update
then
if (BAD_INT_volumeButtons.state == ON)
{
sendHttpGetRequest (rsURL + "volumeUp?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_B_Index).toString + "&scope=room")
} else {
sendHttpGetRequest (rsURL + "volumeDown?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_B_Index).toString + "&scope=room")
}
end
rule "WC_INT_volumeButtons"
when
Item WC_INT_volumeButtons received update
then
if (WC_INT_volumeButtons.state == ON)
{
sendHttpGetRequest (rsURL + "volumeUp?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_WC_Index).toString + "&scope=room")
} else {
sendHttpGetRequest (rsURL + "volumeDown?value=" + volumeStep.toString + "&id=" + deviceName.get(AUD_WC_Index).toString + "&scope=room")
}
end
rule "GLOBAL_INT_volumeButtons"
when
Item GLOBAL_INT_volumeButtons received update
then
var Integer i = -1
while ((i=i+1) < nPHYS_DEVICES)
{
val stateItem = deviceState.get(i).split (delimiter)
var String transportState = stateItem.get(3)
if (transportState == "PLAYING")
{
if (GLOBAL_INT_volumeButtons.state == ON)
{
sendHttpGetRequest (rsURL + "volumeUp?value=" + volumeStep.toString + "&id=" + deviceName.get(i).toString + "&scope=room")
} else {
sendHttpGetRequest (rsURL + "volumeDown?value=" + volumeStep.toString + "&id=" + deviceName.get(i).toString + "&scope=room")
}
}
}
end
rule "GLOBAL_INT_stationURI"
when
Item GLOBAL_INT_stationURI received update
then
logInfo ("AUD","GLOBAL_INT_stationURI::started")
if (GLOBAL_INT_stationURI.state.toString == safe_GLOBAL_INT_stationURI)
{
var Boolean singleZone = true
var String matchZone = ""
var String matchUri = ""
var Integer i = -1
var String zone = ""
while ((i=i+1) < nPHYS_DEVICES)
{
val stateItem = deviceState.get(i).split (delimiter)
var String transportState = stateItem.get(3)
var String uri = stateItem.get(4).toString
zone = stateItem.get(2).toString
if ((transportState == "PLAYING") && (uri != matchUri))
{
if (matchZone == "") // first playing zone
{
matchZone = zone
matchUri = uri
} else { // second playing zone
singleZone = false
}
}
}
if ((singleZone == true) && (matchZone.length > 0) && (matchUri.length > 0))
{
logInfo ("AUD","GLOBAL_INT_stationURI::singleZone switch URI")
sendHttpGetRequest (rsURL + "loadUri?id=" + matchZone + "&value=" + GLOBAL_INT_stationURI.state.toString)
} else {
logInfo ("AUD","GLOBAL_INT_stationURI::multiZone switch URI")
val activeSafeItem = newArrayList()
var Integer i = -1
while ((i=i+1) < nPHYS_DEVICES)
{
val active = guiActiveItem.get(i) as SwitchItem
if (active.state == ON)
{
postUpdate (active, OFF)
Thread::sleep (200)
activeSafeItem.add (true)
} else {
activeSafeItem.add (false)
}
}
i = nPHYS_DEVICES
while ((i=i-1) > -1)
{
val active = guiActiveItem.get(i) as SwitchItem
if (activeSafeItem.get(i) == true)
{
postUpdate (active, ON)
Thread::sleep (200)
}
}
}
}
safe_GLOBAL_INT_stationURI = GLOBAL_INT_stationURI.state.toString
end
section::setActiveItems // set active HABPanel-Items on external manipulation on RFs
rule "GM_setActiveItems"
when
Item GLOBAL_INT_updateRF changed to ON
then
Thread::sleep (30000)
logInfo ("AUD","setActiveItems::started..")
while (GLOBAL_INT_updateRF.state == ON)
{
if ((requestDelay == noChangeDelay) && (deviceState.size > 0))
{
var i = -1
while ((i=i+1) < nPHYS_DEVICES)
{
val stateItem = deviceState.get(i).toString.split(delimiter)
var String transportState = stateItem.get(3).toString
var String powerState = stateItem.get(1).toString
val activeItem = guiActiveItem.get(i) as SwitchItem
if ((transportState == "PLAYING") && (powerState == "ACTIVE") && (activeItem.state == OFF))
{
postUpdate (activeItem, ON)
logInfo ("AUD","setActiveItems::" + deviceName.get(i).toString + " >> ON")
}
if (((transportState == "STOPPED") || (transportState == "PAUSED_PLAYBACK") || (transportState == "NO_MEDIA_PRESENT")) && (activeItem.state == ON))
{
postUpdate (activeItem, OFF)
logInfo ("AUD","setActiveItems::" + deviceName.get(i).toString + " >> OFF")
}
}
}
Thread::sleep (changeDelay)
}
end
section::GUI
the webchannel-buttons are “buttons” with set the webstation-URI as command to item GLOBAL_INT_stationURI
and the raumfeld-debug-site
p.p.p.s. any smugly comment will let explode the post by itself immediatly - so have fun ewith reverse engineering