DLNA / UPNP binding

Continuing the discussion from DLNA / UPNP binding:

Hi, sorry, I not understand how I can install UPNP binding in my OpenHAB?

Not much to it… download the jar, and copy it to your /addons folder. It’s still very experimental, but I’m using it successfully with a Twonky media server and Sony SA-NS400 renderers. I’m frustrated with streams not always playing, wish there was a Channel on the renders for setting an AVTransportURI (you have to use the renderers as audio sinks), and I usually have to manually restart the binding after an OH restart to get the subscriptions going and then manually set the STOP and Player states, but having the subscriptions is wonderful (was previously using scripts without subscriptions).

1 Like

Hi Mark !

I’m sorry to bother you again, but I just upgraded to OpenHab 2.4.0-1 Release, and my simple Volume Control doesn’t work anymore.
When I power up my Sony device, the binding discover it but the discovery seem fail :

2019-01-11 11:03:43.239 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Device type MediaRenderer, manufacturer Sony Corporation, model BDV, SN# null

2019-01-11 11:03:43.240 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Media renderer found: Sony Corporation, BDV

2019-01-11 11:03:43.240 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Device ‘00000000-0000-1010-8000-544249199c7c’ reachability status changed to ‘true’

2019-01-11 11:03:43.241 [DEBUG] [pcontrol.handler.UpnpRendererHandler] - Renderer status changed to true

2019-01-11 11:03:43.243 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY add upnp subscription on AVTransport

2019-01-11 11:03:43.248 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY invoke upnp action GetTransportInfo on service AVTransport with inputs {InstanceID=0}

2019-01-11 11:03:43.249 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY invoke upnp action GetProtocolInfo on service ConnectionManager with inputs {}

2019-01-11 11:03:43.249 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Could not find action ‘GetTransportInfo’ for participant ‘00000000-0000-1010-8000-544249199c7c’

2019-01-11 11:03:43.250 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Could not find action ‘GetProtocolInfo’ for participant ‘00000000-0000-1010-8000-544249199c7c’

2019-01-11 11:03:43.258 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - A GENA subscription ‘AVTransport’ for device ‘uuid:00000000-0000-1010-8000-544249199c7c’ failed

2019-01-11 11:03:43.259 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY received subscription reply false from service AVTransport

==> /var/log/openhab2/events.log <==

2019-01-11 11:03:43.252 [hingStatusInfoChangedEvent] - ‘upnpcontrol:upnprenderer:00000000-0000-1010-8000-544249199c7c’ changed from OFFLINE (COMMUNICATION_ERROR): Communication lost with SALON BLU-RAY to ONLINE

==> /var/log/openhab2/openhab.log <==

2019-01-11 11:03:44.264 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Device type MediaRenderer, manufacturer Sony Corporation, model BDV, SN# null

2019-01-11 11:03:44.265 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Device ‘00000000-0000-1010-8000-544249199c7c’ reachability status changed to ‘false’

2019-01-11 11:03:44.266 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Media renderer found: Sony Corporation, BDV

2019-01-11 11:03:44.267 [DEBUG] [pcontrol.handler.UpnpRendererHandler] - Renderer status changed to false

2019-01-11 11:03:44.682 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Device type MediaRenderer, manufacturer Sony Corporation, model BDV, SN# null

2019-01-11 11:03:44.682 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Device ‘00000000-0000-1010-8000-544249199c7c’ reachability status changed to ‘true’

2019-01-11 11:03:44.683 [DEBUG] [very.UpnpControlDiscoveryParticipant] - Media renderer found: Sony Corporation, BDV

2019-01-11 11:03:44.683 [DEBUG] [pcontrol.handler.UpnpRendererHandler] - Renderer status changed to true

2019-01-11 11:03:44.684 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY add upnp subscription on AVTransport

2019-01-11 11:03:44.686 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY invoke upnp action GetProtocolInfo on service ConnectionManager with inputs {}

2019-01-11 11:03:44.687 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Could not find action ‘GetProtocolInfo’ for participant ‘00000000-0000-1010-8000-544249199c7c’

2019-01-11 11:03:44.689 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY invoke upnp action GetTransportInfo on service AVTransport with inputs {InstanceID=0}

