" /> Informatique - Mon para-monde
Flux RSS

jeudi 17 avril 2014

Pourquoi on ne peut pas transcoder vers une Freebox

Les serveurs multimédias domestiques évoluent de jour en jour. Il n'y a pas si longtemps, on se baladait avec des disques durs portables puis des clés USB, des SDCards pour aller de l'ordi à la platine de salon. Désormais toutes les boxes font plus ou moins serveur et lecteur de flux réseau. C'est le cas aussi pour certaines consoles de jeux (hackées ou non).

Pour ma part, j'ai une PS3 et une Freebox HD (V5, pas la dernière), elles font toutes deux - mal chacune dans leur genre - lecteur DLNA.

Au fil du temps, j'ai d'abord utilisé un petit serveur DLNA qui se trouvait sur mon premier NAS, autant dire qu'il n'était pas top, ne supportait rien et le processeur n'avait de toute façon pas le oumpff pour faire autre chose que streamer en direct les contenus (c'était un TeraStationII de Buffalo).

Depuis j'ai monté mon "petit" NAS perso sur un HP MicroServer avec FreeNAS comme OS/Distrib. Sur FreeNAS,l'une des alternatives "au déballage" est l'installation de Plex. Ce serveur multimédia a de nombreuses fonctions (comme le streaming à distance par exemple, le partage via internet, etc.) et en local dispose d'un module serveur DLNA (=UPnP) qui gère le transcodage.

Le transcodage consiste pour le serveur à recalculer les flux vidéo et audio à la volée lorsque le lecteur ne supporte pas le format original du fichier. La puissance du processeur du MicroServer est suffisante pour la plupart de mes besoins.

L'avantage du transcodage, c'est qu'on a plus à se poser la question du format, on streame un fichier vers la PS3, les tablettes/téléphones Android ou de la pomme de façon totalement transparente même si comme c'est le cas pour les différents iTrucs, il n'y a pas beaucoup de format supporté à la base...

Or comme un oeil sagace peu s'en rendre compte, je n'ai pas cité ci-dessus la Freebox... En effet, celle-ci, bien qu'elle supporte pas mal de codecs tant video qu'audio ou des contenants multimédias pas les plus courants (le Matroska par exemple, excellent container mais peu diffusé face à l'AVI,le MPEG-TS ou au MP4) marche encore plus mal que la PS3 qui avant le transcodage était TRES tatillonne...

Pour résumer : La Freebox ne supporte pas l'un des principaux containers actuel à savoir le MP4, ainsi tout fichier s'annoncant comme "*.mp4" ou avec un type MIME "video/mp4" sera tout simplement ignoré dans la liste des fichiers disponibles (alors que le serveur les envoie bien dans la liste), par ailleurs, pour une raison à l'origine inconnue, il n'était pas possible de transcoder, la freebox n'arrivant pas à récupérer le flux (qui fonctionnait en faisant mimer la freebox par XBMC ou VLC). La freebox a d'autres limitations mais je les laisse de côté car rien en théorie que le transcodage ne pourrait résoudre !

Je me suis donc mis en tête de faire fonctionner ce %#~$£^#"& de transcodage... Si la PS3 le fait il n'y avait pas de raison que la freebox (supportant plus de codec) ne le fasse pas ! Après quelques jours à triturer les profils, a lire des lignes et des lignes de logs de Plex. Il faut se rendre à l'évidence. Il n'y a rien à faire du côté serveur ! Le problème est exclusivement du côté client. J'ai donc ouvert un ticket sur le bugtracker de la Freebox HD mais sans grand espoir quand on voit le nombre de tickets ouverts en attente depuis des années !

Pour la petite histoire, Plex se base sur les champs d'entête et en particulier sur le champ HTTP "User-Agent" pour identifier le matériel qui lui parle. Or la freebox envoie bien une telle ligne lorsqu'elle parcours l'arborescence par l'énumérateur UPnP, mais une fois la ressource multimédia trouvée, elle va la chercher via une requête HTTP ne contenant pas ce fameux "User-Agent"... Résultat, Plex perd la notion du type de matériel qui lui parle et considère parler à un matériel "Generic", c'est à dire qui sait tout lire sans transcodage. N'ayant plus notion de destination de transcodage, l'accès aux ressources énumérées à l'étape précédent échoue lui aussi.

La solution propre est que la Freebox envoie toujours son User-Agent... et il n'y a hélas pas de solution sale car Plex ne fait pas de discrimination par adresse IP par exemple (normal, ca n'a pas de sens dans un réseau universal**Plug'nPlay** ou les IP peuvent varier sans prévenir à l'occasion d'un renouvellement de bail DHCP par exemple...).

Donc toi qui bosse chez Free au développement de la Freebox et qui passe par hasard ici, s'il te plait pourrais-tu rajouter une ligne dans "fbxupnpav" pour que le User-Agent soit envoyé lors de la demande d'un objet pour le streaming. Je t'assure, il y en a pour une ligne du genre

httpResponse.header("User-Agent","Linux/2.6 UPnP/1.0 fbxupnpav/1.0");

en fonction de ton langage de prédilection...

Note, si le source de fbxupnpav avait été libre, je l'aurais fait moi-même et je t'aurais même économisé ça...

Allez soit cool, vieux ! ;)

