Jouons avec le WD Tv Live et UPNP

wdtvlive

Depuis des années je dispose d’un boîtier WD TV Live qui me permet de lire sur la télévision les vidéos stockées sur mon NAS Synology.
Efficace, ce petit boîtier fonctionne parfaitement bien et a trouver naturellement sa place dans le meuble TV.

J’avais un peu oublié sa présence jusqu’à me rendre compte que mon système domotique ne le connaissait pas.
Qu’a cela ne tienne, c’était le moment de jouer avec 🙂

Sur mon téléphone Android, je dispose d’une application, WD TV Remote, qui permet de contrôler le boitier par wifi.
Cela suffit à se dire qu’il doit être possible d’interagir avec lui par le réseau local.

Qui dit boîtier multimédia, dit forcement UPNP. Une petite découverte via l’outil gssdp-discover du projet gupnp-tools nous donne les points d’entrées du boîtier (je vous passe l’ensemble des équipements trouvés pour se concentrer sur le WD) :

gssdp-discover -i eth0.8 --timeout=5
Using network interface eth0.8
Scanning for all resources
resource available
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77::upnp:rootdevice
Location: http://wdtvlive:10184/
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77
Location: http://wdtvlive:10184/
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77::urn:schemas-upnp-org:device:MediaRenderer:1
Location: http://wdtvlive:10184/
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77::urn:schemas-upnp-org:service:AVTransport:1
Location: http://wdtvlive:10184/
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77::urn:schemas-upnp-org:service:ConnectionManager:1
Location: http://wdtvlive:10184/
resource available
USN:      uuid:5e881b94-0090-a9c7-b3b0-56fc82ddce77::urn:schemas-upnp-org:service:RenderingControl:1
Location: http://wdtvlive:10184/

Une visite sur l’url http://wdtvlive:10184/ nous donne un joli arbre xml

...
<serviceList><service><serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType><serviceId>urn:upnp-org:serviceId:AVTransport</serviceId><SCPDURL>MediaRenderer_AVTransport/scpd.xml</SCPDURL><controlURL>MediaRenderer_AVTransport/control</controlURL><eventSubURL>MediaRenderer_AVTransport/event</eventSubURL></service>
...

Déformation professionnelle oblige, je lance un tcpdump sur mon téléphone et j’agis sur la télécommande WD TV Remote.

On retrouve bien le POST http sur le point d’entrée du boîtier et la réponse de se dernier.