2019-01-11 11:03:44.695 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - A GENA subscription ‘AVTransport’ for device ‘uuid:00000000-0000-1010-8000-544249199c7c’ failed

2019-01-11 11:03:44.695 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Could not find action ‘GetTransportInfo’ for participant ‘00000000-0000-1010-8000-544249199c7c’

2019-01-11 11:03:44.696 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY received subscription reply false from service AVTransport

==> /var/log/openhab2/events.log <==

2019-01-11 11:03:44.271 [hingStatusInfoChangedEvent] - ‘upnpcontrol:upnprenderer:00000000-0000-1010-8000-544249199c7c’ changed from ONLINE to OFFLINE (COMMUNICATION_ERROR): Communication lost with SALON BLU-RAY

2019-01-11 11:03:44.697 [hingStatusInfoChangedEvent] - ‘upnpcontrol:upnprenderer:00000000-0000-1010-8000-544249199c7c’ changed from OFFLINE (COMMUNICATION_ERROR): Communication lost with SALON BLU-RAY to ONLINE

But when I tried to send a setvolume command thru the Dimmer item :

2019-01-11 11:04:04.174 [DEBUG] [pcontrol.handler.UpnpRendererHandler] - Handle command 18 for channel upnpcontrol:upnprenderer:00000000-0000-1010-8000-544249199c7c:volume on renderer SALON BLU-RAY

2019-01-11 11:04:04.175 [DEBUG] [ding.upnpcontrol.handler.UpnpHandler] - Upnp device SALON BLU-RAY invoke upnp action SetVolume on service RenderingControl with inputs {InstanceID=0, Channel=Master, DesiredVolume=18}

2019-01-11 11:04:04.177 [DEBUG] [port.upnp.internal.UpnpIOServiceImpl] - Could not find action ‘SetVolume’ for participant ‘00000000-0000-1010-8000-544249199c7c’

…Error and nothing happend …

Any thought about it ? Tell me if I can provide you more information.

Thanks you.

@MacFly I would need to dig into the code again and start debugging and improving. I know there are issues with the binding, not just for you. I pulled this together as a quick project but didn’t have the time to keep on working on this one. I am afraid I won’t have the time for this the next few weeks. Sorry for that.
@5iver My original intention for this binding was to be able to use it as a control point to control a media server and send the media for playback to a renderer. That works for me. I actually can play more than just audio (video, photos). Again, I know there are bugs and combinations that do not work. There is a lot of potential for improvement. Registering the renderers as audio sinks is just an easy side step. Adding a URL directly to the renderer kind of defeats the whole concept of the binding. But maybe there should be a separate server thing type, which is just has a url for a streaming service channel (with a similar renderer selection channel capability). What do you think?

Using audio sinks just is not all that user friendly, and I’ve basically simulated a playURI channel with String items, a rule, and Items to store the uuids. A Channel would have simplified this. I also generate local TTS audio alerts on the server running OH, and have the speakers access the files from the server… no media server involved, so I don’t think what your suggesting would help, at least in my implementation.

Before the binding, I used scripts for everything. Using the binding and playStream, audio often does not play after sending the command. In looking at the logs after a playStream that did not work, I found a Stop PLAY and SetAVTransportURI all being sent at the same time, in random order. And the order of the responses explains why the audio often does not play. I would have expected that the SetAVtransport wouldn’t have been sent until the response was received for the STOP. Same for the PLAY waiting for the SetAVTransport response.

private void playMedia(String url) {
    handler.stop();
    String newUrl = url;
    if (!url.startsWith("x-") && !url.startsWith("http")) {
        newUrl = "x-file-cifs:" + url;
    }
    handler.setCurrentURI(newUrl, "");
    handler.play();
}

Hi Mark,
First of all, thanks you for your answer … I know this is only a side tool for you but so useful for many :slight_smile:

Here is more information about my differents tests, with the hope that will be help you when you have some spare time to dig in it.

First question is when it happend? With the help of Dockers, I have played with many milestone builds (openHAB 2.4 Milestone builds). Your binding works well until milestone 2.4.0-M7, 2.4.0-M8 and further doesn’t work anymore.

Second thing I noticed (on M8 and further) is that if my device is powered ON when I start Openhab, the binding works well but If my device is OFF at openhab start or if I power OFF and ON my device when openhab is started, the actions isn’t reconnized anymore.