samedi 25 janvier 2014

Je craque ou pas ?

Ubuntu en 3200x1800 et bien plus joli et pratique que win8.1 . Certes faut de bon yeux sur un 13" mais c'est tout à fait utilisable...

Donc je sens que ça va imminer... Pour l'instant le seul hic c'est que j'aime bien travailler sur un HD neuf et garder celui d'origine dans un coin et là... ben ces mSATA de 512go, j'en trouve pas...

lundi 2 juillet 2012

Aidez moi à trouver mon prochain portable !

En 2007 j'ai changé d'ordinateur portable. A l'époque j'avais pris un ASUS F3sv-ak143c.

Les points forts qui me l'avaient fait choisir étaient à l'époque :

  • Le processeur un Core2Duo T7500 à 2.2GHz permettant par exemple facilement de faire de la virtualisation
  • 2Go de mémoire
  • Une vraie carte vidéo (sans que ce soit un monstre de consommation) et pas une "intégrée" Intel.
  • Un écran de 15,4" avec une bonne résolution : 1680x1050
  • et un bon support de Linux saveur Ubuntu

Or voilà, je ne suis pas tendre avec mon matériel : la limite fatidique des 5 ans est en vue et comme tous ses prédécesseurs au même âge (Dell, Acer), l'ordinateur part en lambeau, le simple fait de le poser sur un table, je retrouve des vis en dessous, le mécanisme d'ouverture sur l'avant est bloqué.

