SSL tunneling Raspbery Pi

on commence par installer le package stunnel4 :

sudo apt-get install stunnel4

Ensuite il faut l activer sinon on aura cette erreur en essayant de le lancer :

pi@raspberrypi ~ $ sudo /etc/init.d/stunnel4 start
SSL tunnels disabled, see /etc/default/stunnel4

donc pour éviter ca on édite le fichier de conf :

sudo vi /etc/default/stunnel4

et on remplace

ENABLED=0

par

ENABLED=1

ensuite on configure stunnel en créant son fichier de conf qui n existe pas par défaut :

sudo vi /etc/stunnel/stunnel.conf

dont voici le contenu

chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
; PID is created inside the chroot jail
pid = /stunnel4.pid

client=no
cert=/etc/stunnel/stunnel.pem
debug=3
sslVersion = all
output=/var/log/stunnel4/stunnel.log
[sslssh]
accept=443
connect=localhost:22

ensuite il faut une clé sinon on aura cette erreur au démarrage :

sudo /etc/init.d/stunnel4 start

pour créer la clé :

pi@raspberrypi ~ $ cd /etc/stunnel
pi@raspberrypi /etc/stunnel $ sudo openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem

et enfin on peut le starter

pi@raspberrypi /etc/stunnel $ sudo /etc/init.d/stunnel4 start

et vérifier qu il est bien lance avec

pi@raspberrypi /etc/stunnel $ ps -aux | grep tun
warning: bad ps syntax, perhaps a bogus '-'?
See http://gitorious.org/procps/procps/blobs/master/Documentation/FAQ
stunnel4 20179  0.0  0.3   4400   604 pts/0    S    07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
stunnel4 20180  0.0  0.3   4400   604 pts/0    S    07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
stunnel4 20181  0.0  0.3   4400   604 pts/0    S    07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
stunnel4 20182  0.0  0.3   4400   604 pts/0    S    07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
stunnel4 20183  0.0  0.3   4400   604 pts/0    S    07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
stunnel4 20184  0.0  0.3   4400   748 ?        Ss   07:54   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf

Ensuite il faut penser a garder sa clé “stunnel.pem” avec soit pour pouvoir la copier sur le client

Pour configurer le client il faut télécharger putty et stunnel pour Windows. Ensuite in faut installer stunnel et dans le répertoire d installation il faut remplacer la clé “stunnel.pem” par notre clé.

Une fois que la clé est installe il reste plus qu a démarrer stunnel et changer sa config en la remplaçant par :

client = yes
 delay = yes
 [sshtunnel]
 accept = 127.0.0.1:22
 connect = <adresse IP serveur qu on a configurer avant>:443

et on peux ensuite utiliser putty en se connectant a l adresse stunnel : 127.0.0.1:22 et on atterrira sur le serveur distant

Pour AWS EC2 AMI instance

[ec2-user@domU-12-31-39-09-EE-BA stunnel]$ cat stunnel.conf
root = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
; PID is created inside the chroot jail
pid = /stunnel4.pid

client=no
cert=/etc/stunnel/stunnel.pem
debug=3
sslVersion = all
output=/var/log/stunnel4/stunnel.log
[sslssh]
accept=443
connect=localhost:22

puis

[ec2-user@domU-12-31-39-09-EE-BA stunnel]$ sudo stunnel stunnel.conf

 

 

Protection site web par password ET/OU IP

Pour restreindre l’accès aux commandes de mon framework domotique j’utilisai une protection par mot de passe avec lighttpd. J’avais mis cette protection en place en utilisant le tuto disponible ICI.

Le probleme est que l’on doit taper le mot de passe a chaque fois et si je le change je dois le communiquer a mon coloc…. J’ai donc fouiller un peu la doc de lighttpd et je me suis rendu compte qu on pouvait egalement filtrer les acces par adresse IP. Encore plus fort….on peux combiner les 2 solutions !!