Again, thanks you for this tool. At the moment, I kept a container with a light milestone 7 and only your binding, sync with my main openhab 2.4.0 release with mqtt.

Best regards,

Mac_Fly.

@5iver The logic of waiting for a message acknowledgment before taking the next action is weak in the binding. I would have to recode much of it, probably using futures to be able to wait for required return values, if there is an expected answer. I started this by copying some code from bindings like the Sonos binding, and I noticed that in most of these, there wasn’t a consistent check of message acknowledgments.
Also, I tested with a few players, and they all behaved differently as to the expected sequence before the next media queued was served.
Again, a lot of work ahead to make this logic a lot stronger. I am sorry, but I can’t focus on that in the near future.

1 Like

@MacFly Nice to see you found an ingenious way to keep it in the air. Also, thank you for the info on when the binding broke. I will check what changes happened between these releases that could impact the binding.
I hope to be able to come back to this binding, but I cannot guarantee that this will be in the near future.
PS: The reason it brakes between M7 and M8 is probably in this change: upgraded to JUPnP 2.5.0 (#6625) (detail / githubweb )

As a quick fix, I put in a small sleep. So far, this seems to have remedied streams not playing every time.

private void playMedia(String url) {
    handler.stop();
    try {
        Thread.sleep(250);
    } catch (Exception ex) {
        logger.error("Exception during sleep: {}", ex);
    }
    String newUrl = url;
    if (!url.startsWith("x-") && !url.startsWith("http")) {
        newUrl = "x-file-cifs:" + url;
    }
    handler.setCurrentURI(newUrl, "");
    try {
        Thread.sleep(250);
    } catch (Exception ex) {
        logger.error("Exception during sleep: {}", ex);
    }
    handler.play();
}

Hi friends!
I have errors:

2019-01-31 16:13:45.301 [ERROR] [y.upnp.internal.UpnpDiscoveryService] - Participant ‘org.openhab.binding.upnpcontrol.internal.discovery.UpnpControlDiscoveryParticipant’ threw an exception
java.lang.IllegalArgumentException: ID segment ‘bda4efc0-db0c-41f8-b7d5-38:1d:d9:08:d2:25’ contains invalid characters. Each segment of the ID must match the pattern [A-Za-z0-9_-]*.
at org.eclipse.smarthome.core.common.AbstractUID.validateSegment(AbstractUID.java:97) ~[102:org.eclipse.smarthome.core:0.10.0.oh240]
at org.eclipse.smarthome.core.common.AbstractUID.(AbstractUID.java:75) ~[102:org.eclipse.smarthome.core:0.10.0.oh240]
at org.eclipse.smarthome.core.common.AbstractUID.(AbstractUID.java:58) ~[102:org.eclipse.smarthome.core:0.10.0.oh240]
at org.eclipse.smarthome.core.thing.UID.(UID.java:57) ~[109:org.eclipse.smarthome.core.thing:0.10.0.oh240]
at org.eclipse.smarthome.core.thing.ThingUID.(ThingUID.java:43) ~[109:org.eclipse.smarthome.core.thing:0.10.0.oh240]
at org.openhab.binding.upnpcontrol.internal.discovery.UpnpControlDiscoveryParticipant.getThingUID(UpnpControlDiscoveryParticipant.java:74) ~[?:?]
at org.openhab.binding.upnpcontrol.internal.discovery.UpnpControlDiscoveryParticipant.createResult(UpnpControlDiscoveryParticipant.java:47) ~[?:?]
at org.eclipse.smarthome.config.discovery.upnp.internal.UpnpDiscoveryService.remoteDeviceAdded(UpnpDiscoveryService.java:188) [242:org.eclipse.smarthome.config.discovery.upnp:0.10.0.oh240]
at org.jupnp.registry.RemoteItems$1.run(RemoteItems.java:114) [244:org.jupnp:2.5.1]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
at java.lang.Thread.run(Thread.java:748) [?:?]

How I can solve it?

@Mherwege, I’m trying to utilize the binding for the last bit that I’m still using a script for, and I could use some help. I can browse my media server, which is great, but I can’t get the search functionality to do anything. Here is a shell script that takes a playlist name as a string, and returns the URIs for each track. I’d like to replace this with your binding…

#!/bin/sh
#searchString='dc:title = "_Wake Up!" and upnp:class = "object.container.playlistContainer"'
searchString="dc:title = \"$1\" and upnp:class = \"object.container.playlistContainer\""
#echo ${searchString}
#echo
containerID=$(/usr/bin/curl -s --connect-timeout 10 -m 20 http://10.5.5.10:9000/dev0/srv1/control -H "CONTENT-TYPE: text/xml; charset=\"utf-8\"" -H "SOAPACTION: \"urn:schemas-upnp-1400service:ContentDirectory:1#Search\"" -d "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><u:Search xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\"><ContainerID>1</ContainerID><SearchCriteria>$searchString</SearchCriteria><Filter>container id</Filter><StartingIndex>\$1</StartingIndex><RequestedCount>0</RequestedCount><SortCriteria></SortCriteria></u:Search></s:Body></s:Envelope>" | sed 's/.*container id=\"\(.*\)\" parent.*/\1/')
#echo "containerID=${containerID}"
#echo
if [ -n "${containerID}" ]; then
    playURI=$(/usr/bin/curl -s --connect-timeout 10 http://10.5.5.10:9000/dev0/srv1/control -H "CONTENT-TYPE: text/xml; charset=\"utf-8\"" -H "CONNECTION: close" -H "SOAPACTION: \"urn:schemas-upnp-1400service:ContentDirectory:1#Browse\"" -d "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><u:Browse xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\"><ObjectID>$containerID</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter>protocolInfo</Filter><StartingIndex>$containerID</StartingIndex><RequestedCount>0</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>" | grep -Po '(&lt;res protocolInfo=.+?&gt;)[^&]+' | egrep -o '(http:\/\/[^&]+)' | tr '\n' ',' | sed 's/,$//')
    echo "${playURI}"
    /usr/bin/curl -s --request PUT --header "Content-Type: text/plain" --header "Accept: application/json" --data "ON" "http://localhost:8080/rest/items/Status_Network_Twonky/state"
else
    /usr/bin/curl -s --request PUT --header "Content-Type: text/plain" --header "Accept: application/json" --data "OFF" "http://localhost:8080/rest/items/Status_Network_Twonky/state"
fi

I’ve tried different formats for the search criteria (and with other playlist names)…

openhab> smarthome:send Twonky_Search_Criteria "dc:title='_Wake Up!' and upnp:class='object.container.playlistContainer'"
Command has been sent successfully.
openhab> smarthome:send Twonky_Search_Criteria 'dc:title=\"_Wake Up!\" and upnp:class=\"object.container.playlistContainer\"'
Command has been sent successfully.
openhab> smarthome:send Twonky_Search_Criteria "dc:title = '_Wake Up!' and upnp:class = 'object.container.playlistContainer'"                                                                                      
Command has been sent successfully.
openhab> smarthome:send Twonky_Search_Criteria "dc:title = \"_Wake Up!\" and upnp:class = \"object.container.playlistContainer\""
Command has been sent successfully.

… and flipping the Search switch. I’ve also tried doing this from several containers, but nothing is working. There aren’t any errors in the log. How are you using the search?

When I tested this, I was doing it all from PaperUI. The syntax looks fine though. I am just unsure about all the quotes.
You should be able to put in the search string and then flip the search switch to get a result.
I don’t have it running at the moment, so this may take some time for me to test again. It did work back then though. I am afraid I never spend the time to really finish this properly.

Hi all,
I installed the binding and it found my yamaha media playback and my kodi upnp server. I don’t know where to go from here. How can I browse my library? And how to check the results of a search?

Thanks a lot.

For browsing, setup your sitemap like this…

        Text label="Twonky" icon=soundvolume {
            Text item=Twonky_Search_Criteria
            Switch item=Twonky_Search
            Switch item=Twonky_Select
            Switch item=Twonky_Serve
            Selection item=Twonky_Renderer
            Selection item=Twonky_Title
        } 

You can then use Title and Select to browse. Select a renderer and then Serve to play what you have selected. Search hasn’t worked for me yet.

Thanks 5iver,
I tried what you suggested and it works, apart from the fact that I have to refresh the page in browser to obtain the correct list after every selection…

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.

1 Like

@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