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 :
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><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="BROWSE_TYPE_KEYvideo*~>_<~*BROWSE_SORT_KEY8*~>_<~*BROWSE_GROUP_KEY0*~>_<~*BROWSE_FILTER_KEYBROWSE_FILTER_TERM_STARTfilepath:<_EQUALS_>:/tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7BROWSE_FILTER_TERM_END*~>_<~*Naruto Shippuden 170.mkv" parentID="BROWSE_TYPE_KEYvideo*~>_<~*BROWSE_SORT_KEY8*~>_<~*BROWSE_GROUP_KEY0*~>_<~*BROWSE_FILTER_KEYBROWSE_FILTER_TERM_STARTfilepath:<_EQUALS_>:/tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7BROWSE_FILTER_TERM_ENDBROWSE_FILTER_TERM_STARTname:<_EQUALS_>:Naruto Shippuden 170.mkvBROWSE_FILTER_TERM_END*~>_<~*" restricted="0"><dc:title>Naruto Shippuden 170.mkv</dc:title><upnp:class>object.item.videoItem</upnp:class><dc:creator></dc:creator><upnp:genre>Unknown</upnp:genre><upnp:album></upnp:album><res bitrate="1230" protocolInfo="file-get:*:video/x-matroska::DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00000000001000000000000000000000" protection="" tokenType="0" duration="" size="210161304" colorDepth="0" ifoFileURI="" resolution="--">file:///tmp/media/nfs/NAS/FILMS/Naruto/Naruto.Shippuden.Saison.7/Naruto%20Shippuden%20170.mkv</res></item></DIDL-Lite></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 🙂
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.
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 !!!?????
je donne le lien vers tout les codes sur l’upnp database dans le billet ^^
Donc l’information est là, après il faut lire…
(http://www.upnp-database.info/device.jsp?deviceId=244 et aller en bas de la page…)
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
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
tcpdump -A -s2048 host