Voila donc la nouvelle conf d’acces lighttpd pour proteger la partie admin du framework ou je ne demande pas le mot de passe pour les adresse de mon reseau local (je fais confience au gens qui viennent chez moi 😉 ) et je demande un password pour les acces depuis internet :

$HTTP["remoteip"] !~ "192.168.0.*" {
auth.require = ( "/Sender/" =>
(
"method" => "basic",
"realm" => "Password protected area",
"require" => "user=charles"
)
)
}

ensuite il faut penser a reloader la config avec

/etc/init.d/lighttpd restart

Ajout librarie android studio

Ajout de la lib “guava” a un projet dans android studio en 3 étapes :

1/ Copier le fichier “guava-14.0.1.jar” present dans le repertoire d’installation d android studio “C:\Dev\Android\android-studio\lib” vers le repertoire “lib” du projet courant “C:\Users\charles\AndroidStudioProjects\VoiceRecognition\VoiceRecognition\libs”

2/ Ajouter en tant que library (clique droite sur la library) :

222

3/ Ajouter la lib dans le fichier de dep de graddle :

333

Ensuite ca devrait compiler (sinon il faut faire un clean project)

Installation Android Studio Ubuntu

1/JDK

La premiere etape est l’installation du JDK disponible ici. Il faut choisir la version Linux x64 : jdk-7u21-linux-x64.tar.gz.Une fois que la version est DL il faut le decompresser et le copier :

tar xzvf ~/Downloads/jdk-7u21-linux-x64.tar.gz
mv jdk1.7.0_21/ /usr/lib/jvm/

finalement il reste juste a mettre a jour l environement avec au choix des “export dans le wshenv/profile” ou alors avec “update alternative” :

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.7.0_21/bin/java 1
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.7.0_21/bin/javac 1
sudo update-alternatives --install /usr/bin/javaws javaws /usr/lib/jvm/jdk1.7.0_21/bin/javaws 1
sudo update-alternatives --config java
sudo update-alternatives --config javaws
On peux verifier que tout a ete installe correctement avec :

charles@charles-Fixe:~/Téléchargements$ java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)
2/ Android studio
Comme pour le SDK….on commence par le DL ici. Ensuite on le decompresse
tar xvzf android-studio-bundle-130.677228-linux.tgz
et on peux le lancer
cd android-studio/bin
charles@charles-Fixe:~/DEV/android-studio/bin$ ./studio.sh
Capture du 2013-05-26 21:55:24

Creation application android pour remplacer « Tasker + Autovoice » – P1

Le but de cet article est de créer une application native android pour remplacer « tasker + autovoice » que j’utilise actuellement pour envoyer des commandes vocales a mon serveur domotique. Le duo « Tasker + Autovoice » marche plutot bien mais je souhaite qq chose d’integrer dans mon framework et surtout de pouvoir le personnaliser un peu plus. En plus je pourrai tester la nouvel IDE de Google pour le DEV android : Android Studio.

android_studio_medium

Android studio est un IDE Android créée par Google et présenté a la communauté lors des Google I/O de mai 2013. Ce nouvel IDE est en version « beta » et peut être une option intéressante en plus du classique « Eclipse + SDK + Plugin ».

Android Studio est telechargable ICI

Les instructions pour l’installation sont sur la meme page et celle ci est assez facile (comparativement a eclipse + plugins) puisque tout est integre. Une seul remarque importante….si le logiciel ne se lance pas apres l instalation lisez ca :

Known issue: On some Windows systems, the launcher script does not find where Java is installed. If you encounter this problem, you need to set an environment variable indicating the correct location.
Select Start menu > Computer > System Properties > Advanced System Properties. Then open Advanced tab > Environment Variables and add a new system variable JAVA_HOME that points to your JDK folder, for example C:\Program Files\Java\jdk1.7.0_21.

Une fois que tous est installe et que l’application fonctionne on doit avoir un display qui ressemble a ca :

1

Ensuite on va installer le driver du samsung galaxy note 2 pour pouvoir installer nos programme sur ce dernier. Cet operation est explique ICI et ICI

