Cette semaine, nous allons illustrer l'interaction de PHP avec nos capteurs USB sur une application hyper classique: l'enregistrement de paramètres météorologiques (température et d'humidité). Rien de très magique, mais cet exemple simplissime montre tout l'intérêt de pouvoir accéder facilement à des périphériques USB depuis un langage comme PHP, qui par la richesse et la simplicité de ses librairies permet des réalisations intéressantes en deux temps, trois mouvements.
Le but du projet est d'obtenir un graphique en temps réel montrant l'évolution de la température et de l'humidité sur un intervalle de temps donné, comme sur l'exemple ci-dessous. Bien entendu, on veut aussi stocker les données dans une base de données pour pouvoir les retraiter ultérieurement si nécessaire.
Voilà ce qu'on aimerait obtenir, en temps réel
Pour ce faire, on va naturellement utiliser un utiliser un Yocto-Humidity, connecté à un PC sur lequel on a installé un serveur web avec PHP (en l'occurrence on a utilisé EasyPHP, mais on peut aussi le faire avec MAMP sur un Mac OS X par exemple).
Le Yocto-Humidity: une micro-station de mesure
Au niveau du logiciel, il y aura deux parties: le code qui prend les mesures périodiquement et les stocke dans la base, et le code qui affiche le graph sur demande.
Pour prendre les mesures en PHP, nous lançons un petit script PHP sur la machine en ligne de commande. Peu de gens pensent à utiliser PHP de cette manière, et c'est dommage car c'est en réalité un langage bien pratique pour exécuter des petits scripts sous OS. Sous Windows, si vous avez installé EasyPHP ou un environnement équivalent, vous trouverez l'exécutable php.exe quelque part sous Program Files, et il suffit de le lancer avec le nom de votre script PHP en argument. Voilà donc le script qui prend les mesures et les stocke dans la base MySQL:
include("yocto_api.php");
include("yocto_temperature.php");
include("yocto_humidity.php");
function mysql_check($what,$retval)
{ if(!$retval) die("MySQL error ($what): ".mysql_error()); }
$conn = mysql_connect('localhost','db_username','db_password');
mysql_check('connect', $conn);
$res = mysql_select_db('weather');
mysql_check('select_db', $res);
yRegisterHub('http://127.0.0.1:4444');
while(TRUE) {
$temp = yFirstTemperature()->get_currentValue();
$hum = yFirstHumidity()->get_currentValue();
Print("Temperature: $temp C\n");
Print("Humidity: $hum %RH\n");
$time = time();
$time -= $time % 60;
$res = mysql_query("select * from meteo where timestamp=$time");
mysql_check('select', $res);
if(mysql_num_rows($res) == 0) {
mysql_query("insert into meteo (timestamp,temperature,humidity)".
" values ($time,$temp,$hum)");
}
sleep(20);
}
?>
Après l'initialisation de la connection avec la base de donnée MySQL 'weather' (qu'il faut préalablement créer en utilisant phpMyAdmin par exemple), ce code effectue une mesure et la stocke dans la base en utilisant comme index de temps la date et l'heure courantes (fonction time()), arrondies à une minute. On ne stocke pas plus d'une mesure pas minute dans la base, même si la boucle de mesure elle tourne toutes les 20 secondes.
Pour l'affichage du résultat, on fait une petite page web tout ce qu'il y a de plus standard, mais référant à une image qui sera générée dynamiquement en PHP. On utilise une des nombreuses librairies pour faire des graphiques en PHP disponible sur le Web, en l'occurrence jpGraph puisque c'est celle-là que Google nous a retourné en premier aujourd'hui...
$conn = mysql_connect('localhost','db_username','db_password');
mysql_check('connect', $conn);
$res = mysql_select_db('weather');
mysql_check('select_db', $res);
// lecture des mesures durant les dernières 48h depuis la base
$lastday = time() - 2*86400;
$query = "select * from meteo where timestamp>=$lastday order by timestamp";
$res = mysql_query($query);
mysql_check('select', $res);
$time = Array();
$temp = Array();
$hum = Array();
while ($row = mysql_fetch_array($res)) {
$time[] = $row['timestamp'];
$temp[] = $row['temperature'];
$hum[] = $row['humidity'];
}
// dessin du graph
chdir("../jpgraph");
include_once ("jpgraph.php");
include_once ("jpgraph_line.php");
include_once ("jpgraph_date.php");
$tplot = new LinePlot($temp,$time);
$hplot = new LinePlot($hum,$time);
$graph = new Graph(600,350);
$graph->title->Set('Temperature & Humidity');
$graph->SetMargin(60,60,40,50);
$graph->SetMarginColor('white');
$graph->SetScale('datlin',0,100);
$graph->Add($hplot);
$graph->SetY2Scale('lin',0,12);
$graph->AddY2($tplot);
$graph->xaxis->SetLabelAngle(90);
$graph->xaxis->scale->SetDateFormat('H:i');
$graph->yaxis->SetColor('dodgerblue');
$graph->yaxis->title->SetColor('dodgerblue');
$graph->yaxis->title->Set('%RH');
$graph->yaxis->title->SetAngle(90);
$graph->yaxis->title->SetMargin(10);
$graph->y2axis->SetColor('hotpink3');
$graph->y2axis->title->SetColor('hotpink3');
$graph->y2axis->title->Set('°C');
$graph->y2axis->title->SetAngle(90);
$graph->y2axis->title->SetMargin(10);
$graph->Stroke();
?>
Et voilà, c'est tout pour la programmation, le projet est prêt à fonctionner. Avec un petit bémol... si l'on veut mesurer la température et l'humidité à l'extérieur, il va falloir prévoir de protéger un peu l'électronique. Pour nous faciliter la tâche, le capteur proprement dit peut se détacher de l'électronique USB et être déporté à l'aide d'un simple cable nappe, ce qui permet déjà de garder toute la partie la plus sensible à l'intérieur. Nous avons donc déporté le capteur de 4 mètres environ.
Le module est prévu pour pouvoir déporter le capteur d'humidité
Reste à protéger un minimum le capteur lui-même. En l'occurrence, la technique de tropicalisation décrite il y a quelques semaines n'est malheureusement pas applicable, car le spray de tropicalisation risquerait d'endommager le capteur d'humidité. On va donc se rabattre sur une méthode de protection plus classique, et se contruire un petit abri à instruments météo:
Un petit abri pour notre capteur
Le capteur monté verticalement dans son écrin
Et voilà le travail ! Vous pouvez maintenant aller voir par vous-même le temps qu'il fait chez nous...
La station de météo Yoctopuce