Après avoir découvert NodeRed, je me suis essayé à quelques petits tests avec ma Freebox pour visualiser (pour l’instant uniquement dans le debug de nodered) un appel manqué. Voici le code :
[code]
[{”id”:”ba386057.845d3″,”type”:”mqtt-broker”,”broker”:”localhost”,”port”:”1883″},{”id”:”9c3da036.63c26″,”type”:”inject”,”name”:”Every minute”,”topic”:”",”payload”:”",”payloadType”:”date”,”repeat”:”60″,”crontab”:”",”once”:true,”x”:91,”y”:693,”z”:”ca1c08b.f35e3f8″,”wires”:[[”115c3290.eea3cd”]]},{”id”:”21a282c3.de5d7e”,”type”:”http request”,”name”:”FBX list calls”,”method”:”GET”,”url”:”http://mafreebox.freebox.fr/api/v3/call/log/”,”x”:572,”y”:693,”z”:”ca1c08b.f35e3f8″,”wires”:[[”71994ed2.8e66b”]]},{”id”:”fa122b16.05edd8″,”type”:”http request”,”name”:”register as FBX app request”,”method”:”POST”,”url”:”http://mafreebox.freebox.fr/api/v3/login/authorize/”,”x”:425,”y”:179,”z”:”ca1c08b.f35e3f8″,”wires”:[[”fdad563e.0252a8″]]},{”id”:”fb076d40.04f89″,”type”:”function”,”name”:”process FBX challenge”,”func”:”var app_token = context.global.fbx_app_token\n\nvar text = msg.payload.result.challenge;\nvar key = app_token;\nvar algorithm = ’sha1′;\nvar hash, hmac;\n\nhmac = context.global.crypto.createHmac(algorithm, key);\n\n// change to ‘binary’ if you want a binary digest\nhmac.setEncoding(’hex’);\n\n// write in the text that you want the hmac digest for\nhmac.write(text);\n\n// you can’t read from the stream until you call end()\nhmac.end();\n\n// read out hmac digest\nhash = hmac.read(); \n\nvar newMsg = {payload: {’app_id’:'fr.freebox.node’, ‘password’:hash}};\nreturn newMsg;”,”outputs”:1,”x”:920,”y”:546,”z”:”ca1c08b.f35e3f8″,”wires”:[[”bb518ba4.44ae78″]]},{”id”:”5460e78e.ab9f18″,”type”:”function”,”name”:”Build FBX register app payload”,”func”:”msg.payload = {\n \”app_id\”: \”fr.freebox.node\”,\n \”app_name\”: \”Freebox node\”,\n \”app_version\”: \”0.0.1\”,\n \”device_name\”: \”NodeRed Raspi Server\”\n}\nreturn msg;”,”outputs”:1,”x”:265,”y”:227,”z”:”ca1c08b.f35e3f8″,”wires”:[[”fa122b16.05edd8″]]},{”id”:”6b24c3ad.94db3c”,”type”:”inject”,”name”:”Register FBX app”,”topic”:”",”payload”:”",”payloadType”:”date”,”repeat”:”",”crontab”:”",”once”:false,”x”:120,”y”:174,”z”:”ca1c08b.f35e3f8″,”wires”:[[”5460e78e.ab9f18″]]},{”id”:”d2a49edb.2d5b6″,”type”:”function”,”name”:”Handle FBX app registration”,”func”:”var token = msg.payload.result.app_token;\nvar track_id = msg.payload.result.track_id;\n\nvar newMsg1 = { payload: {’track_id’: track_id, ‘app_token’: token}};\nvar newMsg2 = { payload: {’track_id’: track_id}, \”url\”: \”http://mafreebox.freebox.fr/api/v3/login/authorize/\”+track_id};\nreturn [newMsg1, newMsg2];\n”,”outputs”:”2″,”x”:702,”y”:177,”z”:”ca1c08b.f35e3f8″,”wires”:[[”7d297e32.82d68″],[”6981c0b7.967e4″]]},{”id”:”6a03c634.95fc38″,”type”:”inject”,”name”:”TEST: emulate FBX resp”,”topic”:”",”payload”:”{\”success\”:true,\”result\”:{\”app_token\”:\”gP1sh0M7SsKDyXZipuktIXU1uU1W\\/wTCUTq9JJRk4bO4wsS3X4EY9xkK5XRGIz\\/J\”,\”track_id\”:1}}”,”payloadType”:”string”,”repeat”:”",”crontab”:”",”once”:false,”x”:136,”y”:304,”z”:”ca1c08b.f35e3f8″,”wires”:[[”fdad563e.0252a8″]]},{”id”:”fdad563e.0252a8″,”type”:”json”,”name”:”",”x”:548,”y”:225,”z”:”ca1c08b.f35e3f8″,”wires”:[[”d2a49edb.2d5b6″]]},{”id”:”29f6c093.d6094″,”type”:”comment”,”name”:”TODO”,”info”:”Construction dynamique de l’URL d’api de la FBX selon la doc de l’API”,”x”:77,”y”:72,”z”:”ca1c08b.f35e3f8″,”wires”:[]},{”id”:”736aa740.8c9558″,”type”:”function”,”name”:”Load FBX credential “,”func”:”context.global.fbx_app_token = msg.payload.app_token;\ncontext.global.fbx_app_id = msg.payload.track_id;\n\nreturn msg;”,”outputs”:1,”x”:341,”y”:551,”z”:”ca1c08b.f35e3f8″,”wires”:[[”1915c02e.e6ea4″]]},{”id”:”1915c02e.e6ea4″,”type”:”delay”,”name”:”",”pauseType”:”delay”,”timeout”:”4″,”timeoutUnits”:”seconds”,”rate”:”1″,”rateUnits”:”second”,”randomFirst”:”1″,”randomLast”:”5″,”randomUnits”:”seconds”,”drop”:false,”x”:518,”y”:551,”z”:”ca1c08b.f35e3f8″,”wires”:[[”6301246f.9cfedc”]]},{”id”:”6981c0b7.967e4″,”type”:”http request”,”name”:”Get app status”,”method”:”GET”,”url”:”",”x”:830,”y”:235,”z”:”ca1c08b.f35e3f8″,”wires”:[[”b1e9cc85.4e163″]]},{”id”:”c7df6777.382098″,”type”:”function”,”name”:”Check app status”,”func”:”context.count = context.count || 0; \ncontext.count += 1;\n\nvar status = false;\nif (msg.payload.result.status == ‘granted’) {\n\tstatus = true;\n}\n\nvar newMsg = {payload: status, ‘track_id’: msg.track_id, ‘url’ : msg.url};\n\nif (status == false){\n if (context.count >= 20) {\n \treturn [null, null];\n }\n return [null, newMsg];\n}\nreturn [newMsg, null];”,”outputs”:”2″,”x”:1035,”y”:236,”z”:”ca1c08b.f35e3f8″,”wires”:[[”47be3f58.b841c”],[”ec0c4cf1.13f3b”]]},{”id”:”b1e9cc85.4e163″,”type”:”json”,”name”:”",”x”:922,”y”:174,”z”:”ca1c08b.f35e3f8″,”wires”:[[”c7df6777.382098″]]},{”id”:”47be3f58.b841c”,”type”:”mqtt out”,”name”:”FBX app registration”,”topic”:”/freebox/app_registered”,”broker”:”ba386057.845d3″,”x”:1283,”y”:229,”z”:”ca1c08b.f35e3f8″,”wires”:[]},{”id”:”d5fb8149.2a048″,”type”:”debug”,”name”:”",”active”:false,”console”:false,”complete”:false,”x”:1288,”y”:487,”z”:”ca1c08b.f35e3f8″,”wires”:[]},{”id”:”ec0c4cf1.13f3b”,”type”:”delay”,”name”:”",”pauseType”:”delay”,”timeout”:”15″,”timeoutUnits”:”seconds”,”rate”:”1″,”rateUnits”:”second”,”randomFirst”:”1″,”randomLast”:”5″,”randomUnits”:”seconds”,”drop”:false,”x”:893,”y”:342,”z”:”ca1c08b.f35e3f8″,”wires”:[[”6981c0b7.967e4″]]},{”id”:”7d297e32.82d68″,”type”:”file”,”name”:”FBX credential write”,”filename”:”FBX_credential.json”,”appendNewline”:true,”overwriteFile”:true,”x”:937,”y”:132,”z”:”ca1c08b.f35e3f8″,”wires”:[]},{”id”:”d21d17bf.2de2e8″,”type”:”mqtt in”,”name”:”FBX app registration”,”topic”:”/freebox/app_registered”,”broker”:”ba386057.845d3″,”x”:110,”y”:485,”z”:”ca1c08b.f35e3f8″,”wires”:[[”cae27487.351d88″]]},{”id”:”cae27487.351d88″,”type”:”file in”,”name”:”FBX credential read”,”filename”:”FBX_credential.json”,”format”:”utf8″,”x”:327,”y”:485,”z”:”ca1c08b.f35e3f8″,”wires”:[[”c837c8c4.37c838″]]},{”id”:”c837c8c4.37c838″,”type”:”json”,”name”:”",”x”:504,”y”:485,”z”:”ca1c08b.f35e3f8″,”wires”:[[”736aa740.8c9558″]]},{”id”:”5668da1f.a99724″,”type”:”tail”,”name”:”FBX credential read”,”split”:false,”filename”:”FBX_credential.json”,”x”:112,”y”:428,”z”:”ca1c08b.f35e3f8″,”wires”:[[”c837c8c4.37c838″]]},{”id”:”6301246f.9cfedc”,”type”:”http request”,”name”:”FBX get challenge”,”method”:”GET”,”url”:”http://mafreebox.freebox.fr/api/v3/login/”,”x”:685,”y”:551,”z”:”ca1c08b.f35e3f8″,”wires”:[[”f617db7f.09e828″]]},{”id”:”f617db7f.09e828″,”type”:”json”,”name”:”",”x”:788,”y”:496,”z”:”ca1c08b.f35e3f8″,”wires”:[[”fb076d40.04f89″]]},{”id”:”bb518ba4.44ae78″,”type”:”http request”,”name”:”FBX get session”,”method”:”POST”,”url”:”http://mafreebox.freebox.fr/api/v3/login/session/”,”x”:1044,”y”:493,”z”:”ca1c08b.f35e3f8″,”wires”:[[”27d1bdde.d82e42″]]},{”id”:”ef3caff.f10c35″,”type”:”function”,”name”:”FBX Save session token”,”func”:”if (msg.payload.success) {\n context.global.fbx_session_token = msg.payload.result.session_token;\n return null; \n} else {\n return msg;\n}\n”,”outputs”:1,”x”:940,”y”:613,”z”:”ca1c08b.f35e3f8″,”wires”:[[”1f516669.e0ae9a”]]},{”id”:”27d1bdde.d82e42″,”type”:”json”,”name”:”",”x”:1163,”y”:549,”z”:”ca1c08b.f35e3f8″,”wires”:[[”ef3caff.f10c35″,”d5fb8149.2a048″]]},{”id”:”115c3290.eea3cd”,”type”:”function”,”name”:”FBX api build authenticated header”,”func”:”var newMsg = {payload:'’, headers:{’X-Fbx-App-Auth’:context.global.fbx_session_token}};\nreturn newMsg;”,”outputs”:1,”x”:328,”y”:693,”z”:”ca1c08b.f35e3f8″,”wires”:[[”21a282c3.de5d7e”]]},{”id”:”67ac6d79.985394″,”type”:”comment”,”name”:”Get calls list”,”info”:”",”x”:90,”y”:637,”z”:”ca1c08b.f35e3f8″,”wires”:[]},{”id”:”1f516669.e0ae9a”,”type”:”delay”,”name”:”",”pauseType”:”delay”,”timeout”:”2″,”timeoutUnits”:”seconds”,”rate”:”1″,”rateUnits”:”second”,”randomFirst”:”1″,”randomLast”:”5″,”randomUnits”:”seconds”,”drop”:false,”x”:1153,”y”:613,”z”:”ca1c08b.f35e3f8″,”wires”:[[”fb076d40.04f89″]]},{”id”:”71994ed2.8e66b”,”type”:”json”,”name”:”",”x”:726,”y”:693,”z”:”ca1c08b.f35e3f8″,”wires”:[[”82b4ade7.7d4b5″]]},{”id”:”82b4ade7.7d4b5″,”type”:”function”,”name”:”FBX call : new call ?”,”func”:”var calls = msg.payload.result;\n\nfor (var i=0; i
Ma télé n’étant pas un modèle très récent (comprendre écran cathodique de presque 10 ans), elle ne bénéficie pas de technos comme HDMI CEC (à vérifier) qui permettent de mettre en veille automatiquement plusieurs appareils en même temps.
C’est moche…
Or ma télé est connectée au Freebox Player et à un petit lecteur DVD (via la péritel) qui permet d’avoir un son acceptable. Le but est donc de trouver un moyen d’allumer et d’éteindre ces 3 appareils avec le moins d’actions possibles. Après quelques tests via le port USB du Freebox Player et un petit paramétrage de la gestion de l’énergie, il est possible d’obtenir les 5V du connecteur USB lorsque le player est allumé (et uniquement à ce moment là). Donc plusieurs solutions envisageables :
- utilisation d’un/deux relais pour alimenter la TV et le lecteur DVD directement pilotés par l’alim USB
- utilisation d’un ATtiny (ou autre) pour gérer en plus des relais, l’envoi du code IR qui va bien pour basculer le lecteur DVD en mode Péritel
- utilisation d’un ATtiny pour gérer les relais, diffuser un signal IR pour le lecteur DVD et une implémentation software USB HID pour émuler une navigation dans le menu du Freebox Player pour lancer automatiquement la TV ou autre (l’idée étant de lancer cette séquence d’émulation d’appuis sur les touches du clavier après la phase d’énumération…)
- utilisation d’un ATtiny (si toujours suffisant) pour gérer les relais, diffuser un signal IR pour le lecteur DVD, émuler des appuis claviers pour automatiser la navigation dans le Freebox Player et envoyer un signal (433MHz ?) qui pourrait servir à éteindre la chaine HiFi si elle est en fonctionnement (dans la même pièce, mais à l’opposé), cette opération nécessiterait une intervention dans la chaine : intégration d’un module de réception 433Mhz et d’un ATtiny, idéalement alimentés uniquement lorsque la chaine n’est pas en veille, et qui émuleraient (via un transistor) un appui sur le bouton de veille lors de la réception du signal paramétré…
Une très grosse source d’informations sur le sujet : http://nathan.chantrell.net/20121014/tinypcremote-an-attiny85-based-infrared-pc-remote-control/
1. Récupérer via Arduino le signal IR émis par la télécommande pour basculer le lecteur DVD en mode péritel (via https://github.com/nathanchantrell/TinyPCRemote/tree/master/TinyPCRemote_CodeReader)
–> Code for this button: 3225320451
2. Test de la reconnaissance par le Freebox Player du périphérique HID keyboard implémenté sur l’arduino en utilisant vusb for arduino et le sketch suivant :
#include “UsbKeyboard.h”
// IR sensor connected to PB4 = ATtiny85 physical pin 3
#define IRpin_PIN PIND
#define IRpin 0
#define MAXPULSE 5000 // max IR pulse length, default 5 milliseconds
#define NUMPULSES 100 // max IR pulse pairs to sample
#define RESOLUTION 2 // time between IR measurements
uint16_t pulses[NUMPULSES][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we’re storing
void setup() {
pinMode(0, INPUT);
}
void loop() {
//UsbKeyboard.update();
unsigned long irCode=listenForIR(); // Wait for an IR Code
// Process the pulses to get our code
for (int i = 0; i < 32; i++) {
irCode=irCode<<1;
if((pulses[i][0] * RESOLUTION)>0&&(pulses[i][0] * RESOLUTION)<500) {
irCode|=0;
} else {
irCode|=1;
}
}
// —————————————————————————————
// Enter IR codes and keystrokes to send below, see keyboard_commands.txt for list of keys
// —————————————————————————————
if (irCode==3225320451) { // Single character example, “1″
UsbKeyboard.sendKeyStroke(KEY_ENTER);
irCode = 0;
for (int i = 0; i < NUMPULSES; i++) {
pulses[i][0] = 0;
pulses[i][1] = 0;
}
// delay(2000);
}
} // loop end
// IR receive code
int listenForIR() {
currentpulse = 0;
while (1) {
unsigned int highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & _BV(IRpin)) { // got a high pulse
UsbKeyboard.update(); // needs to be called often
highpulse++;
delayMicroseconds(RESOLUTION);
if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][0] = highpulse;
while (! (IRpin_PIN & _BV(IRpin))) { // got a low pulse
UsbKeyboard.update(); // needs to be called often
lowpulse++;
delayMicroseconds(RESOLUTION);
if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][1] = lowpulse;
currentpulse++;
}
}
Ayant eu des soucis il y a quelques années lorsque j’avais testé VUSB avec différentes versions de noyaux linux, je m’attendais à beaucoup tatonner… Que nenni : la reconnaissance en tant que HID se fait parfaitement (aux mauvais contacts de la breadboard près…) et le petit sketch permet de m’assurer que tout fonctionne correctement sur des ordi et sur le FBx Player. Je suis parti, pour ce sketch de test, du TinyPCRemote_ATtiny85 de Nathan Chantrell, que j’ai du modifier un peu (reset de pulses[][]), faute de quoi, sur un ordi et le FBx Player, après un seul appui sur la télécommande, le caractère “RETURN” était envoyé de multiple fois.
Donc pour le moment je suis capable :
- de savoir quel code IR envoyer au lecteur DVD pour commuter en péritel
- d’envoyer des codes de touche clavier au Freebox Player pour naviguer dans les menus
A suivre…
Pour avoir une trace des différentes manips effectuées tout au long de l’install des différents composants.
Point de départ / Pré-requis :
- une install toute fraiche Ubuntu 8.04 - Hardy Heron - (sortie en avril 2008).
- connection internet OK (merci Ubuntu pour la simplicité de mise en oeuvre de cartes WiFi aux drivers douteux…)
Objectif #1 : installation svn
Le but est d’avoir un serveur svn de test (comprendre : “pas un serveur de prod”), pour ensuite installer Trac et permettre la connection au serveur svn (en ssh + svn ?) depuis l’extérieur, et si possible un peu plus secure que juste via http.
- Installation des packages subversion et subversion-tools (et de leur dépendances) depuis les dépots officiels.
- Installation Trac (et de ses dépendances) depuis les dépots officiels.
- Installation MySql… (package mysql-server en version 5.0 au moment de l’install)
Configuration de subversion (cf ce lien) :
- Création d’un repository : svnadmin create /chemin/du/repository
- Ajout du script pour automatiser le lancement du serveur svn : /etc/init.d/svnserve
- Ajout d’un user:group dédié à l’administration subversion :
sudo addgroup svn –system
sudo adduser svn –system –home /votre/répertoire/svn –no-create-home –ingroup svn
sudo chown -R svn: /votre/répertoire/svn
- Développement d’un script de backup automatique basé sur la commande : svnadmin dump /path/to/repository/ > .svn_repos.20080620
- Gestion des droits utilisateurs :
- Intégration de scripts subversion à Nautilus :
installation du paquet nautilus-script-collection-svn
nautilus-script-manager enable Subversion
nautilus –restart
Configuration de Trac (cf ici, ici et ici ) :
- sudo aptitude install trac
- sudo mkdir ~/trac (répertoire contenant les instances de trac)
- sudo chown -R www-data:www-data ~/trac
- Création d’une instance Trac
- sudo trac-admin ~/trac/monprojet initenv
- installation easy_install
wget http://peak.telecommunity.com/dist/ez_setup.py sudo python ez_setup.py
- installation du plugin webadmin
easy_install http://svn.edgewall.com/repos/trac/sandbox/webadmin/
- Ajout dans le trac.ini de chaque projet de la section
[components]
webadmin.* = enabled
Configuration d’apache
- sudo aptitude install apache2 libapache2-modpython
- condfiguration des ports en écoute /etc/apache2/ports.conf
- Fichier de description du site trac : /etc/apache2/sites-available/trac
- a2ensite trac