J’ai eut un peu de mal parce que je pense qu il manque quelques étapes/explication donc je détail un peu plus. La première chose a faire est d’installer le drivers pour la communication Galaxy-PC. Pour cela il faut aller dans la gestion du SDK « SDK android manager »depuis l’application et dans la partie « Extras » coche « Google USB Driver » et de cliquer sur « instal packages ».

2

Grace a cet operation le driver serva ensuite present dans le folder « <sdk>\extras\google\usb_driver\ «

3

Maintenant que le driver est present sur le disque on peut l’utiliser. Il faut ouvrir le « device manager » de windows. Le « Device manager » peut etre lancer depuis le « control panel → System and security → System »

7

Ensuite dans le device manager il y a le tel android dans “other” :

g1

il faut cliquer sur “update driver” pour le forcer a utiliser le driver qu on a instale juste avant. Ensuite on precise qu on a le driver en choissisant “browse my computer…”

j2

Ensuite il faut faire attention a choisir “Let me pick a list of device….” :

j5

Ensuite il faut cliquer sur le bouton “have disk” et donner le lien vers le path ou est le driver (dans le repertoire du SDK)

h1

et enfin windows propose plusieurs choix. Il faut prendre “Android ADB interface”

tt

Windows risque de vous dire que le driver est pas compatible mais il suffit de faire “oui” a la question “installer quand meme”. Si tout se passe bien le device sera enfin visible dans le device manager comme ci dessous :

tyy

Pour etre sure que l’installation on peut verifier la liste des devices attache avec un utilitaire du SDK android disponible dans le repertoire “android-studio\sdk\platform-tools” : adb.exe. Pour ca on utilise l’invite de commande windows et on lance “adb devices” :

fin

Voila 😉 le device est connecte et peut etre utilise dans “android studio”

 

 

Shutdown a distance depuis un PC linux (raspbery Pi)

Il y a qq temps j’ai mis en place une solution de WOL pour démarrer mon PC Windows 7 depuis le Raspberry Pi (le but étant que mon système domotique le démarre automatiquement quand je rentre du travail le soir).

Cela fonctionne bien et j’ai récemment découvert que le shutdown à distance été aussi possible et que sa mise en place n’est pas si difficile que ça….. Tout cela grâce au blog de Michael http://michael.venez.fr/ qui contient toutes les étapes nécessaires.

Pour résumer il faut bien penser à installer les packages nécessaire sur le Raspberry Pi (samba + samba common ). Ensuite il faut activer le RPC sur windows 7 (désactive par défaut pour des raisons de sécurité) grâce a la procédure décrite ici http://www.howtogeek.com/howto/windows-vista/enable-mapping-to-hostnamec-share-on-windows-vista/

Une fois que tout ceci est mis en place on peut arrêter le PC windows 7 à distance avec :

net rpc shutdown -f -I 192.168.0.7 -U user%user_password

Merci encore Michael pour le tuto sur son site.

Migration du server/client domotique de “Select” vers “twisted”

Le serveur domotique hébergé sur mon RaspberryPi déclenche certaines actions en fonction d’évènements. Par exemple lorsqu’ un détecteur de présence est déclenché on allume la lumière de la même pièce. Dans cet exemple l’évènement sera reçût par le port USB du RaspberryPi (car il proviendra de l’Arduino Leonardo). Il existe d’autre évènements qui arriveront sur le RaspberryPi par d’autre moyen (TCP pour le site web de commande par exemple).

Jusqu’ a présent le serveur été code en python et attendait les évènements grâce au module python « select » qui me permettait de monitorer a la fois la liaison USB et TCP. Avec ce modèle je ne pouvais cependant pas faire du processing en arrière-plan (déclencher un évènement a une certaine heure par exemple) puisque le « select » est bloquant. J’ai donc choisit de migrer mon code vers Twisted qui correspond exactement a ce que je veux faire « Twisted is an event-driven networking engine written in Python and licensed under the open source »

