Le 31 mai 2015
Le but est d'agir sur les GPIO du PI depuis une appli sur son
téléphone.
Dans mon cas, j'ai acheté une petite carte à relais (4 euros pour le modèle à 2
relais isolés par optos) et je commande un relais depuis mon téléphone qui
commande une chaudière (le pi est branché à la place du thermostat d'ambiance
qui, pour moi était inexistant).
Dans cet article, je vais (essayer de) vous expliquer comment faire l' interface graphique pour piloter votre pi.
Pré requis : Le pi doit avoir une adresse ip connue de
l'extérieur si on veut s'en servir ailleurs qu'à la maison.
On a donc :
- une adresse IP du pi en interne (locale comme 192.168.0.12)
- une adresse IP du pi en externe (WAN comme 90.105.40.22 - c'est juste
un exemple - je ne vous donne pas la mienne ;-). dans ce cas il faut aussi s'occuper de la box
(NAT etc.).
Principe :
Sur le pi : Apache + PHP
Sur le téléphone : une appli graphique faite sous
App-inventor (gratuit - il faut
quand même un compte Google)
Réalisation :
Sur le pi on créé une page appi.php.
Sur le téléphone, il suffit que l'application cherche à se connecter à
http://adrpi/appi.php?action=toto
(adrpi représente l'adresse du pi)
Dans la page appi.php on récupère l'action et on titille les GPIO en fonction de
cette action.
On peut même faire plus avec http://adrpi/appi.php?action=toto&value=machin
voire
http://adrpi/appi.php?action=toto&value=machin&value2=truc
(Notez que j'utilise action,
value et value2 mais vous êtes entièrement
libre).
Comme j'ai un capteur de température sur mon pi, j'ai aussi besoin d'en avoir l'information sur mon téléphone. Aussi quand je lance une action sur la page php, celle-ci me retourne systématiquement une page vide avec, comme titre les informations voulues. En effet, dans sa version actuelle (2.0) apache ne peut utiliser d'autres méthodes que http et seule l'information titre, dans ce cas peut être exploitée par le composant WebViewer de App-inventor.
Page php (appi.php) :
D'abord récupérer toutes les commandes passées à appi.php.
Contenu de appi.php :
Le retour des infos :<?php
foreach ($_GET as $k=>$v) {
$$k=$v;
echo "<!-- $i $k=${$k} -->\n";
$i++;
}
Ceci créera les variables action,
value et value2
avec leurs valeurs remplies (par exemple $action=toto)
La deuxième ligne (echo) sert juste à mettre
dans un commentaires les valeurs reçues (pour debug).
Une fois ceci fait, un vulgaire switch sur
action, par exemple vous permet de faire ce que
vous voulez :$act=strtolower(substr($action,0,5));
echo "<!-- act=$act -->$n";
switch($act) {
case "allum":
$type = "Start";
system("$site/startchau.py",$cr);
if($cr==0) {
respond();
}
break;
case "etein":
$type = "Stop";
...
J'avais besoin de connaître l'état de la chaudière (allumée ou éteinte, la
température de consigne de jour, celle de nuit, la température mesurée, etc.
J'ai choisi un format dont les valeurs sont séparées par <deux points> et décidé
de communiquer les températures en centièmes de degrés pour ne pas avoir de
virgules. Ainsi 19,5 °C était représenté par 1950. L'ordre des informations
était aussi fixe :
État de la chaudière (0 ou 1), température de consigne de jour, température
de consigne de nuit, température mesurée... Et ça donne :
1:2100:1600:1947
grâce à une petite fonction qui s'en occupe
function respond() { global $mode, $state, $consj, $consn, $nuitd, $nuitf, $temp, $noty; print "<html><head>\n"; print "<title>$mode:$state:$consj:$consn:$nuitd:$nuitf:$temp:$noty</title>\n"; print "</head><body>\n"; print "$mode:$state:$consj:$consn:$nuitd:$nuitf:$temp:$noty\n"; print "</body></html>\n"; }
Les "\n" sont là pour faire plus joli si on
doit examiner le code source de la page
... qui produit donc ceci (exemple partiel) :
<html><head> <title>1:2100:1600:1947</title> </head><body> 1:2100:1600:1947 </body></html>
Le téléphone n'avait plus qu'à se débrouiller avec ça :-)
Notez que la ligne encadrée par les balises body
n'est pas indispensable.
L'appli graphique :
Justement parlons-en. Sous App-inventor, dans la liste des User interface, on
trouve le composant WebViewer.
On le glisse dans son projet et on le rend invisible. On coche également la case
IgnoreSslerrors (pour éviter "page Web non trouvée").
Quand je veux allumer la chaudière, j'envoie http://adrpi/appi.php?action=allume
et ma page php reçoit donc la variable $action="allume".
Pour le faire depuis l'interface graphique, on passe en mode Blocks (on
quitte le mode Designer), on clique une fois sur WebViever
(que j'ai renommé en Appi) et on choisit
call <Appi> .GoToUrl que j'ai
intégré dans une SendA (comme Send Action) qu'on appelle avec le paramètre
allume (par exemple) qui
arrive alors à travers la variable
Action de la procédure SendA. La
variable globale url contient
http://90.105.40.22/appi.php (encore une fois l'IP n'est qu'un exemple)
Il faut aussi un composant Clock que l'on trouve à gauche (dans le mode Designer) dans la rubrique Sensors sur lequel on décoche TimerEnabled. J'ai réglé TimerInterval à 500 pour avoir 1/2 seconde. Comme on le voit ici, après avoir envoyé la commande, on autorise le timer à se mettre en route.
Lorsqu'il se déclenche (1/2 seconde plus tard, donc) il initialise la variable globale res pour refléter le contenu du titre de la page web (peut-être) reçue. Si res est vide, on décrémente une variable retry (fixée à 10 au début) et on quitte. Si res est remplie, on arrête le timer et on passe à l'analyse des valeurs reçues.
Voila la fonction (à peu près) complète :
LabRefresh
est un label qui affiche une sorte de compte-rendu de ce qui se passe et
getmots est la fonction qui analyse les données
séparées par les <deux-points> pour afficher les diverses infos aux bons
endroits.
On voit, dans cette fonction ce qui se passe si jamais
retry arrive à 0 : on affiche le
compte-rendu, on arrête le timer et ont quitte.
Je n'ai pas montré qu'à chaque passage dans la décrémentation on ajoute un point
à la fin du label
LabRefresh pour faire une petite animation :
Après de nombreux essais à tâtons, l'ensemble marche parfaitement (je peux aussi parler à l'interface et le résultat est bluffant :-)
NB je ne suis pas très content de la structure de mon article, si quelqu'un a de meilleures idées, je suis ouvert ;-)