POST /MediaRenderer_AVTransport/control HTTP/1.1
Accept: */*
User-Agent: Twonky-NMC/7.3-Android (Android/4.4.2 (Build KOT49H); samsung/GT-I9505) DLNADOC/1.50
Host: wdtvlive:10184
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo"
Content-Type: text/xml; charset="utf-8"
Content-Length: 312
 
<?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:GetTransportInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:GetTransportInfo></s:Body></s:Envelope>HTTP/1.1 200 OK
 
Transfer-Encoding: chunked
EXT:
CONTENT-TYPE: text/xml; charset="utf-8"
SERVER: POSIX, UPnP/1.0, Intel MicroStack/1.0.1497
1BF
 
<?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:GetTransportInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><CurrentTransportState>PAUSED_PLAYBACK</CurrentTransportState><CurrentTransportStatus>OK</CurrentTransportStatus><CurrentSpeed>1</CurrentSpeed></u:GetTransportInfoResponse></s:Body></s:Envelope>

Génial 🙂

Ne reste plus qu’a tester tout cela avec une belle requête curl (accrochez-vous à votre clavier..) :

curl -H "Content-Type: text/xml" -H 'SOAPACTION: urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo"' -XPOST -d '<s:Envelope xmlns: s="http://schemas.xmlsoap.org/soap/envelope" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding"><s:Body><u:GetTransportInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:GetTransportInfo></s:Body></s:Envelope>' http://wdtvlive:10184/MediaRenderer_AVTransport/control
<?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:GetTransportInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><CurrentTransportState>PAUSED_PLAYBACK</CurrentTransportState><CurrentTransportStatus>OK</CurrentTransportStatus><CurrentSpeed>1</CurrentSpeed></u:GetTransportInfoResponse></s:Body></s:Envelope>

Elle est pas belle la vie ? :p

On voit dans la réponse le mode actuel du boîtier :
PAUSED_PLAYBACK

En remplacant la méthode « GetTransportInfo » par « GetPositionInfo », le WD Tv nous donne tout un tas d’information dont le film actuellement joué :

curl -H "Content-Type: text/xml" -H 'SOAPACTION: urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"' -XPOST -d '<s:Envelope xmlns: s="http://schemas.xmlsoap.org/soap/envelope" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding"><s:Body><u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:GetPositionInfo></s:Body></s:Envelope>' http://wdtvlive:10184/MediaRenderer_AVTransport/control
<?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:GetPositionInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><Track>1</Track><TrackDuration>00:22:46</TrackDuration><TrackMetaData>&lt;DIDL-Lite xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot;&gt;&lt;item id=&quot;BROWSE_TYPE_KEYvideo*~&gt;_&lt;~*BROWSE_SORT_KEY8*~&gt;_&lt;~*BROWSE_GROUP_KEY0*~&gt;_&lt;~*BROWSE_FILTER_KEYBROWSE_FILTER_TERM_STARTfilepath:&lt;_EQUALS_&gt;:/tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7BROWSE_FILTER_TERM_END*~&gt;_&lt;~*Naruto Shippuden 170.mkv&quot; parentID=&quot;BROWSE_TYPE_KEYvideo*~&gt;_&lt;~*BROWSE_SORT_KEY8*~&gt;_&lt;~*BROWSE_GROUP_KEY0*~&gt;_&lt;~*BROWSE_FILTER_KEYBROWSE_FILTER_TERM_STARTfilepath:&lt;_EQUALS_&gt;:/tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7BROWSE_FILTER_TERM_ENDBROWSE_FILTER_TERM_STARTname:&lt;_EQUALS_&gt;:Naruto Shippuden 170.mkvBROWSE_FILTER_TERM_END*~&gt;_&lt;~*&quot; restricted=&quot;0&quot;&gt;&lt;dc:title&gt;Naruto Shippuden 170.mkv&lt;/dc:title&gt;&lt;upnp:class&gt;object.item.videoItem&lt;/upnp:class&gt;&lt;dc:creator&gt;&lt;/dc:creator&gt;&lt;upnp:genre&gt;Unknown&lt;/upnp:genre&gt;&lt;upnp:album&gt;&lt;/upnp:album&gt;&lt;res bitrate=&quot;1230&quot;  protocolInfo=&quot;file-get:*:video/x-matroska::DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00000000001000000000000000000000&quot; protection=&quot;&quot; tokenType=&quot;0&quot; duration=&quot;&quot; size=&quot;210161304&quot; colorDepth=&quot;0&quot; ifoFileURI=&quot;&quot; resolution=&quot;--&quot;&gt;file:///tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7/Naruto%20Shippuden%20170.mkv&lt;/res&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData><TrackURI>file:///tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7/Naruto%20Shippuden%20170.mkv</TrackURI><RelTime>00:08:00</RelTime><AbsTime>NOT_IMPLEMENTED</AbsTime><RelCount>2147483647</RelCount><AbsCount>2147483647</AbsCount></u:GetPositionInfoResponse></s:Body></s:Envelope>

Ici je vois que Junior regarde le fichier « Naruto Shippuden 20170.mkv » (ok pas très instructif comme film…) et ce depuis 8 minutes.

Python disposant de l’excellent module lxml pour parser les fichiers XML, un coup de scripting tout simple permet d’isoler les informations importantes :

from lxml import etree
 
tree = etree.parse('le fichier xml')
for element in tree.iter('CurrentTransportState'):
result = element.text
print "WD TV Live status: "+result
 
tree = etree.parse('le fichier xml')
for element in tree.iter('TrackURI'):
film = element.text
print "WD TV Live joue : "+film
 
WD TV Live status: PLAYING
WD TV joue: file:///tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7/Naruto%20Shippuden%20170.mkv

Toutes les commandes disponibles sont référencées sur l’upnp database.

Maintenant le serveur domotique connait l’état du boitier WD TV Live ainsi que le fichier joué sur le téléviseur.
Ce qui nous permet par exemple de programmer une surveillance de ce que Junior regarde…

tree = etree.parse('le fichier xml')
for element in tree.iter('TrackURI'):
film = element.text
if "Pr0n_A_Papa" in film:
# power off immédiat de la télévision

J’espère que ce petit billet vous donnera envie d’aller explorer un peu les points d’entrée UPNP des différents équipements de votre domicile 😉

EDIT : Pour éteindre et allumer votre WD TV Live par une simpe requête http, il suffit d’envoyer le POST suivant :
curl -XPOST -d ‘{« remote »: »w »}’ http://wdtvlive/cgi-bin/toServerValue.cgi

Amusez-vous bien 🙂

Ce billet a été posté dans domotique et taggé , . Bookmark ce permalink.

6 commentaires sur “Jouons avec le WD Tv Live et UPNP

  1. Article intéressant qui m’ouvre des portes.
    C’est vrai que l’on voit apparaitre des périphériques UPNP un peu partout. Mais je n’avais pas pensé à les piloter comme tu le fais.
    A creuser.
    Merci.

  2. Super !!! Quel dommage d’avoir aussi peu d’information sur où/comment trouver les codes du WD live TV. L’upnp database !?!? où est l’information !!!?????

  3. Bonjour,
    pourriez vous me donner les détails des réglages aussi bien coté Synology que cote WDTV?
    J’essaye d’avancer mais je suis un peu bloqué:
    – soit je passe par l’interface WDTV, mais je ne peux pas ni changer le type d’affichage, ni telecharger les infos, ni supprimer les fichiers
    – Soit je passe par l’appli ios pour lancer le film en sélectionnant le lecteur wdtv, mais cela rame et je perds la possibilité de choisir la langue ou les sous titres.
    la wdtv et le synology 216j sont tous les deux branchés sur une routeur giga.
    merci à vous

  4. Bonjour, merci pour ton tuto ! 😉 Pourrais-tu m’eclairer sur ta façon de faire tcpdump? car je l’ai installé sous debian et il ne me retourne pas dutout d’infos détaillées comme toi…

    Voila son retour -> 14:25:00.598434 ARP, Request who-has WD TV Live.local tell 192.168.1.28, length 46

    Merci a toi