La documentation est très bien faite est disponible sur le site officiel : http://twistedmatrix.com/trac/

Dans mon cas je veux que twisted monitor 2 « récepteurs » :

  • La liaison USB qui communique avec l’Arduino Leonardo est reçoit donc les messages des capteurs (capteur présence, détection incendie) qui peuvent être trigger à tout moment. Cette liaison est aussi utilisée pour envoyer des ordres aux capteurs/actionneurs du réseau (par exemple pour allumer la lumière)
  • La liaison TCP qui communique avec un client python fortement couple a un script PHP qui reçoit les ordres de la GUI HTML. Cette liaison est utilisée dans les 2 sens (le serveur répond au client qui affiche la réponse sur la page web).

La création de ses 2 « handlers » se fait assez facilement à condition de trouver le bon protocole duquel il faut hériter. Pour la liaison TCP il faut hériter de « twisted.internet.protocol. Protocol » (il existe déjà pas mal d’exemple pour ce cas de figure). Pour la liaison USB avec L’Arduino Leonardo on doit hériter de « twisted.protocols.basic. LineReceiver ». Ce protocole permet de recevoir les messages du port USB à condition qu’il soit bien envoyé comme une ligne complète. Il ne faut pas se tromper avec un autre protocole sinon les données seront tronquées.

Chacun de ses « handlers » a une méthode qui sera appelé lors de la réception de message : « lineReceived » pour l USB et « dataReceived » pour le TCP. Voilà à quoi ressemblent les 2 handlers

class UsbHandler(LineReceiver):
    """protocol handling class for USB """

    def __init__(self,iBrain,iRegisteredDevice):
        self.brain = iBrain
        self.registeredDevices = iRegisteredDevice

    def lineReceived(self, line):
        logging.info("USB Handler created to process : " + str(line))
        self.brain.HandleUsbInput(line,self.registeredDevices)

class TcpHandler(Protocol):
    """protocol handling class for TCP """

    def __init__(self,iBrain,iRegisteredDevice):
        self.brain = iBrain
        self.registeredDevices = iRegisteredDevice

    def dataReceived(self, data):
        logging.info("Tcp Handler created to process : " + str(data))
        if "READ" in str(data):
            logging.info("READ command")
            aRest = aBrain.ReadDeviceStatus2(data,aRegisterDevices)
            logging.info("READ command res " + str(aRest))
            self.transport.write(str(aRest))
        elif str(data) == "STOP": 
            logging.info("STOP command")
            aBrain.stop()
            reactor.stop()
        else:
            logging.info("Write command")
            aBrain.SendMessage(data,aRegisterDevices)
            self.transport.write("ACK")

 

Ensuite on attache ses 2 protocoles au “reacteur” qui est le Cœur de twisted. Pour le TCP on lui ajoute une surcouche au travers une factory (je ne sais pas pkoi il ne faut pas faire la même chose pour l USB…)

reactor.listenTCP(50007, TcpHandlerFactory(aBrain,aRegisterDevices))
SerialPort(UsbHandler(aBrain,aRegisterDevices), '/dev/ttyACM0', reactor, 9600)

 

Avec ce design je me retrouve dans la même configuration que celle de mon “framework – Select” fait maison. On va donc ajouter une boucle qui sera capable de gérer la logique background (celle qui ne dépend pas d’un évènement particulier).

Pour cela on créer une méthode (dans notre cas elle se contente d’appeler la vrai méthode de processing) :

def tired_task(iBrain):
    #logging.info("I want to run slowly" + str (datetime.datetime.now()))
    iBrain.smartProcessing2(aRegisterDevices)

et on l ajoute au “reactor” avec une frequence :

lc2 = LoopingCall(tired_task, aBrain)
 lc2.start(5)