Voici pour illustrer la charnière droite (faiblarde rendant l'écran mou comme du chewing-gum) et ses ses jolis fils apparents

et le trackpad qui tient encore grace à un recours fréquent à un appel divin

(notez la trace d'usure du clic-gauche :) )

Or donc, la recherche du successeur a débuté est je suis TRES ennuyé. La principale raison tient dans les caractéristiques que j'ai noté ci-dessus qui me semblaient juste bien depuis bien des années.

Mon critère principal était la résolution d'écran suivi du rapport puissance/poids.autonomie . J'AIME avoir des écrans avec plein de points (Mon Dell de 2000 était déjà un 15" rapport 4/3 de 1400x1050 (SXGA+), l'Acer avait exactement le même écran alors que les 16/10 étaient déjà légion mais avec des résolutions inférieures, c'est pour moi un strict minimum pour organiser correctement mon bureau). Or en cette année 2012, trouver un portable pas trop cher avec une résolution ayant au moins 1050 lignes devient une vraie course au trésor la norme semblant être devenue 1680x800 c'est à dire une régression de 20% par rapport à ce que j'ai actuellement et depuis 12 ans !

De son côté le "FullHD" (1920x1080) n'est disponible qu'exceptionnellement et sur des ordinateurs chers, le seul endroit où on le trouve à prix raisonnable c'est bizarrement sur des écrans 13,3" comme ceux des nouveaux Zenbook Prime d'ASUS.

Alors je me tourne vers la grande famille internetique et tweetisante pour avoir votre avis :

Quel ordinateur portable dois-je envisager pour remplacer mon F3Sv ?

Les critères étant :

  • résolution 1600x1050 MINIMUM
  • diagonale d'écran entre 13" et 15,4", pas plus.
  • autonomie 7h (selon la pub), >4h30 (en réel)
  • proc puissant avec virtualisation et économie d'énergie
  • 4Go (les 2Go devenaient poussifs sous la dernière Ubuntu)
  • Carte vidéo dédiée (pas obligatoirement le dernier modèle pour jouer à Crysis, au maximum je ferai du Portal2 via Wine :) )
  • Clavier rétro-éclairé (c'est un nouveau critère, bien pratique :) )
  • disque dur matériel ou SSD ou hybride "onsenfou" d'au moins 300Go (actuellement, il y a un 500Go dedans)
  • Le poids inférieur à 1,75kg, le moins lourd le mieux ;)
  • Lecteur de SD
  • Support de Linux (tout du moins capable de le faire tourner au début et que ce soit une machine pas trop obscure afin que le support s'améliore ensuite)

Les non critères :

  • présence d'une ouebcam
  • présence d'un lecteur/graveur DVD/BR

Les hors de question :

  • Non, je ne veux pas une tablette
  • Ni d'un machin Apple (pour plein de raisons)
  • plus petit que 13" ou plus grand que 15,6" (intraitable là dessus)
  • d'une résolution <1600 de large et <1050 de haut (idem)

Alors qui peut m'aider ?

samedi 23 juin 2012

Raspberry Pi + LEGO, redux

Bon,le premier boîtier en LEGO avait été commencé à l'arrache et cet après-midi avec Lucas, nous nous sommes attelés à une version plus "prés du corps".

Je n'ai pas pris de photo de making-of désolé, mais grosso-modo j'ai d'abord fait un gabarit avec des pièces disparates pour déterminer l'encombrement par niveau du R-Pi, trouvé une solution pour le fixer et le surélever un peu pour la dissipation thermique. Puis j'ai monté le boitier définitif en barres de 1 et enfin j'ai fait le toit et le socle.

Le format du R-Pi est assez compatible avec le format LEGO mais malgré tout il ne fait pas un nombre pair de plots LEGO, nécessitant en cela des compromis (par exemple le rebord de la base sur 2 des faces)*

Toujours est-il voici la version définitive du boîtier. Etant donné qu'il s'agit d'un projet Top Secret, il est gardé de prés par 2 cosmonautes LEGO !

Voici maintenant la face alimentation+SD Card :

La face portant la prise HDMI :

Le port RJ45 et les 2 USB :

Et la sortie audio et composite (plus la petite fenêtre pour voir les LEDs de statut) :

Et maintenant au boulot ! On remet le système dedans :

Et on allume :

vendredi 22 juin 2012

Premières taches d'administration après l'installation d'une image sur Raspberry Pi

Se logguer sur son R-Pi avec image Pisces

Pour se logguer, je rappelle qu'il faut utiliser le compte "raspbian" avec le mot de passe "raspbian".

L'image pisces a un serveur ssh fonctionnel dès le démarrage, c'est ce que j'utilise (mon R-Pi n'a ni clavier ni écran)

Si vous utilisez un clavier et un écran, attention par défaut il est en QWERTY. Perso, passant par SSH, mon clavier est correctement réglé mais il est visiblement conseillé de reconfigurer tout cela via

dpkg-reconfigure locales
dpkg-reconfigure keyboard-configuration

Le compte "raspbian" a le droit de sudoer pour "root" pour administrer la machine.

Changer les mots de passe par défaut

Brut d'installation, une image pisces possède 2 comptes avec mots de passe : root et raspbian Il convient de les modifier car ils sont communs à toutes les installations du système.

En tant que "raspbian" tapez :

passwd

et saisissez 2 fois de suite à l'aveugle votre nouveau mot de passe. vous venez de modifier le mot de passe de "raspbian"

Pour le compte root, il suffit de passer par sudo :

sudo passwd
(saisissez le mot de passe de "raspbian")

et idem, saisissez 2 fois le nouveau mot de passe de root.

Il est important de modifier ce mot de passe pour le connaître, en effet si lors du boot du R-Pi, il y a un problème il faudra saisir ce mot de passe pour pouvoir accéder au shell (par exemple pour réparer un crash disque).

Toutes les manips suivantes sont à faire en utilisateur root ou via sudo.

Modifier les clés du serveur SSH par défaut

Toutes les images pisces possèdent les mêmes clés SSH, il faut en générer d'autres pour augmenter la sécurité (sinon un autre système sur lequel elles seraient installées, quel qu'il soit, pourrait se faire passer entièrement pour votre R-Pi).

rm /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-server

Faire la mise à jour du système et du firmware

en tant que root et en ayant une connexion internet valide

apt-get update ; apt-get upgrade

puis

rpi-update

... et patienter... puis rebooter via

reboot

Réglage du fuseau horaire

Le Raspberry n'ayant pas de RTC (d'horloge interne sauvegardée par pile) l'image pisces est équipée d'un serveur (et donc client) NTP déjà configuré par contre il faut régler le fuseau par défaut.

dpkg-reconfigure tzdata

Changer le nom du système

Par défaut, lorsqu'on part d'une image pisces, le système s'appelle... pisces, changeons cela :

echo littlebrick > /etc/hostname

Pour régler le FQDN si vous en avez un, éditez /etc/hosts et mettez le sur la ligne 127.0.1.1 sous la forme :

127.0.1.1     littlebrick.i.senis.org littlebrick

Dans les 2 cas, il faut bien sûr remplacer "littlebrick" et "littlebrick.i.senis.org" par le nom de votre système.

Une fois fait, soit il faudra attendre le redémarrage suivant, soit il faut lancer

hostname -b littlebrick

Ajouter un utilisateur

adduser nom_de_login

remplir les champs pertinents (perso, juste le "Full name") puis configurer le mot de passe

