Un nouveau jouet
Je me suis procuré récemment un Avocent SPC810. Waah ça en jette comme ça ! Mais… c’est quoi ? C’est un appareil qui permet de gérer la puissance d’équipements dans un datacenter. Il possède 8 prises et on peut par exemple éteindre et allumer 8 serveurs à distance. Pour la gestion, on peut nommer des ports, leur donner un état au démarrage (“lorsque le courant revient, j’allume ce port ou le laisse éteint ?”), voir le courant total consommé mais aussi créer des utilisateurs, donner des droits d’accès à des utilisateurs sur des ports,…
Pour se connecter dessus, on utilise un port série en RS232 qui le plus souvent se trouve sur une prise DB-9. Or ici, comme c’est de coutume dans les datacenter, ils n’utilisent pas de prises DB-9, mais des câbles RJ45 pour causer en série. Les appareils récent font tout en IP via le réseau de gestion du datacenter. Le fabricant de cet appareil a prévu de vendre un appareil (chez Avocent ils appellent ça un CPS) qui fait du “serial over IP” : d’un côté de ce boîtier CPS il y a du réseau RJ45, de l’autre des ports Serial RJ45. Ce qui est fun avec ces gens qui font du série en RJ45 (Avocent, Cisco et d’autres) c’est qu’ils ne se sont pas mis d’accord pour le pinout. Un ami m’a aidé après un peu de trial and error à retrouver le pinout, et on a pu fabriquer un adaptateur DB9-RJ45 spécifique que je peux planter dans un port série DB9-USB sur le PC.
Infrared Power
Voilà mon idée avec ce machin : dans ma chambre, j’ai une télécommande infrarouge qui commande une lampe RGB autour de mon lit et ma lampe de chevet ( c’est basé sur ce projet, je ne vais pas y revenir en détails ). But : utiliser la même télécommande pour d’autres appareils dans ma chambre comme l’éclairage de mon bureau.
Et pour ce faire, je vais utiliser… un Banana Pi que j’ai sous la main. Le Banana Pi est un clone du Raspberry Pi original mais sous stéroïdes. A l’heure actuelle, il est un peu dépassé mais il possède un capteur infrarouge. Je vais m’en servir pour envoyer des commandes au SPC810.
Configuration de l’infrarouge sur le Banana Pi
Pour commencer, on vérifie que le capteur IR est reconnu sur le Banana Pi :
cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0100 N: Name="sunxi-ir" P: Phys=RemoteIR/input1 S: Sysfs=/devices/virtual/input/input0 U: Uniq= H: Handlers=sysrq rfkill kbd event0 B: PROP=0 B: EV=3 B: KEY=ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
On voit une référence à event0, on se référera par la suite à ce capteur via : /dev/input/event0
Pour trouver une télécommande qui est reconnue (là c’est la loterie mais en général ça fonctionne) on utilise evtest :
apt-get install evtest
evtest /dev/input/event0
Input driver version is 1.0.1 Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 Input device name: "sunxi-ir" Supported events: [...] Properties: Testing ... (interrupt to exit) Event: time 1457262850.435187, type 1 (EV_KEY), code 5 (KEY_4), value 1 Event: time 1457262850.435194, -------------- EV_SYN ------------ Event: time 1457262850.686531, type 1 (EV_KEY), code 5 (KEY_4), value 0 Event: time 1457262850.686536, -------------- EV_SYN ------------ Event: time 1457262852.554246, type 1 (EV_KEY), code 9 (KEY_8), value 1 Event: time 1457262852.554255, -------------- EV_SYN ------------ Event: time 1457262852.796536, type 1 (EV_KEY), code 9 (KEY_8), value 0 Event: time 1457262852.796542, -------------- EV_SYN ------------
So far so good, il reconnait des touches de ma télécommande ! Installons lirc qui va s’occuper le lire et décoder les signaux de la télécommande :
apt-get install lirc
Edition de /etc/lirc/hardware.conf pour qu’il ressemble à :
# /etc/lirc/hardware.conf # # Arguments which will be used when launching lircd LIRCD_ARGS="" #Don't start lircmd even if there seems to be a good config file #START_LIRCMD=false #Don't start irexec, even if a good config file seems to exist. #START_IREXEC=false #Try to load appropriate kernel modules LOAD_MODULES=true # Run "lircd --driver=help" for a list of supported drivers. DRIVER="devinput" # usually /dev/lirc0 is the correct setting for systems using udev DEVICE="/dev/input/event0" #MODULES="sunxi-ir" # Default configuration files for your hardware if any LIRCD_CONF="" LIRCMD_CONF=""
Maintenant il faut configurer LIRC avec cette télécommande spécifique. Il existe une BDD de télécommandes du marché avec LIRC mais la mienne n’y figure pas, je configure quelques touches à la main. Je récupère pour commencer la configuration d’une télécommande générique :
wget http://lirc.sourceforge.net/remotes/generic/NEC.conf
Puis je lance irrecord qui est l’utilitaire de configuration :
irrecord -H devinput -d /dev/input/event0 NEC.conf
Après avoir identifié quelques touches, je me retrouve avec un fichier NEC.conf.conf (sic) qui contient des trucs du genre :
KEY_POWER2 0x01000900000001 0x00000000000000 KEY_POWER 0x01000500000001 0x00000000000000 KEY_F10 0x01000E00000001 0x00000000000000 KEY_F11 0x01001200000001 0x00000000000000 KEY_F12 0x01000A00000001 0x00000000000000
J’enlève à la main le deuxième code 0x00000000000000 et enregistre sous le nom /etc/lirc/lircd.conf
J’édite le fichier /etc/lirc/lircrc, c’est lui qui enverra les signaux vers mon script python plus tard. Je crée des blocs du style pour chaque touche que je compte utiliser :
begin prog = myProg button = KEY_F10 config = key1 repeat = 0 end
Voilà, lirc est configuré, on peut le redémarrer pour appliquer les changements :
service lirc restart
Test avec irw :
irw 0001000e00000001 00 KEY_F10 rgbremote 0001001200000001 00 KEY_F11 rgbremote 0001000a00000001 00 KEY_F12 rgbremote 0001000900000001 00 KEY_POWER2 rgbremote 0001000500000001 00 KEY_POWER rgbremote
Yay ! Passons à la partie Python qui fera le lien entre la télécommande et SPC810
Python, IR et Série
Python discute avec l’IR par le biais de la librairie pylirc :
apt-get install python-pylirc
et discute en série via le module PySerial.
Pour utiliser le serial, je branche mon adaptateur serial dans l’USB et regarde ce que me dit dmesg :
[ 15.738687] usbserial: USB Serial Driver core [ 15.781537] usbcore: registered new interface driver ftdi_sio [ 15.809006] USB Serial support registered for FTDI USB Serial Device [ 15.830876] ftdi_sio 4-1:1.0: FTDI USB Serial Device converter detected [ 15.850186] usb 4-1: Detected FT232BM [ 15.864004] usb 4-1: Number of endpoints 2 [ 15.878486] usb 4-1: Endpoint 1 MaxPacketSize 64 [ 15.893360] usb 4-1: Endpoint 2 MaxPacketSize 64 [ 15.908012] usb 4-1: Setting MaxPacketSize 64 [ 15.928439] usb 4-1: FTDI USB Serial Device converter now attached to ttyUSB0 [ 15.947323] ftdi_sio: v1.6.0:USB FTDI Serial Converters Driver
ah, il faudra donc utiliser le port /dev/ttyUSB0
Bon, on a enfin tout configuré, l’infrarouge, le serial, installé les librairies il est temps de pondre un petit code qui fait le lien entre tout ça :
import pylirc import serial import time LSonAllume = False LBureauAllume = False sonAllume = False # #initialisation du serial # ser = serial.Serial( port='/dev/ttyUSB0', baudrate=9600, parity=serial.PARITY_ODD, stopbits=serial.STOPBITS_TWO, bytesize=serial.SEVENBITS ) ser.close() ser.open() if ser.isOpen(): print 'Serial connection done...' # #initialisation de l'infrarouge # pylirc.init("myProg","/etc/lirc/lircrc") def read(): out = '' while ser.inWaiting() > 0: out += ser.read(1) print out return out def login(): ser.write('\r\r') time.sleep(1) read() #login par défaut, j'attends le hacker #qui rentre dans ma chambre, se branche sur #le SPC, éteint la lumière et repart en ricanant ser.write('Admn\r') time.sleep(0.5) read() ser.write('admn\r') time.sleep(0.5) read() def toggleLSon(): global LSonAllume if LSonAllume: ser.write('off port lson\r') else: ser.write('on port lson\r') time.sleep(0.5) read() LSonAllume = not LSonAllume def toggleLBureau(): global LBureauAllume if LBureauAllume: ser.write('off port lbureau\r') else: ser.write('on port lbureau\r') time.sleep(0.5) read() LBureauAllume = not LBureauAllume def toggleSon(): global sonAllume if sonAllume: ser.write('off port son\r') else: ser.write('on port son\r') time.sleep(0.5) read() sonAllume = not sonAllume def offAll(): global sonAllume global LBureauAllume global LSonAllume ser.write('off ports all\r') time.sleep(0.5) read() sonAllume = False LBureauAllume = False LSonAllume = False login() while True: list = pylirc.nextcode() if list is not None: for code in list: if code == "key1": toggleLSon() if code == "key2": toggleLBureau() if code == "key3": toggleSon() if code == "powerOff": offAll() #garder la connexion active après 5 min if ser.inWaiting() > 0: time.sleep(1) if(read().find('ended') != -1) : #session ended print 'Reconnecting...' time.sleep(1) login()
A l’aide de ce script, j’ai configuré 4 nouveaux boutons sur ma télécommande : un qui allume/éteint ma sono, un qui fait la lumière au dessus de mes platines, un qui fait la lumière sur mon bureau et un OFF qui éteint tout en même temps. Combiné à l’arduino qui possède son propre capteur vers mon lit, ma télécommande est configurée comme suit :