-
-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Upnp Device Finder Service #4534
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Wow, i had almost the exact same code, i mean really identical ( right down to using Math.max on the expiration calc ) . That was weird to read. Couple things i observed running basically the same thing over night. While you can get the devices Putting this in the finder core addon probably mitigates this a bit more, since it should startup along with the jupnp service, but who knows? I also noticed that when sending a targeted search, the device did not always respond, i'm guessing this is some type of backoff logic by the device to identical search requests to avoid flooding the network ? I would assume that after 60 or 120 seconds that would clear. But it seemed kinda inconsistant. One thing i also did was when the thing was added, if the device was not in the jupnp registry (device is null), i would send a targeted search request to it and try and get it registered. I wish Jupnp included the registration time of the device as well as it advertised max age. I can give this a try today if you like and see how it works? |
In my code when the addon would start (e.g. calling subscribe) that sends an immediate search which effectively resets and synchronizes the counting of both the registry and the finder service. |
I did the same, but did not always get a subscription callback for the device, which was what i was trying to debug today. |
In my case when the component is activated it does two general searches for sddp:all and ssdp:rootdevice to make sure the registry is populated.
Yeah. I think it might be accrssible via java reflection but probably a pita to implement. |
I also did something similar in the upnpService.getControlPoint().search();
upnpService.getControlPoint().search(new RootDeviceHeader()); |
I'll try running this right now and revert the control binding back and see how it goes. |
So my device still went offline after exactly 30 mins. Couple of observations.
Whats odd is that i don't see any logging from the Finder service, like the listeners are not firing. Also if you look above, the UpnpIOServiceImpl starts removing subscriptions, but then we see UpnpControlDiscoveryParticipant detect the device. I'm a little confused, but will look into it a little later today. |
...ore.io.transport.upnp/src/main/java/org/openhab/core/io/transport/upnp/UpnpDeviceFinder.java
Show resolved
Hide resolved
I will probably need to add some retry logic for the case the search fails. |
So the good news is my device is still online, so thats great. There were 2 instances over night where the scheduled search happened, but the device did not respond and a minute later we see
But when the code tries searching right after this log statement, the device does respond and the thing comes back online, so thats good. Checking the upnp log, we indeed never received a response to the first search request performed a minute earlier. One thing i'm a bit confused about, but is not really a problem, is this:
The first 3 lines are within a single millisecond of each other and seem to show the device unregistering, but then the discovery participant is notified at the same time of the device. The device does not respond to the search request in the upnp logs until |
As you say. Curious. |
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
@digitaldan I just pushed a commit that retries the searches at 5 second intervals for a maximum of 5 retries, or until the device is discovered (in fewer tries). |
Thats great, i'll run that now for a while and let you know. |
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
@mherwege I am interested to hear your thoughts on the following topics:
|
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
So i ran this for about 24 hours. The WiiM stayed active all the way until about 2 hours ago. Over this time it did deregister 5 times, but in four of those cases it responded to the final search request sent after deregistering and stayed online. Then, for some reason it would not respond to the scheduled search requests or the the requests sent when a device is deregistered (so 5 search requests before it timed out, and 5 search requests after it deregistered). So this definitely helped, but it would be nice when a device deregisters to continue to try to discover it every minute or so (it could be rebooting, or there might be a network issue, etc..) An yes, i think this device is not behaving nicely. I might see if i can report this on the forums, i think the devs there actually monitor those. |
@digitaldan I am reluctant to go much further down this road because we really still have no clue about the real problems we are trying to work around. So before doing much more I want to run some proper UPnP diagnostic tools on this device to get a full picture of what it does/not do. I have plenty of test tools but no device to test. You have the device but apparently no tools. So I did some googling about possible Upnp tools from Apple (below) and so I wonder if you can kindly give them a try? |
Before i pick a tool, what type of information are you looking for? I guess my first choice for general troubleshooting would be Wireshark/tcpdump with a capture filter to specifically target the packets we are after, but again i guess i'm not sure what info you are looking for? I also have jUpNP logging at TRACE level to its own file appender, which seems like it does a pretty good job as a general sniffer? |
Let me ask a slightly off-topic question, but still related. @mherwege this is probably aimed more to you. For this device specifically, our UPnP control binding handles 80% of the functionality, but is missing some key vendor specific features, namely:
I have struggled figuring out the right place to put these into a binding, some thoughts:
I'm not saying i like all these options, its just what i have been thinking about. The reason i ask is that if we specifically support this device in a binding, we could isolate workaround for it there and not in the core. |
Initially I want to see raw data on every datagram that the devices sends, on every port, on every protocol, on every ip version, both autonomously, and as responses to queries from other apps. |
Apropos playlists and multi room support: I have also done a lot of work on this. Pure UPNP / DLNA does neither of these very well. I see that your Wiim device has an own namespace service for playlists to presumably get around UPNP / DLNA weaknesses. And Sonos and Linn (to name a few) also do similar things. In pure UPNP/DLNA the playlist is not managed by the renderer but rather by the control point. The renderer supports a playlist of only two tracks (setAvTransportURI and setNextAvTransportURI) which allows renderers to do gapless track transitions. So rather than going down the custom namespace path for different manufacturers renderers I would suggest adding playlist support to OH whereby it pushes tracks to the renderer via setAvTransportURI plus setNextAvTransportURI if the renderer supports it. Apropos multi room support, the original UPNP/DLNA standard only allows synchronising the track start (you can play around with custom delays in sending set.. resp. setNext.. commands in order to compensate for different renderers track start latency). However if the various renderers play out the tracks at different frames per second, then track synch can drift apart (particularly on longer tracks). Using renderers of the same model ameliorates but does not fully solve this. There is a v2 of the renderer UPNP specification that implements clock synch methods across renderers plus a playSynched method. However different manufacturers have tended to spurn following the playSynched specification in favour of using their own custom namespace api. Probably through laziness and a wish to impose their own proprietary ecosystem. Nevertheless there is some potential for the OH playlist service (TM! new!) to implement a common playlist towards multiple renderers from different manufacturers with track start synching via thing config params, and play rate synching via (say) a kind of proxy server to split a common stream from the media server into multiple rate transposed streams to the individual renderers. This would be a big project. But I have the core concepts in my head. We could do this in parallel with your suggestion to go down the manufacturer proprietary route. But it would be well to have a clear architecture defined in advance. With (say) common interfaces defined by OH and implemented specifically for different manufacturers custom ecosystems. |
PS one reason why manufacturers implement custom playlist management in the renderer is because if the playlist is managed by the control point then that must remain online to dish out the track play commands. This is not possible if the cp is a mobile device. But since OH remains on 7/24 it could easily dish out track play commands to all attached renderers continuously. |
And this is exactly what I tried implementing in the upnpcontrol binding. It may not be perfect, but there is playlist management in that binding. |
It it solves the issue for a good number of devices, why not. But I am still struggling to understand if there is no issue with jupnp or the specific's user network setup in the first place. If this is a common problem, it should actually be resolved in the jupnp library, but that starts being outside of the scope of pure OH.
The classes you refer to put it in the scope of jupnp, not OH. The upnp transport is there to try to isolate that. You may not need an OSGI service though, as all upnp users in OH also use the transport, so they could just call an interface to register for updates. |
This is a hard call. I would probably go for 2 short term, but look into 3 is the longer term option. |
I think at this point i would opt for # 2 as well. This handler could then send more frequent search requests just for this device, support the additional mutli-room and playlist support, and we will not need to touch the core at this point. I dropped a message in the WiiM forums , its actually quite active with more then a few devs there, so maybe some progress will be made in an update. |
Umm. Could it simply be that JUpnp does not support ipV6? @digitaldan you say your device has both ipV4 and ipV6 connections. So perhaps it sends its NOTIFY announcements on the Upnp ipV6 multicast address/port and not on the Upnp ipv4 ones? In that case OH will not (yet) see those notifications. Whereas by contrast the M-SEARCH hack proposed in this PR does work because OH sends the search on the Upnp ipV4 multicast address/port, and the device correctly responds using ipV4. @digitaldan could you therefore please try disabling ipV6 for this device? @kaikreuzer / @lolodomo just copying you on the post in case you have any thoughts on this.. |
Pinging @wborn too.. |
So i just ran tcpdump for all udp packets on port 1900, and i don't see anything from the WiiM on IPV6. Also the WiiM support team got back to me and asked me to open a ticket up. Another user (likely a developer) on the forums confirmed with tcpdump he was also not seeing any notify packets from the device over a 90 min period, but his Sonos device were frequently broadcasting. They have a frequent release cadence for firmware updates, so i'm optimistic this could get fixed sooner then later 🤞 |
Yes, that's correct, but I would think that this should be no problem, because IPv4 is still the default for UPnP. I don't know if the specs say anything about how a device is supposed to react if both IP versions are available, but my guess is that it definitely has to announce and respond on IPv4 in such a case.
I agree here, but then again, jUPnP tries to be a spec-compliant implementation and workarounds are not really nice. Having said this, there are already a couple of special handlings for non-compliant devices in the code as it turns out that there are far too many non-compliant devices out there in the wild.
You are all invited to create PRs against jUPnP as well - luckily @wborn and myself are maintainers there. 😄 |
Just a quick update, WiiM/Linkplay has been very responsive. They confirmed the issue and the development team is going to update their code to send NOTIFY packets. They are also planning on pushing an early build to my devices so i can test it out. Hopefully this resolves at least this device's issues sometime soon. |
Excellent news! Let us wait to confirm that they fixed it. But after that I think we can close this PR. |
Relates to #4527
Relates to openhab/openhab-addons#17976
This PR adds a new component service that can be used to keep mis-behaving UPnP devices 'alive' in the UPnP registry by sending a targeted M-SEARCH message for their UDN before their maxAge expires.
I am not sure if we should add the to OH Core or if we should actually solve this issue in the respective OH addon for example so I am posting this code (work-in-progress) for review and comments.
Signed-off-by: Andrew Fiddian-Green software@whitebear.ch