passwd nom_de_login

enfin, si nécessaire, ajouter l'utilisateur au groupe des "sudoers" si cet utilisateur peut administrer la machine (passer en "root").

adduser nom_de_login sudo

Compléter le système

ajouter "contrib non-free" dans /etc.apt/sources.list au bout des lignes :

deb http://archive.raspbian.org/raspbian/ wheezy main contrib non-free
deb-src http://archive.raspbian.org/raspbian/ wheezy main contrib non-free

Attention, ne pas décommenter les lignes concernant la distrib Debian de base, car même si la distrib Raspbian est basée sur Debian, les paramètres de compilation spécifiques retenus pour le Raspberry rendent les binaires incompatibles (en particulier la façon de gérer les "float" qui est "soft" sur Debian et "hard" sur Raspbian)

relancer

apt-get update

et exécuter

aptitude

pour installer les paquets supplémentaires désirés.

mercredi 20 juin 2012

Raspberry Pi + LEGO = Amour :)

Pour un Raspberry, le boitier idéal ne peut être QUE en LEGO alors je commence à faire des tests avec les pièces que j'ai :

Avec les LED à l'air :

Avec l'arceau au dessus des USB et RJ45 :

Arrivée du Raspberry Pi

Et voilà, comme le temps file ! Ca fait bientôt 3 mois que je n'avais rien écrit ici bas.

Cependant aujourd'hui est un grand jour. J'ai reçu mon Raspberry Pi, le petit ordinateur pas cher pour bidouiller.

Alors certes pour l'instant je ne l'ai pas encore eu le temps de le brancher mais voici le premier contact en photos.

A titre d'information et pour illustrer le succès du Raspberry, il faut savoir que j'ai fait mon inscription sur le site de précommande de RS Components le 9 mars. J'ai eu accès au site de commande ferme le 22 mai, ai passé commande le lendemain pour une livraison annoncée sous 3 semaines. Au final je l'ai donc reçu aujourd'hui 20 juin.

Or donc ce matin vers 10 heures, la camionnette de DHL m'a amené le paquet signé du logo RS si typique

J'avais commandé le Raspberry Pi modèle B (le seul disponible et franchement, je ne sais pas si le modèle A a un quelconque avenir...) mais aussi une carte SD de 4Go et une alimentation micro-USB (les chats par ici ayant un appétit particulier pour les petits câbles de ce genre, il ne m'en reste pas beaucoup de fonctionnelles)

Le Raspberry arrive bien emballé dans un petit carton moussu, fermé par des autocollants de "sécurité". 2 feuilles de papier glacé accompagnent, n'en attendez pas grand chose, l'une est le certificat de conformité, l'autre de "démarrage rapide" (en gros, allez sur pour récupérer la distrib que vous voulez).

Une fois déballée, la carte en elle-même ressemble à ce à quoi je m'attendais. Ce qui marque surtout c'est la taille, elle n'est vraiment pas grosse...

Pour vous donner une bonne impression de celle-ci, j'y ai branché l'adaptateur secteur que j'ai acheté avec

puis je l'ai mise à côté de sa petite soeur (une carte Arduino Uno/Ethernet), de la carte SD et d'un breadboard.

Voilà pour la mise à nu, maintenant YAPUKA !

lundi 19 mars 2012

ELV Max! Il est temps de passer commande

Excusez la blague à 2 balles, il n'est bien sûr pas question d'acheter quelque chose mais de trouver les commandes que le cube peut recevoir et les réponses qu'il peut fournir.

On a déjà vu quelques commandes :

Le sniffing du réseau et le classique essai/erreur permettent d'en trouver quelques autres :

  • "m:" qui modifie les données de la M:aison
  • "z:" qui est envoyé avant un groupe de commandes
  • "n:" qui met le cube en mode apprentissage
  • "x:" annule une commande en cours de type "n:"
  • "d:" et "e:" qui décodent et encodent une chaine binaire (quel algorithme ? mystère)

Comme les lignes reçues, la macrosyntaxe est <lettre de commande>:<enchaînement de champs séparés par des virgules>.

Dans les champs, les données sont soit codées en hexadécimal ou en texte brut (p. exemple : "z:1e,G,02" ) soit encodées partiellement ou totalement en base64 (p. exemple : "s:AAAAiAAAAAPx4AAI=" )

Toutes les commandes que je trouverai seront rajoutées ici au fur et à mesure avec des liens vers chaque description.

dimanche 18 mars 2012

Quelques ordres S: (S12,S20,S21,S22,S23)

J'ai été très occupé ces derniers temps, pas eu trop le temps d'écrire les articles sur d'autres fonctions S:(end) de l'ELV Max!

En voici quelques unes :

ConfigValve (Commande 0x12)