Dans mon cas cette méthode va mettre a jour les capteurs automatiquement quand nécessaire. Par exemple si le dernier relevé de température date de plus de 5 minutes dans le salon et que la config de ce capteur autorise un relevé toutes les 5 minutes….on le met à jour. Cette méthode va également vérifier l’ensemble des capteurs stable de l’appartement et les updater si nécessaire. Par exemple on va éteindre la lampe de l’entrée si personne n’a été détecté depuis 10 minutes.

    def smartProcessing2(self,iListOfDevice):
        '''Une boucle qui a lieu regulierement pour prendre des decision. Elle va verifier les detecteur et en fonction triger certains evenements.
        Par ex si qq un est detecte dans l entree on decide d allumer la lumiere.
        Cette classe va aussi verifier si certaines autres actions (non lie a la detection de personne) peuvent etre prise.
        Par ex : si on a pas eut de detection de personne depuis un moment ds l entree et que la lumiere est allume....on etient
        Enfin elle va aussi mettre a jour tous les capteurs en fonction de leur refresh rate
        Par exemple si ca fait trop longtemps qu on a pas updater la T alors on la met a jour'''
        logging.info("Begining of a smart loop")

        #Step 1 : Verifier tous les detecteurs (interupteurs stables) pour voir si ils ont ete actives et prendre les actions correspondantes avant de les reset
        #Par exemple si le detecteur de fumee a ete active alors on va envoyer un mail 
        logging.info("Checking all possible event")
        for aOneDevice in iListOfDevice.registeredDevices:
            logging.debug("checking event : " + str(aOneDevice.id))
            if ((aOneDevice.id == 2) and (aOneDevice.currentStatus=="unstable")):
                sendEmailFireDetected()
            elif ((aOneDevice.id == 10) and (aOneDevice.currentStatus=="unstable")):
                self.PeopleDetectedEntree(iListOfDevice)
            elif ((aOneDevice.id == 9) and (aOneDevice.currentStatus=="unstable")):
                self.PeopleDetectedCharlesRoom(iListOfDevice)
            aOneDevice.reset()

        #Setp 2 : On reset les actions resultantes des detections passe
        #Par exemple si la lumiere de l entree ete ON car qq un avait ete detecte depuis 10 minutes mais qu il y a plus eu de detection depuis 10 min....on eteind
        logging.info("Reseting all previous automatic actions")
        for aOneDevice in iListOfDevice.registeredDevices:
            logging.debug("checking states : " + str(aOneDevice.id))
            if ((aOneDevice.id == 9) and ((iListOfDevice.getDevice(3)).currentStatus=="on") and (datetime.datetime.now() - aOneDevice.LastTMeaureDate > datetime.timedelta (seconds = 600))):
                self.TurnCharlesLightOff(iListOfDevice)
            elif ((aOneDevice.id == 10) and ((iListOfDevice.getDevice(8)).currentStatus=="on") and (datetime.datetime.now() - aOneDevice.LastTMeaureDate > datetime.timedelta (seconds = 180))):
                self.TurnEntreeLightOff(iListOfDevice)

        #Setp 3 : On force un refresh des capteurs periodiques
        logging.info("Force the auto refresh of capteur")
        for aOneDevice in iListOfDevice.registeredDevices:
            logging.debug("checking autoupdate : " + str(aOneDevice.id))
            if ( (aOneDevice.stateCanBeRefresh == True) and (aOneDevice.refreshOngoing == False)and (datetime.datetime.now() - aOneDevice.LastTMeaureDate > datetime.timedelta (minutes = aOneDevice.refreshRatemin) ) ):
                logging.debug("We can refresh : " + str(aOneDevice.id))
                self.refreshCapteur(aOneDevice,iListOfDevice)

Grace à cette nouvelle boucle intelligente la mise à jour des capteurs ne se fait plus dans la crontab avec :

# toutes les heures + 7 min on refresh la emperature entree
 7 * * * * /home/pi/Usb_Arduino_Leonardo/PythonWrapperWebArduinoUsbS.py -o CRONTAB -s 30

La mise à jour des capteurs fait maintenant partie intégrante de l’application.

