Yes… forgot to mention that. IDK if the issue is in the binding, or the UIs and StateOptions. I’ll check to see if the Kodi binding has the same issue.
The issue is in the UI’s. I remember a PR where the state options were added to Basic UI and Classic UI in selections, but the PR did not add dynamic updating of the state options. I believe the SSE events don’t include them, so the issue was in the core. PaperUI has the same issue.
@5iver does the UPNP binding give you the ability to find renderers on the network and effecively use these devices as AudioSinks/players for Audio on the network?
Yes… it’s great not having to use scripts for this anymore.
Fantastic, do the Sinks show as switches that can be turned on/off? Id love to see how youve used it fo this purpose if you use them as sinks for audio playback
No. Audiosinks are more at the system level, that can be used in audio Actions. I have Items that hold the UUIDs of all the sinks, an Item for each speaker representing the PlayURI, and play to the speakers using this. The important part is right above the ‘except’ in the third rule.
@rule("Alert: Advance House Shuffle")
@when("Item HouseShuffle_Advance received command")
def advanceHouseShuffle(event):
advanceHouseShuffle.log.debug("Advancing House Shuffle")
workingStreamList = str(items["Working_Stream_List"]).split(",")
if len(workingStreamList) == 0:
streamList = str(items["Stream_List"]).split(",")
workingStreamList = refillList(None, streamList, "HA_Streams_{}".format(items["HouseShuffle_Genre"]))
if len(workingStreamList) > 0:
events.sendCommand("HouseShuffle_PlayURI", workingStreamList.pop())
events.postUpdate("Working_Stream_List", ",".join(workingStreamList))
else:
advanceHouseShuffle.log.error("Advance House Shuffle: Reset workingStreamList failed")
@rule("Alert: House Shuffle received command")
@when("Item HouseShuffle_PlayURI received command")
def houseShuffleChange(event):
previousPlayURI = items["HouseShuffle_PlayURI"]
houseShuffleChange.log.debug("House Shuffle changed: [{}]".format(event.itemCommand))
for speaker in filter(lambda speaker: speaker.state == previousPlayURI and ir.getItem(speaker.name.replace("_PlayURI", "_Player")).state == PlayPauseType.PLAY, ir.getItem("gSpeakerPlayURI").getMembers()):
speaker.sendCommand(str(event.itemCommand))
@rule("Alert: Speaker playURI received command")
@when("Member of gSpeakerPlayURI received command")
def speakerPlayURIReceivedCommand(event):
speakerPlayURIReceivedCommand.log.debug("Speaker playURI received command [{}]: Starting rule: current state=[{}], command=[{}]".format(event.itemName,ir.getItem(event.itemName).state,event.itemCommand))
try:
if event.itemCommand == StringType("HouseShuffle"):
newURI = str(items["HouseShuffle_PlayURI"])
if not any(filter(lambda speaker: speaker.state == PLAY and items[speaker.name.replace("_Player","_PlayURI")] == StringType(newURI), ir.getItem("gSpeakerPlayer").getMembers())):
speakerPlayURIReceivedCommand.log.debug("Speaker playURI received command [{}]: No other speaker is playing the house shuffle, so picking a new random one".format(event.itemName))
workingStreamList = str(items["Working_Stream_List"]).split(",")
if len(workingStreamList) > 0:
newURI = workingStreamList.pop()
if len(workingStreamList) > 0:
events.sendCommand("Working_Stream_List", ",".join(workingStreamList))
else:
events.sendCommand("HouseShuffle_Genre", str(items["HouseShuffle_Genre"]))
events.postUpdate("HouseShuffle_PlayURI", newURI)
events.sendCommand(event.itemName, newURI)
else:
if items[event.itemName.replace("_PlayURI","_System")] == ON:
audioSink = "upnpcontrol:upnprenderer:{}".format(items[event.itemName.replace("_PlayURI","_UUID")])
playStream(audioSink, str(event.itemCommand))
else:
speakerPlayURIReceivedCommand.log.debug("Speaker playURI received command [{}]: canceling request since speaker is offline: [{}]".format(event.itemName, event.itemCommand))
except Exception as e:
import traceback
message = "Alert: Speaker playURI received command [{}]: Exception: [{}]: [{}]".format(event.itemName, e, traceback.format_exc())
speakerPlayURIReceivedCommand.log.error(message)
NotificationAction.sendNotification(adminEmail,"{}".format(message))
While I’m at it, here is a rule to provide a online/offline state for the speakers. Every now and then mine will fall off the network.
@rule("Alert: Speaker system status update")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521099e changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521366d changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f522dcaf changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f5207868 changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f520f682 changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f5210909 changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52220b3 changed")
@when("Thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de changed")
def speakerSystemStatusUpdate(event):
speakerName = filter(lambda item: str(item.state).replace("uuid:", "") == str(event.thingUID).split(":")[2], ir.getItem("gSpeakerUUID").members)[0].name.replace("UUID", "System")
speakerSystemStatusUpdate.log.debug("Speaker system update [{}]: [{}]".format(speakerName, event.statusInfo))
if items[speakerName] == OnOffType.OFF and str(event.statusInfo) == "ONLINE":
events.sendCommand(speakerName, "ON")
if items[speakerName.replace("System", "Player")] == PlayPauseType.PLAY:
events.sendCommand(speakerName.replace("System", "Stop"), "OFF")
else:
events.sendCommand(speakerName.replace("System", "Stop"), "ON")
speakerSystemStatusUpdate.log.info("Speaker system update [{}]: ON".format(speakerName))
elif items[speakerName] == OnOffType.ON:
events.sendCommand(speakerName, "OFF")
speakerSystemStatusUpdate.log.info("Speaker system update [{}]: OFF".format(speakerName))
Woah! Thanks!!! May you also show us your items?
They are not your usual DSL rules are they??
I will have a crack at doing this with my UPNP renderer
No, Jython. I’ve liberated my home of the old rule engine!
Here are some examples of the Items I use…
Group gSpeaker "Speakers" <soundvolume> (gEntertainment,gDevice)
Group gAutoPlay_Mode "Auto Play: Mode [%s]" <none> (gSpeaker)
Group gSpeakerSystem "Renderer: System [%s]" <none> (gSpeaker)
Group gSpeakerIP "Renderer: IPs" <none> (gSpeaker)
Group gSpeakerPlayURI "Renderer: PlayURIs" <none> (gSpeaker)
Group gSpeakerPlayer "Renderer: Players" <none> (gSpeaker)
Group gSpeakerStop "Renderer: Stops" <none> (gSpeaker)
Group gSpeakerTitle "Renderer: Titles" <none> (gSpeaker)
Group gSpeakerUUID "Renderer: UUIDs" <none> (gSpeaker)
Group gSpeakerVolume "Renderer: Volumes" <none> (gSpeaker)
String Alert_Prefix "Alert prefix [%s]" <none> (gSpeaker)
String Working_Stream_List "Working stream list [%s]" <none> (gSpeaker)
String Stream_List "Stream list [%s]" <none> (gSpeaker)
String Working_Prefix_List "Working prefix list [%s]" <none> (gSpeaker)
String Prefix_List "Prefix list [%s]" <none> (gSpeaker)
String HouseShuffle_PlayURI "House Shuffle station [%s]" <none> (gSpeaker)
String HouseShuffle_Genre "House Shuffle station genre [%s]" <none> (gSpeaker)
String HouseShuffle_Playlist "House Shuffle playlist [%s]" <none> (gSpeaker)
Switch HouseShuffle_Advance "Advance House Shuffle" <switch> (gSpeaker) ["Switchable"] {autoupdate="false"}
Switch Wakeup_Alarm "Wakeup Alarm [%s]" <switch> (gSpeaker) ["Switchable"]
Switch Wakeup_Alarm_Snooze "Snooze" <switch> (gSpeaker) ["Switchable"] {autoupdate="false"}
Switch Stop_All_Speakers "Stop all speakers" <switch> (gSpeaker) ["Switchable"] {autoupdate="false"}
String US_MasterBathroom_Speaker_AutoPlay_Mode "Master Bathroom Upstairs (Auto Play: Mode) [%s]" <switch> (gUS_MasterBathroom,gSpeaker,gAutoPlay_Mode)
String US_MasterBathroom_Speaker_PlayURI "Master Bathroom Upstairs (PlayURI) [%s]" <none> (gUS_MasterBathroom,gSpeaker,gSpeakerPlayURI)
String US_MasterBathroom_Speaker_UUID "Master Bathroom Upstairs (UUID) [%s]" <none> (gUS_MasterBathroom,gSpeaker,gSpeakerUUID)
Switch US_MasterBathroom_Speaker_System "Master Bathroom Upstairs (System) [%s]" <switch> (gUS_MasterBathroom,gSpeaker,gSpeakerSystem)
Dimmer US_MasterBathroom_Speaker_Volume "Master Bathroom Upstairs (Volume) [%s]" <soundvolume> (gUS_MasterBathroom,gSpeaker,gSpeakerVolume) ["Lighting"] {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:volume"}
Player US_MasterBathroom_Speaker_Player "Master Bathroom Upstairs (Player) [%s]" <none> (gUS_MasterBathroom,gSpeaker,gSpeakerPlayer) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:control"}
Switch US_MasterBathroom_Speaker_Stop "Master Bathroom Upstairs (Stop) [%s]" <switch> (gUS_MasterBathroom,gSpeaker,gSpeakerStop) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:stop"}
Switch US_MasterBathroom_Speaker_Mute "Master Bathroom Upstairs(Mute) [%s]" <soundvolume_mute> (gUS_MasterBathroom,gSpeaker) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:mute"}
String US_MasterBathroom_Speaker_Title "Master Bathroom Upstairs (Title) [%s]" <none> (gUS_MasterBathroom,gSpeaker,gSpeakerTitle) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:title"}
String US_MasterBathroom_Speaker_Artist "Master Bathroom Upstairs (Artist) [%s]" <none> (gUS_MasterBathroom,gSpeaker) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:artist"}
String US_MasterBathroom_Speaker_Album "Master Bathroom Upstairs (Album) [%s]" <none> (gUS_MasterBathroom,gSpeaker) {channel="upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f52109de:album"}
String Twonky_Renderer "Twonky Renderer [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:upnprenderer"}
String Twonky_Title "Twonky Title [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:currenttitle"}
String Twonky_Search_Criteria "Twonky Search Criteria [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:searchcriteria"}
Switch Twonky_Search "Twonky Search [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:search"}
Switch Twonky_Select "Twonky Select [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:select"}
Switch Twonky_Serve "Twonky Serve [%s]" <none> (gDS_Office,gSpeaker) {channel="upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:serve"}
doh! That leaves me out
Ive got enough to learn on the old engine to start that hahah!
That’s unfortunate. You can use both at the same time too.
The important bit for you, using the DSL, would be something like this…
import org.eclipse.smarthome.model.script.ScriptServiceUtil
rule "Speaker playURI received command"
when
Member of gSpeakerPlayURI received command
then
audioSink = "upnpcontrol:upnprenderer:" + ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.replace("_PlayURI","_UUID")).state.toString
playStream(audioSink, receivedCommand)
end
Only new to this stuff, so just baby steps. If only I was a developer/programmer it would be much easier but one language is enough for now!
Thanks Scott! Ill give it a go
Hi Mark,
Sorry to bother you but just to know if there is any chance that you could check this issue ?
Best regards,
Mac_Fly.
HI 5iver, had a go at this but I could only get MUTE to work
20:01:55.429 [INFO ] [smarthome.event.ItemCommandEvent ] - Item 'KDS_Stop' received command ON
20:01:55.430 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Handle command ON for channel upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:stop on renderer Linn Klimax DS
20:01:55.430 [INFO ] [arthome.event.ItemStatePredictedEvent] - KDS_Stop predicted to become ON
20:01:55.431 [DEBUG] [nding.upnpcontrol.handler.UpnpHandler] - Upnp device Linn Klimax DS invoke upnp action Stop on service AVTransport with inputs {InstanceID=0}
It seems maybe this feature isnt available to me?
0:02:33.266 [DEBUG] [nding.upnpcontrol.handler.UpnpHandler] - Upnp device Linn Klimax DS add upnp subscription on AVTransport
20:02:33.278 [DEBUG] [nding.upnpcontrol.handler.UpnpHandler] - Upnp device Linn Klimax DS received subscription reply true from service AVTransport
20:02:33.286 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable LastChange with value <Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/"><InstanceID val="0"><TransportState val="NO_MEDIA_PRESENT"/><TransportStatus val="OK"/><CurrentMediaCategory val="NO_MEDIA"/><PlaybackStorageMedium val="NONE"/><NumberOfTracks val="0"/><CurrentTrack val="0"/><CurrentTrackDuration val="0:00:00"/><CurrentMediaDuration val="0:00:00"/><CurrentTrackURI val=""/><AVTransportURI val=""/><CurrentTrackMetaData val=""/><AVTransportURIMetaData val=""/><PossiblePlaybackStorageMedia val="NETWORK"/><CurrentPlayMode val="NORMAL"/><TransportPlaySpeed val="1"/><NextAVTransportURI val="NOT_IMPLEMENTED"/><NextAVTransportURIMetaData val="NOT_IMPLEMENTED"/><RecordStorageMedium val="NOT_IMPLEMENTED"/><PossibleRecordStorageMedia val="NOT_IMPLEMENTED"/><RecordMediumWriteStatus val="NOT_IMPLEMENTED"/><CurrentRecordQualityMode val="NOT_IMPLEMENTED"/><PossibleRecordQualityModes val="NOT_IMPLEMENTED"/></InstanceID></Event> from service AVTransport
20:02:33.287 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentMediaCategory with value NO_MEDIA from service AVTransport
20:02:33.288 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable AVTransportURI with value from service AVTransport
20:02:33.288 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrackURI with value from service AVTransport
20:02:33.288 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable TransportPlaySpeed with value 1 from service AVTransport
20:02:33.289 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrackURI with value from service AVTransport
20:02:33.289 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable InstanceID with value 0 from service AVTransport
20:02:33.289 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrackMetaData with value from service AVTransport
20:02:33.290 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable TransportStatus with value OK from service AVTransport
20:02:33.290 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable AVTransportURIMetaData with value from service AVTransport
20:02:33.290 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrackMetaData with value from service AVTransport
20:02:33.291 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrackDuration with value 0:00:00 from service AVTransport
20:02:33.291 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentPlayMode with value NORMAL from service AVTransport
20:02:33.291 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable PossiblePlaybackStorageMedia with value NETWORK from service AVTransport
20:02:33.292 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentTrack with value 0 from service AVTransport
20:02:33.292 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentRecordQualityMode with value NOT_IMPLEMENTED from service AVTransport
20:02:33.292 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable RecordMediumWriteStatus with value NOT_IMPLEMENTED from service AVTransport
20:02:33.293 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable PlaybackStorageMedium with value NONE from service AVTransport
20:02:33.293 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable NextAVTransportURIMetaData with value NOT_IMPLEMENTED from service AVTransport
20:02:33.293 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable PossibleRecordQualityModes with value NOT_IMPLEMENTED from service AVTransport
20:02:33.294 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable NumberOfTracks with value 0 from service AVTransport
20:02:33.294 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable PossibleRecordStorageMedia with value NOT_IMPLEMENTED from service AVTransport
20:02:33.294 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable CurrentMediaDuration with value 0:00:00 from service AVTransport
20:02:33.295 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable NextAVTransportURI with value NOT_IMPLEMENTED from service AVTransport
20:02:33.295 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable RecordStorageMedium with value NOT_IMPLEMENTED from service AVTransport
20:02:33.295 [DEBUG] [npcontrol.handler.UpnpRendererHandler] - Upnp device Linn Klimax DS received variable TransportState with value NO_MEDIA_PRESENT from service AVTransport
Please post your Item definition and describe what you are trying to do.
Hi Scott
Adjust volume, skip track or stop
Switch KDS_Stop "KDS Stop [%s]" {channel="upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:stop"}
Switch KDS_Mute "KDS Mute [%s]" {channel="upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:mute"}
String KDS_Title "KDS Track Title [%s]" {channel="upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:title"}
Player KDS_Player "KDS Player [%s]" {channel="upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:control"}
Dimmer KDS_Volume "KDS Volume [%s]" {channel="upnpcontrol:upnprenderer:4c494e4e-0026-0f22-3898-012366860171:volume"}
Those look OK. It’s possible that your device and the binding are not compatible. What speaker are you trying to use?
Hi Scott
Its one of these:
These are made by Linn, so I would have thought they’d work. Can you use them with any other UPnP control software? I’ve tried a LOT of them and this is my favorite.
I use Kazoo to control the unit. They do work with Bubble UPNP too.
How can I determine which features it would support? Not sure where to go from here…
Since this is a very experimental binding, so there’s not much more you can do without digging into the logs and code.