00     00
01     Bitfield : 76543210
                       10 = broadcast (?)
02     12    COMMANDE
03     00
04     00
05     00
06     AABBCC Adresse d'émission
07     ..
08     ..
09     XX     RoomId
10     XX     Configuration du Boost (1)
11     XX     Configuration du cycle de détartrage (2)
12     XX     Position Max de la valve
13     XX     Position Min de la valve

(1) La configuration du Boost se fait sur un octet sous forme de 2 champs de bits :

  • 3 bits pour la durée du Boost en tranche de 5min
  • 5 bits pour l'ouverture de valve en tranche de 5%

(2) Le détartrage se règle lui aussi sur un champ de 8 bits :

  • 3bits pour le jour (0=Samedi, 1=Dimanche... 6=Vendredi)
  • 5bits pour l'heure de mise en route par tranche de 30 minutes

AddDirectLinkFromTo (0x20) et RemoveDirectLinkFromTo (0x21)

00     00
01     Bitfield : 76543210
                       10 = broadcast (?)
02     20/21    COMMANDE
03     00
04     00
05     00
06     AABBCC Adresse d'émission du périphérique référence
07     ..
08     ..
09     AABBCC Adresse d'émission du périphérique de pilotage
10     ..
11     ..
12     XX Type de périphérique

setGroupRFaddr (0x22) et removeGroupRFaddr (0x23)

00     00
01     Bitfield : 76543210
                       10 = broadcast (?)
02     22/23    COMMANDE
03     00
04     00
05     00
06     AABBCC Adresse d'émission du périphérique à ajouter ou retirer de la pièce
07     ..
08     ..
09     XX     RoomId

On a pas fini, il reste encore quelques commandes s:, en particulier le réglage des programmes journaliers (mode 0x10) et le changement de modes (mode 0x40) qui sont incontournables et un peu velus.

lundi 13 février 2012

ELV Max! commande "s:" syntaxe générale et commande de réglage des températures par défaut (0x11)

La commande "s:" sert à envoyer une commande (send en anglais quoi).

Le format général est s:<chaine en base64>

Pour illustrer voici la commande générée par la modification du décalage de température sur un thermostat dont l'adresse est 00fb6d.

s:AAARAAAAAPttACoiPQkJGAM=

Le décodage ramène une chaine binaire (ici en hexa) :

00 00 11 00 00 00 00 fb 6d 00 2a 22 3d 09 09 18 03
#0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #A #B #C #D #E #F #10

Si on décortique, en premier lieu, on trouve tout de suite à partir de #6 une adresse de périphérique.

Une modification du même paramètre fait varier uniquement l'octet #E tandis que le changement d'autres paramètres de température font varier individuellement les autres octets de #A à #10.

Ces valeurs ne sont cependant pas encodées directement. Ainsi une température qui se règle par pas de 0,5° et encodée sous la forme T°x2 et le décalage de température qui peut aller de -3,5 à 3,5 est encodé par dT°x2+7 .

Au final voici le payload de la fonction 11(hex) :

00     00
01     Bitfield : 76543210
                       10 = broadcast (?)
02     11    COMMANDE (ici réglage des températures par défaut)
03     00
04     00
05     00
06     AABBCC Adresse d'émission
07     ..
08     ..
09     XX     RoomId
10     XX     Température de comfort
11     XX     Température éco
12     XX     Température max réglable sur la tête
13     XX     Température min réglable sur la tête
14     XX     Décalage de température
15     XX     Température lorsqu'une fenêtre est ouverte
16     XX     Durée de la consigne de fenêtre ouverte

Le retour de l'envoi d'une telle commande est une ligne "S:"

Celle-ci contient 3 champs séparés par des virgules :

1 : Ce chiffre semble augmenter de temps en temps
2 : Succés/Echec (0/1)
3 : Ce chiffre diminue au maximum de 1 à chaque commande passée, il peut aussi augmenter le maximum est 30(hex) soit 48(dec).

Je pense que les commandes sont envoyées aux têtes par bloc ou par cycles, le champ 1 identifie le bloc courant et le 3 le nombre d'emplacements libres dans ce bloc. C'est pour cela que le champ 3 ne diminue pas toujours ; des commandes sont envoyées en même temps que d'autres sont reçues.

dimanche 5 février 2012

ELV Max! Contenu de la ligne L:ive

A la différence des lignes de C:onfig qui sont aussi nombreuses qu'il y a de périphériques branchés, la ligne L:ive est unique. Tous les périphériques sont regroupés en une seule ligne.

Par ailleurs il n'y a pas d'information sur le cube dans la ligne L:

Interogation du cube

On peut demander une nouvelle ligne L:ive mise à jour par l'envoi de "l:" (L minuscule) suivi de CR+LF Le cube répond alors par une ligne L: contenant les dernières données dont il dispose.

