iSponsorBlockTV
iSponsorBlockTV copied to clipboard
Device discovery and Roku TV
I found myself fiddling with DIAL and lounge API, so I thought I'd share a couple of findings
So we get the response from SSDP discovery:
Cache-Control: max-age=3600
ST: urn:dial-multiscreen-org:service:dial:1
USN: ID::urn:dial-multiscreen-org:service:dial:1
Ext:
Server: Roku/12.5.5 UPnP/1.0 Roku/12.5.5
LOCATION: http://IP:8060/dial/dd.xml
WAKEUP: MAC=MAC;Timeout=10
Right, so hitting the location (http://IP:8060/dial/dd.xml), and we need to read the response header Application-URL. Interestingly, the value for me is
Application-URL: http://IP:8060/dial
As you can see, there's no trailing slash, which might be causing an issue here I guess the issue here is that we need to check for a trailing slash, and if it's not there, add it.
Next, when hitting http://IP:8060/dial/YouTube, it gets blocked (403) if you do not add this exact origin header
Origin: https://www.youtube.com
The response headers contain
Access-Control-Allow-Origin: https://www.youtube.com
So I guess that's something that needs to be added to the request here.
Finally, here's the content of http://IP:8060/dial/YouTube
<?xml version="1.0" encoding="UTF-8" ?>
<service
xmlns="urn:dial-multiscreen-org:schemas:dial" dialVer="2.1">
<name>YouTube</name>
<options allowStop="true" />
<state>running</state>
<link rel="run" href="run" />
<additionalData>
<testYWRkaXR>c0ef1ca</testYWRkaXR>
<brand>TCL</brand>
<model>7130X</model>
<yumi>XXXX</yumi>
<passiveSessionId>XXXX</passiveSessionId>
</additionalData>
</service>
So this is strange, since there's no screen id and no lounge id here. So this could cause an error.
Anyway, these are some observations, perhaps they are reasons why the discovery is not working for some people.
Based on this comment https://github.com/andrewsayre/pysmartthings/issues/63#issuecomment-973682191, there's no screen Id or lounge or anything.
My (wild) guess is that Youtube took all this info to their backend, and you need to hit some API with the passiveSessionId somehow.
That’s very interesting, that would explain why auto discovery magically didn’t work for me when I tried to use it a couple weeks ago. Thanks for making such a detailed issue
I've been trying to figure out how the passiveSessionId might work but the devices I have to test all still show the regular screenId parameter. I'd appreciate a mitm capture of a phone connecting to a device that has the passiveSessionId in order to keep investigating. I'll make the trailing slash fixed in the near future. Thanks for your insight
I didn't have time to do a capture, but I tried to understand the lounge/dial better. It turns out it is normal for the DIAL info of the app to not contain additionalData at all.
I think in some way, if the TV is already in a lounge, it might return additionalData (like screenId, loungeToken, etc) and this would allow the client (e.g. a phone) to immediately join a lounge. When additionalData is not present, in this case the phone sends a pairingCode to the TV, and the TV registers it using https://www.youtube.com/api/lounge/pairing/register_pairing_code. I still don't know how a phone generates the pairingCode (exactly which endpoint it hits)
My understanding is the lack of additionalData (or simply the lack of a lounge, device id, etc) is because there's no need to create, join and listen to changes in a lounge (which requires long polling) if there are no other devices expect the TV itself. So technically the TV can differ joining a lounge until another device joins.
https://github.com/patrickkfkan/yt-cast-receiver is a good resource to test against actually, and I understood some of the ins and outs better because of it.