J’ai également supprimé la base de données qui été interrogée par le site web et remplit par le serveur. Maintenant le site web interroge le serveur pour récupérer l’état T de n’importe quel capteur (en utilisant le format JSON).

case "CMD_READ" :
 $aCommandToExecute = WRAPPER2 . "-o " . getenv(REMOTE_ADDR) . " -s " . $_REQUEST["iCmdToExecute"] . " -t READ";
 $output = array();
 exec($aCommandToExecute, $output);
 print(json_encode($output));
 break;

renvoit :

[“‘{\”py\/object\”: \”Deipara_Objects.CapteurMesure\”, \”InPossibleCmd\”: {\”15\”: \”recoit Nouvelle T\”}, \”physicalLocation\”: \”\”, \”ActionsCommands\”: {\”15\”: \”self.currentStatus=aData\\\\nself.LastTMeaureDate=datetime.datetime.now()\\\\nself.refreshOngoing = False\”}, \”OutPossibleCmd\”: {\”15\”: \”recoit Nouvelle T\”}, \”porteuse\”: \”GATEWAY\”, \”stateCanBeRefresh\”: true, \”type\”: \”CapteurMesure\”, \”LastRefreshDate\”: {\”py\/repr\”: \”datetime\/datetime.datetime(2013, 4, 7, 22, 13, 48, 269822)\”}, \”refreshRatemin\”: 3, \”refreshOngoing\”: false, \”id\”: 15, \”currentStatus\”: 209.0, \”Reset\”: \”\”, \”LastTMeaureDate\”: {\”py\/repr\”: \”datetime\/datetime.datetime(2013, 4, 8, 15, 31, 38, 381700)\”}, \”PossibleStates\”: {}, \”description\”: \”\”}'”]

Au site Web et les informations nécessaires pour la page seront utilisés. Toute la logique est en train de migrer vers le serveur python pour qu’il coordonne l’ensemble des actions. Je clarifie également toutes les interfaces pour utiliser des formats standard (JSON plutôt que des select de colonnes dans une base).

L’ensemble du code est toujours dispo ICI

Création d’un daemon python capable de communiquer avec le port USB et un socket

Actuellement quand je clique sur un lien qui nécessite l’envoie d’un message a un capteur dans l’appartement comme par exemple « actualiser la température » :

ScreenShot001

Le site web envoie une requête AJAX qui appel un script python pour communiquer par USB depuis le RaspberryPi vers l’Arduino Leonardo. Le script monitor ensuite le port USB pour la réponse de l’Arduino Leonardo pendant 10s pour récupérer la réponse du capteur et la transmettre au site web et à l’utilisateur.

TemperatureRequestV1

Ce design fonctionne plutôt bien mais bug de temps en temps quand plusieurs personne tentent de rafraichir la température et l’humidité en même temps car une réponse « humidité » peut arriver avant une réponse « température » et les réponses seront inverse. De plus cela ne me permet pas de mettre des capteurs  qui ne nécessite pas d’être appelé pour envoyer une information tel qu’un détecteur de fumée 😉
J’ai donc décidé de revoir le script python pour lui permettre de recevoir des infos de capteur a tout moment sans interaction avec l’utilisateur. Ce daemon doit cependant toujours être capable de recevoir les demandes des utilisateurs du site web…
Le daemon est donc en constante attente soit de message provenant de l’Arduino Leonardo au travers du port USB, soit de message de l’utilisateur (site web) provenant d’un client léger python au travers d’un socket réseau.

TemperatureRequestV2Server

Le monitoring simultané du port USB et d’un socket se fait grâce au module python « select » qui est un appel direct à la fonction « select » disponible sous linux. C’est le moyen le plus simple que j’ai trouvé pour faire du multiplexing sur mes 2 entrées (port USB et socket). Le code est donc plutôt simple puisque l’on attend juste que « select » nous donne la main pour tester quelle « entrée » a reçue quelque chose. En fonction de l’entrée on procéder au traitement. Voilà le code avec quelque commentaire pour mieux comprendre 😉

Un gros changement a également eut lieu dans la chaine de réponse puisque le process est maintenant asychrone. Il faut donc inclure plus d’information dans la réponse tel que l’ID du capteur pour savoir a quoi correspond la valeur reçue sur le port USB. Voilà un nouvel exemple de réponse de l’Arduino  Leonardo
La réponse comporte plusieurs champ/valeur tel que l’ID du capteur. Cet ID sera également inséré dans la DB.

Bonus :

Comme il m’arrive de temps en temps de redémarrer mon Raspberry Pi et que le daemon n’est pas lance au démarrage le system pourrai ne plus fonctionner….
J’ai donc légèrement modifie mon client qui est appelé par le serveur web pour détecter si le daemon est bien démarrer sur le RaspberryPi. Si ce n’est pas le cas le Server se charge de démarrer le daemon. On ne pourra donc pas répondre a la requête utilisateur mais au moins les suivantes fonctionneront bien.

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    s.connect((HOST, PORT))
except:
    print("no server available")
    s.close()
    print("starting server")
    subprocess.call("python PythonWrapperWebArduinoUsbD.py", shell=True)
    #on va rester la a l infini

Exemple :

On lance le script python serveur avec les arguments tel qui l serait lancer par le site web a la réception d’une requête client (les arguments utilisés simulant un Ping avec réponse hardcode ‘456’ d’un capteur.

pi@raspberrypi ~/Usb_Arduino_Leonardo $ python PythonWrapperWebArduinoUsbS.py -s J -i 20 -o TOTO
no server available
starting server

Le client détecte bien qu’il n y a pas de serveur et en lance donc un. Dans un autre terminal on relance le client

Client :

pi@raspberrypi ~/Usb_Arduino_Leonardo $ python PythonWrapperWebArduinoUsbS.py -s J -i 20 -o TOTO
Received 'MSG:J_ID:20_ORIGIN:TOTO'
pi@raspberrypi ~/Usb_Arduino_Leonardo $

Server :

pi@raspberrypi ~/Usb_Arduino_Leonardo $ python PythonWrapperWebArduinoUsbS.py -s J -i 20 -o TOTO
no server available
starting server
handle the server socket
handle all other sockets
input is : MSG:J_ID:20_ORIGIN:TOTO
Writting input to USB port and sending back to sender
Log line : DATE: 2013-03-11 21:02:08.518208 ORIGIN: TOTO CMD: J ID: 20
handle all other sockets
input is :
Closing socket

Le serveur à bien reçu la demande du client et à forwarder la demande a l’Arduino Leonardo par le port USB. Ensuite il a repris sa boucle et quelque secondes plus tard il a reçu la réponse ‘456’ sur le port USB. La réponse a été décodé et stocke dans la DataBase pour ensuite être utilise sur le site Web.

Installation de Sqlite3

J’ai décidé d’ajouter une base de données à mon site web de domotique pour conserver des informations sur les différents éléments. Je voulais utilise mongoDb au début mais comme il n’existe pas de paquet pour Rasbpian j’ai fallbacke sur SQLite3.

Voici comment ajouter SQLite3 a mon installation (voir ici pour l’installation de lighttpd et php).

sudo apt-get install sqlite3
sudo apt-get install php5-sqlite
sudo service lighttpd restart

Sqlite est maintenant utilisable sur notre serveur lighttpd 😉

 

Backup Raspbian SD card

J’ai récemment faillit perdre des jours de travaille sur ma raspbian du fait d’une mauvaise configuration du fichier sudoers… J’ai donc décidé de faire ce petit post pour présenter une manière de sauvegarder la carte SD.

Ce post reprend les explications presente ICI et ICI.

Il faut utiliser le binaire Disk Manager (disponible ICI). Une fois le binaire installe il suffit de sélectionner la lettre qui correspond à la carte SD (F dans mon exemple) et un nom de fichier de sauvegarde (RaspbianPi15Nov12.img) et de cliquer sur READ (car on lit la carte SD vers l’ordinateur).