Structure générale d'une ligne L:

La ligne L: ne possède qu'un champ encodé en Base64

par exemple :
L:CwD7bQASGEcpAAAA

Contenu du champ

L'exemple ci-dessus se décode en :

0b 00 fb 6d 00 12 18 47 29 00 00 00

On repère tout de suite les octets 2,3,4 "00fb6d" correspondant à une adresse. Par ailleurs, le premier octet contient 0x0b correspondant au nombre d'octets qui suivent (lorsqu'il y a plusieurs périphériques connectés, on retrouve à nouveau cette même structure <longueur><contenu> répétée autant de fois qu'il y a de périphériques.

On remarque aussi, pas mal d'octets à 0x00, ca va pas nous aider à dépiauter la bêêête mais ça s'arrange après avoir modifier des éléments de config :) .

Position     Champ
0              1 octet  = longueur du morceau de réponse suivant (je n'ai rencontré que des enregistrements de 11 caractères : 0x0b)
1              3 octets = Adresse
4              1 octet  = ? 
5              1 octet  = ? 
6              1 octet  = ? 
                  bits 1-2 = ?
                  bit 3    = Verrouillage clavier
                  bits 4-6 = ?
                  bits 7-8 = Mode
7              1 octet  = Position de la valve (0-100)
8              1 octet  = Température de consigne réglée sur la tête
9-10           2 octets = Date de fin
11             1 octet  = Heure de fin

Les octets 4-6 ne sont pas souvent modifiés par des actions par la webapp ou par modification des réglages de la tête, les seuls bits modifiés de façon synchrone sont sur l'octet 6 (bits 7 et 8) et correspondent au mode (0b00 : mode auto, 0b01 : mode manu, 0b10 : mode temporaire, 0b11 : mode Boost)

Date et heure ne sont valides que lorsqu'on est en mode "temporaire".

ELV Max! Contenu de la config (ligne C:)

La ligne C: se décompose en 2 champs principaux. Outre l'entête "C:", on retrouve le code d'adressage en hexadécimal sur 6 caractères (donc une fois retransformé, sur 24bits) suivi d'une virgule et à nouveau un contenu encodé en Base64.

C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==

Voici donc la ligne correspondant au périphérique 007ead. Dans le cas présent, il s'agit du cube lui-même et je n'en étudierai pas la config tout de suite car peu intéressante, pour le plaisir voici le décodage (les données alphanumériques sont soulignées, le reste est en hexadécimal) :

ED 007EAD 00 09 01 00 IEQ0112240 00 0B 00 04 40 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 0B 00 04 40 00 00 00 00 00 00 00 41 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF http://www.max-portal.elv.de:80/cube 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CET 00 00 0A 00 03 00 00 0E 10 CEST 00 03 00 00 00 00 1C 20

On y découvre entre autre l'URL du backend du portail web (l'adresse du frontend est à http://www.max-portal.elv.de/ ).

Intéressons-nous plutôt aux thermostats.

La config est là-aussi contenue dans un champ encodé en base64. Celle-ci étant particulièrement longue, je vous en fait grâce et je vais me contenter d'en faire le détail :

Position     Champ
0              1 octet  = ?
1              3 octets = Adresse
4              1 octet  = Type de périphérique (0=Cube?, 1=Thermostat)
5              1 octet  = ?
6              10 octets= Numéro de série (IEQXXXXXXX)
16             1 octet  = Température de confort (*)
17             1 octet  = Température Eco (*)
18             1 octet  = Température maximale de réglage (4.5° soit 0x09 = valeur de 'off')
19             1 octet  = Température minimal de réglage (30.5° soit 0x3d = valeur de 'on')
20             1 octet  = Décalage de réglage température (*)
21             1 octet  = Température en cas d'ouverture de fenêtre (*)
22             1 octet  = Durée de changement de consigne en cas d'ouverture de fenêtre (*)
23             1 octet  = bitfield de 8 bits
                3 bits   = durée du Boost (*)
                 5 bits   = valeur de valve du Boost (*)
24             1 octet  = bitfield de 8 bits
                3 bits   = Jour du cycle de détartrage de la valve (*)
                 5 bits   = heure de détartrage de la valve (*)
25             1 octet  = position maximum de la valve ? (255) peut-être dépendant du réglage initial de course
26             1 octet  = position de départ de la valve ? (0) peut-être dépendant du réglage initial de course
27             début des programmes journaliers (7 groupes = 1 par jour) (*)
(*) les valeurs sont modifiables depuis la webapp

Les températures sont exprimées en multiples de 0,5° (Température = Valeur/2)

La liste des jours commence le Samedi(=0 ???) jusqu'au Vendredi (=7)

Le décalage de température est exprimé en multiples de 0,5° à ajouter à -3,5° (Décalage = Valeur/2 - 3.5)

La durée du boost se calcule donc par Durée = (Valeur & 0xE0)>>5 et la valeur de valve par Valve = (Valeur & 0x1F)

Idem pour le détartrage : Jour = (Valeur & 0xE0)>>5 et Heure = (Valeur & 0x1F)

Un programme journalier est constitué de 26 octets, 13 blocs de 2 octets pour être plus précis soit 13 paliers programmables par jour. Sur ses 16bits (composant les 2 octets MSB et LSB), sont encodées 2 grandeurs : la température de consigne et l'heure de fin.

0TTTTTTH.HHHHHHHH

La Température est à nouveau exprimée en multiple de 0,5 tandis que l'heure est exprimée en multiple de 5 minutes

Donc partant du principe qu'on lit les octets un par un, on a :

Température = ((MSB & 0x7E)>>1)/2
Heure de fin = ((MSB & 0x01)*256+LSB)*0.5

Il me reste donc 2 champs dont je n'arrive pas à comprendre la signification (0 et 5).

Demander une ligne de C:onfig

Il est possible de demander la ligne de configuration d'un périphérique spécifique si on connait son adresse.

Pour cela il faut envoyer la commande "c:" suivie de l'adresse en hexadécimal par exemple (terminer par CR+LF) :

c:007ead
C:007ead,<........................>

Le résultat est la ligne C: telle qu'on peut la voir en haut de l'article. Si l'adresse est inconnue, il n'y a pas de réponse.

Méthodologie

La méthode pour repérer tout cela est principalement de lancer depuis l'interface web des commandes unitaires puis de récupérer la configuration immédiatement après afin d'isoler les différences et d'en tirer une signification.

Pour les champs non modifiables (température maxi ou min), il faut faire des essais ("si c'était une température, si je divise par 2 est-ce que ca donne une valeur qui a du sens ?") éventuellement avec le manuel pas loin

samedi 28 janvier 2012

J'ai découvert une commande de plus sur ELV Max!, ben j'aurais préféré m'en passer... :)

Alors que je bidouillais le Cube via netcat, j'ai lancé quelques commandes de la forme <lettre><:><cr><lf>

Et bien, ca m'a permis de découvrir à mon corps défendant la commande "a:" que l'on peut désormais surnommer "Reset sauvage de toute les métadonnées".

4 petits caractères suffisent à ramener le cube dans un état immaculé :

H:IEQ0112240,007ead,0109,00000000,2ee8c053,00,32,0c011c,0c2b
M:
C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==
L:

On voit le champ M: vide, l'absence de données L:ive et une seule ligne de config pour le Cube lui-même...

La bonne nouvelle, c'est qu'après avoir fait le réapprentissage d'un thermostat, il semble que la config soit retrouvée (retéléchargée du la tête ?)

H:IEQ0112240,007ead,0109,00000000,233903cd,04,32,0c011c,0d04
M:00,01,VgIBAQZCdXJlYXUA+20BAQD7bUlFUTAxODQ5OTkHQnVyZWF1MQEB
C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==
C:00fb6d,0gD7bQEBFP9JRVEwMTg0OTk5KiI9CQcYAzAM/wBESFUIRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERIVQhFIEUgRSBFIEUgRSBFIEUgRSBFIEUgREhUbETMVRRFIEUgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIERIVGxEzFUURSBFIEUgRSBFIEUgRSBFIEUgREhUbETMVRRFIEUgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIA==
L:CwD7bQASGEcpAAAA

On peut noter au passage que le champ 6 de H: a changé (00 -> 04) mais je ne sais pas pourquoi..

vendredi 27 janvier 2012

ELV MAX! Lignes Host (H:) et Maison (M:)

Revenons à l'étude de la réponse initiale du Cube Max!

Le format le plus global est :

  • un ensemble de lignes commençant toutes par une lettre suivie d'un "deux points" lui même suivi d'un contenu
  • chaque ligne est terminée par un marqueur assez classique : cr/lf (carriage return/line feed)

Voici ce que j'ai pu tirer pour l'instant des lignes H et M

H:

Contient des données très basiques sur le système : Les champs du contenu sont séparés par des virgules

H:IEQ0112240,007ead,0109,00000000,35e2322f,00,32,0c011b,0909

que l'on peut découper en :

  • IEQ0112240 = numéro de série du Cube (invariant dans la même installation, il est imprimé sous le cube), format alphanumérique
  • 007ead = nombre constant (on le retrouve ailleurs sur la première ligne C:, on le verra plus tard), c'est donc d'une certaine manière un moyen d'adressage, format hexadécimal sur 3 octets
  • 0109 = la version du microcode embarqué a priori (le code a changé après une mise à jour)
  • 00000000 = euh comment dire... des zéros ?
  • 35e2322f = un nombre variant totalement à chaque connexion, probablement un identifiant de connexion mais on ne le retrouve nulle par ailleurs, format hexadécimal sur un long (32bits)
  • 00 = encore des 0... impossible d'en savoir la signification
  • 32 = toujours 32 là aussi... impossible d'en tirer une conclusion
  • 0c011b = là aussi un invariant
  • 0909 = Est-ce que ca ne serait pas 9 heures 09 (si c'est le cas, le cube n'est pas à l'heure :) ), à voir lorsqu'on passera

M:

M:00,01,VgIHAQdDdWlzaW5lAP4uAgtTYWxsZSBkJ2VhdQD99QMNQ2hhbWJyZSBMdWNhcwCWrAQTQ2hhbWJyZSBGcmVkIExvdWxvdQCZbwUGQnVyZWF1APttBg1TYWxsZSBkZSBiYWluAPx4BwVTYWxsZQCWkgcBAP4uSUVRMDE4NDgxMgdDdWlzaW5lAQEA/fVJRVEwMTg0NzQ0C1NhbGxlIGQnZWF1AgEAlqxJRVEwMTg2MTYyDUNoYW1icmUgTHVjYXMDAQCZb0lFUTAxODMzMTcTQ2hhbWJyZSBGcmVkIExvdWxvdQQBAPttSUVRMDE4NDk5OQZCdXJlYXUFAQD8eElFUTAxODUxNjYNU2FsbGUgZGUgYmFpbgYBAJaSSUVRMDE4NjExNw9TYWxsZSDDoCBtYW5nZXIHAQ==

La ligne M: là aussi contient des champs séparés par des virgules. Et là aussi les 2 premiers sont invariants d'une connexion à l'autre (toujours 00 et 01) Suit un champ beaucoup plus long qui semble codé mais on note qu'on a affaire à des caractères tous "imprimables" et qu'en fin de ligne on retrouve des "=" typiques du remplissage final en base64

Si on décode ce 3ème champ comme du base64 on récupère en effet un contenu contenant des éléments reconnaissables et cohérents (les caractères non imprimables ont été supprimés) :

V(...)Cuisine(...)Salle d'eau(...)Chambre Lucas(...)Chambre Fred Loulou(...)Bureau(...)Salle de bain(...)Salle(...)IEQ0184812 Cuisine(...)IEQ0184744 Salle d'eau(...)IEQ0186162 Chambre Lucas(...)IEQ0183317 Chambre Fred Loulou(...)IEQ0184999 Bureau(...)IEQ0185166 Salle de bain(...)IEQ0186117 Salle à manger(...)

Dans ce contenu binaire on peut retrouver une certaine organisation : Il y a 3 sous-ensembles.


** un préambule de 2 octets au contenu inconnu
** une structure décrivant les pièces (organisation logique)
** une structure décrivant les périphériques (organisation physique)

Format de la liste des pièces

Le premier octet contient le nombre de pièces définies (roomCount). A sa suite, on retrouve répétée roomCount fois une structure définissant une pièce :

  • Nombre de caratères du nom de la pièce (1 octet)
  • Nom de la pièce (X octets cf supra)
  • ID de la pièce (1 octet)
  • 3 octets dont le contenu ressemble au champ qualifié d'adressage sur la ligne H:, mais il ne semble pas utilisé (ID est utilisé ensuite)

Immédiatement après la liste des pièces on attaque la liste des périphériques (thermostats) Le principe est le même que la liste des pièces.

Format de la liste des périphériques

Le premier octet contient le nombre de périphériques définis (devCount).

La aussi on retrouve devCount fois une structure de périphérique :

  • Type de périphérique (1 octet) 0=Cube, 1=Tête thermostatique, peut-être y en a t'il d'autres pour par exemple le thermostat mural (mais je n'en ai pas)
  • 3 octets "d'adressage", le contenu de ce champ se retrouve comme premier champ des lignes C: suivantes permettant de les rattacher à un périphérique
  • 10 octets de numéro de série
  • 1 octet de nombre de caractères du nom du périphérique
  • Nom du périphérique (X octets ci-dessus)
  • ID de la pièce de rattachement (1 octet)

Voilà, avec la ligne M: on peut construire la structure de notre maison.

La prochaine fois, je m'attaque à la ligne C: qui donne la config courante d'un périphérique.

mardi 24 janvier 2012

Domotiqueuh tiqueuh tiqueh

Non, je ne me transforme pas en Soeur sourire mais depuis quelques mois j'avais mis en place des corps thermostatiques sur certains des radiateurs de la maison et en ce début d'année, j'y ai installé les têtes thermostatisques adaptées