Archives par étiquette : système

GPIO – Entrée en matière

Grâce à son port GPIO (General Purpose Input/Output), le Raspberry Pi peut interagir avec le monde réel en communiquant avec des capteurs, des moteurs, et un tas d’autres composants électroniques (sondes de température, LEDs, capteurs gyroscopiques, boussoles, GPS, servos moteurs, récepteurs IR/RF…). De la petite commande relais pour piloter vos guirlandes de Noël, au robot, en passant par la station météo et le drone, les possibilités sont sans limites, ou presque 🙂

pi_gpio

Le matériel de base

Qui dit GPIO, dit composants électroniques 🙂 Il va de soit que des compétences en électronique de base sont requises. De plus, il convient de s’équiper d’un minimum de matériel afin de pouvoir tester et réaliser de petits circuits.

imageVoici, selon moi, le stricte minimum du matériel à acheter avant de démarrer :

Le port GPIO

Le port GPIO du Pi comporte 26 broches qui peuvent être utilisées de manières différentes. Le schéma ci-dessous (publié par le site eLinux) montre le rôle de chaque broches ainsi que les protocoles qu’elles supportent.

GPIOsOn distingue 7 types de broches et usages qu’on peut en faire :

Ces différents « bus » et « protocoles » permettent d’interfacer le Pi avec d’autres cartes, modules ou composants électroniques.

Les exemples d’utilisation les plus simples des broches de type GPIO sont l’allumage et l’extinction d’une LED, l’interaction avec un bouton/interrupteur, le contrôle de relais, etc,…

L’I²C, le SPI, l’UART et le PWM permettent quant à eux de communiquer avec des microcontrôleurs pour réaliser des opérations plus complexes telles que le contrôle de servos moteurs, la lecture de mesures prises par des capteurs etc,…

Alimentation des broches

Avant toute chose il est important de préciser les broches du port GPIO sont alimentées en 3,3V. Seules les deux broches d’arrivée de courant (en rouge) fournissent une tension de 5V.

Ce qui veut dire qu’en mode ouput (sortie) la tension fournie par une broche est de 3,3V et délivrera un courant de 50mA max. Vous devrez donc vous assurer que les composants que vous reliez à ces broches supportent se type de courant. En mode input (entrée), une broche ne tolérera qu’une tension maximum de 3,3V ! Vous devrez donc toujours faire attention à vos branchements pour éviter d’endommager votre Raspberry Pi 🙂 

En outre, il est préférable d’utiliser une source d’alimentation tierce pour les composants et modules électroniques que vous souhaitez ajouter dans votre circuit. En effet, le Raspberry Pi n’est pas suffisamment robuste pour alimenter correctement et sans danger des circuits électroniques. Pour allumer une LED pas de problème, mais pour faire tourner un moteur, prévoyez une source d’alimentation dédiée.

Dans l’absolue, et pour des raisons évidentes de sécurité, je conseille d’utiliser des piles plutôt que de travailler directement sur le secteur (d’où le coupleur de pile dans la liste du matériel de base) 😉

Prendre la main sur le port GPIO

WiringPi est un outil qui permet de contrôler les différentes broches du port GPIO. Pour installer WiringPi :

git clone git://git.drogon.net/wiringPi
cd ./wiringPi
./build

A partir de là, vous pouvez obtenir l’état de toutes les broches grâce à la commande :

gpio readall

Ce qui devrait vous afficher un tableau de ce type :

readallChaque ligne du tableau représente une broche du port GPIO et vous indique sont mode IN/OUT (entrée/sortie) et sont état/valeur 0/1 (low/high). La colonne GPIO représente le numéro de la broche tel que décrit sur le schéma en haut de cet article. La colonne wiringPi représente le numéro de broche que vous devez utiliser en utilisant la commande gpio.

De manière très simplifiée, si vous voulez allumer une LED, vous devez mettre la broche en mode sortie/output. En mettant l’état de la broche à 1/up, la LED s’allumera. Si vous voulez savoir si un bouton/interrupteur est ouvert ou fermé, vous devez mettre la broche en mode entrée/input. Si vous lisez la valeur 0/down, alors l’interrupteur est ouvert. Si vous lisez la valeur 1/up, alors l’interrupteur est fermé 🙂 Dans la pratique c’est un tout petit peu plus complexe, mais il s’agit là de comprendre le principe.

Pour chaque broche, vous pouvez changer le mode entrée/sortie ou in/out grâce à la commande (<pin> étant le numéro de la broche ciblée) :

gpio mode <pin> in
gpio mode <pin> out

En mode entrée/read vous pouvez lire l’état d’une broche avec la commande :

gpio read <pin>

En mode sortie/write, vous pouvez changer l’état d’une grâce à la commande :

gpio write <pin> 0
gpio write <pin> 1

Pour plus d’information sur la commande gpio : http://wiringpi.com/the-gpio-utility/

Quelques exemples de montages simples

En cherchant un peu sur le web vous trouverez une multitude de tutos qui expliquent comment faire de petits montages simples. Inutile de plagier la terre entière en recopiant ici ces tutos, je préfère vous donner directement quelques liens :

1 – Raspberry Pi BOA Drone

Pi-BOA-Drone_small_45C’est avec un grand plaisir que j’attaque ce nouveau projet : un drone avion longue distance, piloté par un Raspberry Pi, baptisé Pi BOA Drone 🙂 L’objectif (impossible ? ambitieux ?) de ce projet est d’effectuer un vol de 400 kms (entre Lille et Metz) en parfaite autonomie (auto-pilote) !

Les avions et la robotique m’ont toujours passionné, et le mariage de ces deux mondes avec l’avènement des drones, tant au niveau militaire que « domestique », m’a donné envie de realiser mon propre drone. Il y a quelques années, cela relevait du fantasme, les composants et matérieux étaient chers et il n’existait pas de « système » suffisamment compact et accessible pour pouvoir l’intégrer à dans « object volant » sans se ruiner. L’arrivée du Raspberry Pi a changé la donne 😉

Les drones actuels

parrot_ar_droneUn des premiers drones a avoir été présenté au grand public est l’AR Drone de Parrot. Vendu en France à partir de 2010 pour près de 350€, il est, je pense, à l’origine de nombreux autres projets volants de la famille des multicopters/multirotors.

Soyons clair, il s’agit en fait d’un « hélicoptère » télécommandé amélioré. Je vais être vache, mais prenez un petit hélicoptère comme le Silverlit Sky Unicorn vendu une trentaine d’euros, ajoutez y une mini caméra, et vous obtenez le même résultat : Un objet volant télécommandé capable de faire du vol stationnaire tout en capturant une vidéo. Même si la technologie embarquée dans l’AR Drone est beaucoup plus complexe (gestion des rotors, capteurs, etc,…), le résultat est sensiblement le même… En disant cela, je ne cherche pas à dénigrer quoi que ce soit, j’essaie simplement de démystifier le sujet pour montrer qu’un drone n’est qu’un ensemble de systèmes simples 🙂

IMG_5459J’ai ce petit hélicoptère (le Silverlit Sky Unicorn) depuis plusieurs mois, et je dois dire que je m’amuse beaucoup avec 😀 Il m’a énormément inspiré pour ce projet de drone. Si vous vous lancez dans l’aventure, je vous conseille de vous acheter ce genre de jouet très abordable ne serait ce que pour vous familiariser avec la chose et vous rendre compte des problématiques liées au vol d’un objet 🙂

Revenons à l’AR Drone et à son système électronique embarqué. La première génération de la bête est pilotée par un processeur ARM9 qui fait tourner un OS Linux avec 128 Mo de RAM, le tout étant télécommandé via un lien WiFi. Cela ne vous rappelle rien ? Le tableau ci-dessous vous mettra sur la voix :

Système embarqué
AR Drone v1
Raspberry Pi
Modèle B 512
Processeur ARM9 468 MHz ARM11 700 MHz
RAM 128 Mo 512 Mo
Connectique USB, WiFi USB, Ethernet, GPIO
OS Linux Linux

Tout à fait ! C’est un système très semblable au Raspberry Pi qui fait voler l’AR Drone 🙂 Ce constat permet de valider l’hypothèse qu’il est possible de faire voler quelque chose grace à un Pi 🙂

Les drones multirotors

hexaphoto2Quand on dit « drone », on pense souvent aux drones de la famille des multicopters/multirotors, c’est à dire un « hélicoptère » à plusieurs rotors.  En cherchant sur le web, vous trouverez une multitude de sites/blogs qui expliquent comment créer un drone multirotors. Il existe même des systèmes « prêts à l’emploi », et des circuits dédiés au pilotage des différents rotors (qui est une opération relativement complexe). De plus en plus de sites spécialisés vendent tout le matériel nécessaire pour que vous puissiez monter vous même votre drone tri/quadri/hexa/octocopter. Celon les configurations et les matériaux, comptez plusieurs centaines d’euros tout de même.

L’intérêt de ce type de drone est qu’ils peuvent faire du vol stationnaire, ce qui est idéal pour les prises de vues aériennes. Plusieurs entreprises exploitent déjà ce créneau, comme la société Nord Drone Services dont je salue l’initiative 🙂

En revanche, ces drones consomment beaucoup d’énergie rien que pour se maintenir en l’air. Même si certains modèles permettent d’embarquer plusieurs kg de matériel, c’est au détriment de l’autonomie qui dépasse rarement les 20 minutes.

openpilot_logoJ’attire votre attention sur le projet OpenPilot qui propose une plateforme opensource pour la réalisation de ce type de drone. La communauté autour de ce projet est très active et le site est une mine d’information pour quiconque s’intéresse au sujet 🙂

Les drones avions

MQ-1_Predator_UAV_DronePersonnellement, je suis fasciné par les drones utilisés par les militaires depuis quelques années. Ces bijoux de technologies (qui sont en fait de gros avions télécommandés beaucoup plus simple à faire voler qu’un quadricoptère) ont le gros avantage d’avoir des ailes ! S’appuyer sur des ailes pour rester en l’air est beaucoup moins énergivore et permet d’emporter de plus lourdes charges. Il suffit d’assurer une propulsion suffisante pour assurer la portance nécessaire et ainsi maintenir l’avion en vol.

HarfangEn effet, l’objectif du projet Pi BOA Drone, est de parcourir de longues distances, l’autonomie, et par conséquent la gestion de l’energie, est donc une question cruciale. C’est pourquoi je m’oriente plutôt vers un drone avion. En terme de design, j’aime beaucoup les empennages bi-poutre comme pour le drone Harfang d’EADS.

D’où un premier croquis du drone que j’image réaliser :

Pi-BOA-Drone_small

Pi BOA Drone

Qui dit drone, dit moteurs, servos moteurs, capteurs, accéléromètres, gyroscopes, gps,… c’est à dire beaucoup de composants électroniques avec lesquels il va falloir communiquer. Heureusement pour nous, le Raspberry Pi est doté d’un port GPIO (General Purpose Input/Output) 🙂

pi_gpioCet articles servant d’introduction au projet, je ne vais pas détailler ici le fonctionnement de ces pines. Sachez toutefois que le port GPIO du Pi supporte plusieurs types d’interfaces. Pour plus de détails, consulter cette page : http://elinux.org/RPi_Low-level_peripherals

Electronique

Contrairement aux projets Pi TimeLapse, Pi CarJukeBox et Pi HomeDashScreen, nous aurons ici besoins de compétences en électronique. Mes connaissances dans ce domaine sont, pour le moment, très limitées. Pour comprendre comment les choses fonctionnent, je me base sur des livres que j’ai acheté pour l’occasion, ainsi que sur ce que je trouve sur le web.

C’est pourquoi, je lance un appel à l’aide 🙂 Tous ceux qui sont intéressés par le projet et qui ont des compétences en électroniques sont invités à intervenir pour apporter des explications/informations/astuces ou corriger d’éventuelles erreurs 🙂

Aéronautique

Puisqu’il s’agit d’un avion, il va également falloir comprendre les notions de bases de l’aéronautique pour nous permettre de réaliser le corps et les ailes du drone ainsi que son système de propulsion.

Pire que l’électronique, mes connaissances dans ce domaine sont proches du néant 🙁 J’en appelle donc aux passionnés de modélismes et autres professionnels de l’aéronautique et vous encourage à intervenir sur les différents articles 🙂

Démarrage du projet

A l’heure d’aujourd’hui, je n’ai aucune certitude quant à la faisabilité du projet, et je n’ai qu’une vague idée de la manière dont il faut procéder 🙂 Même pour la configuration de l’avion, son design, le nombre de moteurs, ses caractéristiques et sa taille, rien n’est encore fixé, tout est à l’étude 🙂

Ce dont je suis certain, c’est que ce projet sera très instructif et passionnant 🙂

Compte tenu de la quantité de choses à comprendre pour la réalisation d’un drone de ce type piloté par un Pi, je vais aborder les différentes problématiques les unes après les autres. Tout ce qui touchera à l’utilisation du port GPIO, fera l’objet d’un article dédié publié dans la catégorie GPIO du menu principal de ce blog.

Une fois que nous aurons tous les éléments pour contrôler les différents composants, je poursuivrai cet article en expliquant de manière très didactique comment réaliser le drone et le piloter. Comme pour les autres projets, je tâcherai d’établir une liste complète du matériel à acheter ainsi qu’une estimation du prix total. Nous aborderons également les problématiques juridiques liées au pilotage d’un drone sur le territoire français.

A suivre 🙂

Note sur la réglementation relative aux UAV en France

Il est clair que les contraintes administratives et autres règlementations sont ultra restrictives quant au vol des drones et autres UAV en France. Dans tous les cas, je n’ai pas l’intention de faire quelque chose d’illégale, je ferai le nécessaire pour être en règle. S’il savère qu’il est impossible d’obtenir une autorisation pour faire voler mon drone en France, alors je me limiterai à des vols sur propriétés privées, voire dans mon salon si il le faut -_-. Il est certain que je ne vais pas m’arrêter de réfléchir à la conception d’un drone simplement parce que « c’est interdit »… D’ailleurs ce n’est pas « interdit », c’est simplement réglementé ! Il s’agit de se conformer à la réglementation 🙂

Pour le moment, je suis plus concentré sur le challenge technique, je n’en suis pas encore à faire voler quelque chose :)

Par ailleurs, l’idée du projet est bien de faire un drone « home made » et « from scratch ». Ce n’est pas tant de faire voler un drone qui m’intéresse (je pourrais en acheter un…), mais plutôt la partie « ingénierie ». Construire un drone autonome fait appelle à des technos et des compétences très variées, c’est cela qui m’intéresse. C’est comme pour les Légos, une fois que c’est construit, ça n’a plus vraiment d’intérêt ;)

Pour terminer, cela me parait évident de ne pas passer au dessus des zones habitées ni au dessus des aérodromes ^^ Il y a un minimum de bon sens à avoir, et il faut prévoir un itinéraire sans danger. J’ajouterai que dans tous les cas, je ne vais pas lancer mon drone et espérer qu’il arrive à bon port… Je le suivrai de près en voiture avec tout le matériel nécessaire pour le localiser en temps réel :)

Maintenant que ces questions législatives et oh combien barbantes ont été abordées, je vous propose d’en revenir aux problématiques techniques :)

12 – En résumé

IMG_5413Ce dashscreen est accroché au mur de mon séjour depuis presque un an maintenant, et je m’en sers tous les jours 🙂 L’affichage de l’heure et de la date en fait une horloge pratique et très lisible depuis toute la pièce. L’affichage de la météo est également une information utile au quotidien. Quant à la Terre et la Lune, je reconnais que l’utilité est moindre, mais je trouve cela vraiment chouette :). Si ce n’est pas votre truc, vous pouvez facilement remplacer ces images par des photos, pour ajouter une fonction « cadre photo numérique » intégrée à votre dashscreen 😉

Les autres modules, ping, TeamSpeak, bande passante et VPN me sont utiles pour surveiller ce qui se passe sur mon réseau et être alerté des pannes et autres problèmes qui peuvent survenir.

Juste au dessus du module graphique de la bande passante, j’ai intégré un graphique du nombre de visite quotidienne de ce blog 🙂 J’utilise GAPI pour récupérer les statistiques de Google Analytics, puis JSAPI (Google Charts) pour créer le graphique.

Pour les modules, le principe est toujours le même :

  1. une <div> avec un id dans le fichier index.php
  2. une feuille de style style.css pour positionner la div en question et gérer la mise en forme des données affichées
  3. une fonction javascript dans le fichier javascript.js qui lance une requête AJAX à intervalle régulier
  4. une ligne dans le fichier ajax.php pour appeler la bonne fonction PHP
  5. une fonction PHP dans le fichier inc.php pour générer le code HTML pour les images à afficher

Télécharger les sources

Vous pouvez télécharger toutes les sources ici : PiHomeDashScreen

Note : Vous devrez adapter le code à vos besoins.

Etendre le projet ?

Il sera vraiment intéressant de répertorier tous les modules créer sur ce principe par tous les utilisateurs qui se lance dans la réalisation d’un dashscreen. Nous pourrions mettre en place un « dépôt » pour stocker et partager tous les modules existants 🙂 Si cela intéresse du monde, n’hésitez pas à foncer 🙂

Nous pourrions également proposer une appli en ligne avec tous ces modules pour que le Pi n’est qu’à pointer sur une URL pour afficher une page web avec différentes options et modules activés/désactivés 😉

Remerciements

J’aimerai remercier toutes les personnes qui sont intervenues en commentaire ou sur forum, ou qui m’ont contacté directement par mail. Merci pour l’intérêt que vous portez à ce projet, ainsi que pour vos questions, remarques et astuces qui ont contribué à améliorer le projet. Merci également pour les erreurs qui m’ont été remontées avec beaucoup d’indulgence 😉

Le matériel

Un Pi et un écran suffisent pour réaliser ce projet. Vous pouvez choisir le type et la taille d’écran que vous souhaitez. Vous pouvez brancher votre Pi sur votre télé pour avoir un affichage en grand dans votre salon, ou utiliser un tout petit écran de 7″ à 10″ pour vous créer un réveil high-tech (l’idée m’a été soufflée sur un forum 🙂 ). Vous pouvez également étendre les fonctionnalités de ce dashscreen en ajoutant du son, ou un écran tactil pour interagir avec les informations affichées.

Technos et logiciels utilisés

  • Linux, Raspbian
  • script bash
  • Apache
  • PHP5
  • HTML & CSS
  • JavaScript
  • netcat
  • Xplanet
  • imagemagick

Sommaire

Forums de discussion

10 – Module 7 – VPN

J’utilise un petit serveur VPN PPTP pour que mes amis et moi puissions facilement échanger des fichiers ou jouer ensemble en réseau 🙂 C’est très facile à mettre en place aussi bien coté serveur en installant le paquet pptpd, que coté client car c’est nativement supporté par Windows.

Ce module me permet d’afficher la liste des personnes qui sont connectées à mon serveur VPN PPTP.

jarvis_screenshot_VPNJe ne détail pas dans cet article comment installer et configurer PPTPD. Voici un tutoriel qui vous aidera à mettre en place ce type de VPN : https://help.ubuntu.com/community/PPTPServer

Le serveur pptpd étant installé sur ma gateway, il faut procéder de la même manière que pour le module graphique de la bande passante pour transférer les données sur le Pi en utilisant netcat. La seule chose de nouveau ici est la commande last qui permet de récuppérer les informations de connexion des clients du VPN.

Transférer les données vers le Pi

Côté Pi (serveur netcat) :

#!/bin/bash

### BEGIN INIT INFO
# Provides:          nc_vpn_srv
# Required-Start:
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: vpn for Jarvis
# Description:       Enable service provided by daemon.
### END INIT INFO

dst_port=12346
dst_dir=/home/jarvis/vpn
dst_file=vpn_oberon.log

nc_vpn()
{
  while [ "true" ]
  do
    nc -q 1 -u -l 12346 > $dst_dir/$dst_file < /dev/null
    sleep 5
  done
}

case "$1" in
        stop)
                echo " Stoping vpn for Jarvis..."
                killall vpn
                killall nc
                ;;
        start)
                echo " Starting vpn for Jarvis..."
                nc_vpn&
                exit 0
                ;;
        *)
                exit 1
                ;;
esac

exit 0

Côté gateway (client netcat) :

#! /bin/bash

### BEGIN INIT INFO
# Provides:          nc_vpn_clt
# Required-Start:
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: vpn for Jarvis
# Description:       Enable service provided by daemon.
### END INIT INFO

src_port=8889
dst_port=12346
dst_host=10.0.0.1

nc_vpn()
{
        while [ "true" ]
        do
                last | grep ppp | grep "logged in" | nc -q 1 -p $src_port -u $dst_host $dst_port
                sleep 5
        done
}

case "$1" in
        stop)
                echo " Stoping vpn for Jarvis..."
                killall vpn
                killall nc
                ;;
        start)
                echo " Starting vpn for Jarvis..."
                nc_vpn&
                exit 0
                ;;
        *)
                exit 1
                ;;
esac

exit 0

Excécutez ces scripts au démarrage du système en les placants dans le répertoire /etc/init.d puis exécutant la commande suivante :

update-rc.d nom_du_script.sh defaults

index.php

Une simple <div> suffit car nous voulons simplement afficher une liste d’utilisateurs :

<div id="vpn"></div>

style.css

Un petit peu de mise en forme pour faire joli 🙂

/* vpn */

div#vpn
{
  left              : 550px;
  bottom            : 10px;
  position          : absolute;
  overflow          : hidden;
  background-color  : rgba(0, 0, 0, 1);
  color : #FFF;
}

td.vpn
{
  text-align        : left;
  font-size         : 30px;
  padding           : 5px;
}

img.vpn
{
  width : 20px;
  height : 20px;
}

javascript.js

Une simple requête AJAX permet de récupérer les données à afficher.

/* VPN */

var vpn_timeout;

function vpn ()
{
  $.ajax({
    async : false,
    type: "GET",
    url: "./ajax.php",
    data: "block=vpn",
    success: function(html){
      $("#vpn").html(html);
    }
  });

  vpn_timeout = setTimeout("vpn()", 5000);
}

ajax.php

Rien de particulier pour ce module :

  /////////////////////////////////////////////////
  //  VPN PPTPD
  /////////////////////////////////////////////////

  if($block == 'vpn'){
    echo vpn();
  }

inc.php

Deux fonctions sont nécessaires pour ce module :

  • vpn_parseData() : parse le fichier envoyé à travers netcat
  • vpn() : créé un tableau HTML avec les noms des utilisateurs connectés
  /////////////////////////////////////////////////
  //  VPN PPTPD
  /////////////////////////////////////////////////

  function vpn () {

    $datas = vpn_parseData ("/home/jarvis/vpn/vpn_oberon.log");

    $html  = '';

    if(sizeof($datas) > 0){
      $html .= '<table cellspacing="0px">';
      foreach($datas as $data){
        $html .= '<tr>';
        $html .= '<td valign="middle"><img class="vpn" src="pict/vpn.png"></td><td class="vpn">'.$data[0].'</td>';
        $html .= '</tr>';
      }
      $html .= '</table>';
    }

    return $html;
  }

  function vpn_parseData ($stat_file) {
    $datas = array();
    if(filemtime($stat_file) < time()-10){return $datas;}
    $stats = fopen($stat_file, 'r');
    while (($line = fgets($stats)) !== false) {
      $explode_line = str_word_count($line, 1, "0123456789.");
      $datas[]  = $explode_line;
    }
    fclose($stats);
    return $datas;
  }

Et voilà pour ce dernier module qui s’avère très simple 🙂

9 – Module 6 – Graphique de la bande passante

Pour diverses raisons, il peut intéressant de s’avoir si notre bande passante internet est saturée ou non. Ce module affiche un historique d’environ 5 minutes de l’utilisation de la bande passante descendante (download) et montante (upload). De cette manière, je peux voir en un seul coup d’oeil si quelque chose d’anormal se passe sur mon réseau.

jarvis_screenshot_ifstat

Introduction

Ce module est de loin le plus compliqué de tous. D’une part, il va falloir récupérer le débit instantané utilisé par l’interface réseau de la gateway qui est reliée à la Box internet. Puis, il va falloir transmettre ces données au Pi sur lequel fonctionne le dashscreen. Enfin, il faudra créer un graphique pour représenter ces informations…

En effet, j’ai choisi de ne pas utiliser de soft type mrtg qui sont spécialisés pour ce genre de chose. Je préfère installer le minimum de soft, et utiliser quelques commandes de base. Pour faire quelque chose de simple (comme afficher la bande passante sur la graphique), pas besoin de sortir l’artillerie lourde 🙂 Et puis …si on ne se compliquait pas la vie, ce serait beaucoup moins drôle, n’est ce pas ? 😉

Mesurer la bande passante

ifstat est un petit outil en ligne de commande qui affiche les statistiques d’utilisation d’une interface réseau. Dans un terminal, taper la commande suivante :

ifstat -n -i eth0

Et vous obtiendrait en continue, quelque chose dans le genre :

       eth0       
 KB/s in  KB/s out
    0.45      0.06
    0.71      0.39
    2.85      0.76
    0.57      0.06
    1.86      0.19
    0.45      0.06
    0.45      0.06
    0.45      0.06
    0.57      0.06
    0.59      0.13
    0.45      0.06
    0.45      0.06
    0.59      0.26
    0.57      0.06
    1.74      0.13
    ...

Chaque seconde on obtient le débit instantané (ou presque), en KBytes/s, c’est à dire en Ko/s 🙂 C’est exactement ce qu’il nous faut 🙂 Il convient maintenant d’envoyer ces informations en continue sur notre Pi.

Transmettre les données au Pi à travers le réseau

Le moyen le plus simple de transmettre une info d’un ordinateur à un autre c’est de les envoyer dans des paquets UDP… C’est tellement trivial qu’il ma fallu plusieurs jours avant d’en avoir l’idée !

La commande netcat est tout à fait appropriée pour ce type d’opération. Sur une machine A qui joue le rôle de serveur faites :

nc -u -l 12345
  • -u : pour utiliser l’UDP
  • -l : pour passer en mode écoute (serveur)
  • 12345 : un numéro de port découte

Puis sur une machine B qui joue le rôle de client, faites :

nc -p 8888 -u 10.0.0.1 12345
  • -p 8888 : un port source
  • -u : pour utiliser l’UDP
  • 10.0.0.1 : adresse IP de la machine A (serveur)
  • 12345 : port d’écoute de la machine A (serveur)

Et hop, tout ce que vous tapez au clavier sur B, s’affiche sur A 🙂

Albert Einstein disait « Tout devrait être rendu aussi simple que possible, mais pas plus ! ».

A méditer 😉

Pour transmettre les données renvoyées par la commande ifstat à travers netcat, nous utiliserons un pipe. Voici les deux scripts complets (client/serveur) pour réaliser cette opération :

  • Script serveur à exécuter sur le Pi nc_ifstat_srv.sh :
### BEGIN INIT INFO 
# Provides: nc_ifstat_srv 
# Required-Start: 
# Required-Stop: 
# Default-Start: 2 3 4 5 
# Default-Stop: 0 1 6 
# Short-Description: ifstat for Jarvis 
# Description: Enable service provided by daemon. 
### END INIT INFO

dst_port=12345
dst_dir=/home/jarvis/ifstat
dst_file=eth0.log

nc -u -l $dst_port >> $dst_dir/$dst_file&
  • Script client à exécuter sur votre gateway/routeur nc_ifstat_clt.sh  :
### BEGIN INIT INFO
# Provides:          nc_ifstat_clt
# Required-Start:
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ifstat for Jarvis
# Description:       Enable service provided by daemon.
### END INIT INFO

src_port=8888
dst_port=12345
dst_host=10.0.0.2
eth=eth0

nc_ifstat()
{
	while [ "true" ]
	do
  		ifstat -n -i $eth | nc -p $src_port -u $dst_host $dst_port
  		sleep 5
	done
}

case "$1" in
        stop)
		echo " Stoping ifstat for Jarvis..."
                killall ifstat
		killall nc
		;;
        start)
		echo " Starting ifstat for Jarvis..."
		nc_ifstat&
		exit 0	
                ;;
        *)
                exit 1
                ;;
esac

exit 0

Pour exécuter le script au démarrage de la machine, placer le dans le répertoire /etc/init.d puis lancer la commande :

update-rc.d nom_du_script.sh defaults

A ce stade, vous devriez avoir un fichier sur votre Pi dans lequel, chaque seconde, la bande passante instantanée y est ajoutée en fin de fichier 🙂 Il ne nous reste plus qu’à lire ce fichier avec un script PHP, et dessiner le graphique pour représenter les données qu’il contient 🙂

Création du graphique en PHP

Ici encore, j’aurais pu utiliser une lib graphique en PHP, en JavaScript ou en n’importe quoi d’autre. Mais au lieux de sous exploiter une usine à gaz difficilement personnalisable, j’ai préféré créer ma propre fonction graphique en PHP. Vous allez voir que c’est beaucoup plus simple que ce qu’on peut s’imaginer 🙂

Voici ma fonction imagickHisto() :

function imagickHisto ($max, $eth = '', $up_down = 'down') {

  $datas = parseData ("eth0.log", $up_down);

  $width            = 304; // largeur du graphique
  $height           = 100; // hauteur du graphique
  $padding          = 1;
  $ticks            = 5;
  $background_color = '#000'; // couleur du fond
  $axes_color       = '#555'; // couleur des axes

  if($up_down == 'down'){
    $data_color       = '#1D1'; // couleur du graphique pour le download
  }
  else{
    $data_color       = '#D11'; // couleur du graphique pour l'upload
  }

  $nb_values        = $width - 2*$padding - 2;
  $max_value        = $height - 2*$padding - 4;

  $nb_datas         = sizeof($datas);
  $trim             = $nb_values - $nb_datas;

  if($trim < 0){$trim = 0;}

  $image = new Imagick();
  $image ->newImage( $width, $height, new ImagickPixel($background_color) );
  $draw  = new ImagickDraw();
  $draw->setStrokeColor( new ImagickPixel($axes_color) );

  $xx1    = $padding;
  $xy1    = $height - $padding - 1;
  $xx2    = $width - $padding - 1;
  $xy2    = $xy1;
  $yx1    = $xx1;
  $yy1    = $xy1;
  $yx2    = $yx1;
  $yy2    = $padding;
  $half_y = $height/2;
  $half_x = $width/2;

  $draw->line  ( $xx1, $xy1, $xx2, $xy2 );
  $draw->line  ( $yx1, $yy1, $yx2, $yy2 );

  $draw->line  ( $yx1, $yy2, $yx1+$ticks, $yy2 );
  $draw->line  ( $yx1, $half_y, $yx1+$ticks, $half_y );

  $draw->setStrokeColor( new ImagickPixel($data_color) );

  $first_x = $xx1 + 1 + $trim;
  $last_x  = $xx2 - 1;
  $first_y = $xy1 - 1;
  $last_y  = $yy2 + 1;

  for($i=0;$i<$nb_values;$i++){
    if(isset($datas[$i])){
      $value   = $datas[$i]*$max_value/$max;
      $value_y = $first_y - $value;
      $value_x = $first_x + $i;
      $draw->line  ( $value_x, $first_y, $value_x, $value_y );
    }
  }

  $image->drawImage( $draw );

  $text_draw = new ImagickDraw();
  $text_draw->setFillColor($axes_color);
  $text_draw->setFontSize( 12 );
  $image->annotateImage($text_draw, $half_x-20, $padding+10, 0, "$eth - $up_down");

  $image->setImageFormat( "png" );
  header( "Content-Type: image/png" );
  echo $image;
  exit;
}

Veuillez accepter mes excuses pour le manque cruel de commentaire dont fait l’objet cette fonction. Pour résumer, la fonction prend trois paramètres :

  • $max : la valeur max (en Ko) pour borner le graphique. Par exemple, mon débit réel maximum atteint 1800 Ko/s. Je choisie donc $max = 2000.
  • $eth : nom de l’interface (exemple eth0)
  • $up_down : « up » ou « down » pour spécifier la couleur du graphique ainsi que les données à afficher issue de ifstat

La fonction lit un tableau de donnée renvoyé par la fonction parseData(), puis dessine sur le graphique une barre de 1px de large par donnée. Avec une largeur de 300px, on peut donc afficher 5 minutes d’historique de données 🙂

Voici la fonction parseData() dont le rôle est de lire le fichier contenant les données issues de la commande ifstat :

  function parseData ($stat_file, $up_down) {
    $datas = array();
    if(filemtime($stat_file) < time()-10){return $datas;}
    $stats = fopen($stat_file, 'r');
    while (($line = fgets($stats)) !== false) {
      $explode_line = str_word_count($line, 1, "0123456789.");
      if($up_down == 'down') {
        $datas[]  = $explode_line[0];
      }
      else{
        $datas[]  = $explode_line[1];
      }
    }
    fclose($stats);
    $datas = array_slice($datas, -300);
    return $datas;
  }

Cette fonction prend deux paramètres :

  • $stat_file : fichier à parser
  • $up_down : « up » ou « down » pour distinguer les données d’upload et de download

Pour la suite, nous reprennons la même démarche que pour les autres modules 🙂

index.php

Il faut une div par graphique ; nous en ajoutons donc deux au fichier index.php, une pour l’upload et une pour le download.

 <div id="ifstat_eth0_up"><img id="img_eth0_up" src="pict/blank.png"></div>
 <div id="ifstat_eth0_down"><img id="img_eth0_down" src="pict/blank.png"></div>

Comme pour le module Xplanet, il convient d’initier la source des balises images <img> avec une image vide blank.png.

style.css

Il suffit ici de positionner nos deux <div> :

/* ifstat */

div#ifstat_oberon_up
{
  right             : 20px;
  bottom            : 20px;
  position          : absolute;
  overflow          : hidden;
  background-color  : rgba(0, 0, 0, 1);
}

div#ifstat_oberon_down
{
  right             : 340px;
  bottom            : 20px;
  position          : absolute;
  overflow          : hidden;
  background-color  : rgba(0, 0, 0, 1);
}

javascript.js

Une simple requête AJAX permet de récupérer les graphiques à afficher.

/* ifstat */

var ifstat_timeout;

function ifstat () {

  var now             = new Date().getTime();

  var url_down = "ajax.php?block=ifstat&eth=wan&up_down=down&max=2000&hour="+now;
  var img_eth0_down = $("<img />").attr("src", url_eth0_down);
  $("#img_eth0_down").attr("src", url_eth0_down);

  var url_up   = "ajax.php?block=ifstat&eth=wan&up_down=up&max=150&hour="+now;
  var img_eth0_up = $("<img />").attr("src", url_eth0_up);
  $("#img_eth0_up").attr("src", url_eth0_up);

  ifstat_timeout = setTimeout("ifstat()", 5000);
}

Même principe que pour le module Xplanet, il convient de précharger les images avant de les afficher. Je fixe le délais de rafraichissement à 5 secondes, ce qui est suffisant.

ajax.php

Le code à ajouter dans ce fichier reste élémentaire comme pour les autres modules. Il ne faut toutefois pas oublier de prendre en compte les paramètres de la fonction imagickHisto() :

  /////////////////////////////////////////////////
  //  IFSTAT
  /////////////////////////////////////////////////

  if($block == 'ifstat'){
    imagickHisto ($_REQUEST['max'], $_REQUEST['eth'], $_REQUEST['up_down']);
  }


inc.php

Dans ce fichier, il suffit de copier-coller les fonctions imagickHisto() et parseData() qui ont été décrites plus haut dans cet article.

Voilà le rendu final en gros plan, lorsque la bande passante est très sollicitée :

ifstat

8 – Module 5 – TeamSpeak

Si vous ne connaissez pas TeamSpeak, il s’agit d’un logiciel d’audioconférence qui permet à plusieurs personnes de discuter via Internet (pour plus d’informations http://fr.wikipedia.org/wiki/TeamSpeak). Ce module sert à afficher l’état du serveur TeamSpeak (allumé/éteint) ainsi que la liste des personnes qui y sont connectées.

jarvis_screenshot_TS3Pour obtenir ces informations j’utilise TeamSpeak 3 PHP Framework qui est téléchargeable gratuitement. Cette grosse lib PHP permet d’accéder à toutes les fonctionnalités du serveur TeamSpeak3. Que demande le peuple ? 🙂

Il suffit de télécharger et décompresser TeamSpeak 3 PHP Framework à la racine de votre répertoire web.

index.php

Comme pour les autres modules, une seule <div> suffit. Vous commencez à avoir l’habitude 😉

 <div id="ts3"></div>

La balise reste vide, et sera « remplie » par la fonction JavaScript…

style.css

Feuille de style minimaliste pour ce module :

/* ts3 */

div#ts3
{
  left              : 340px;
  bottom            : 10px;
  position          : absolute;
  overflow          : hidden;
  background-color  : rgba(0, 0, 0, 1);
  color             : #FFF;
  font-weight       : bold;
  text-align        : center;
}

td.ts3_user
{
  text-align        : left;
  font-size         : 30px;
  padding-left      : 10px;
}

javascript.js

Encore une fois, une simple requête AJAX permet de récupérer les informations à afficher.

/* TS3 */

var ts3_timeout;

function ts3 ()
{
  $.ajax({
    async : false,
    type: "GET",
    url: "./ajax.php",
    data: "block=ts3",
    success: function(html){
      $("#ts3").html(html);
    }
  });

  ts3_timeout = setTimeout("ts3()", 10000);
}

Le délai de rafraichissement est fixé à 10 secondes pour voir rapidement qui se connecte/déconnecte du serveur.

ajax.php

Cela se passe d’explications…

  /////////////////////////////////////////////////
  //  TS3
  /////////////////////////////////////////////////

  if($block == 'ts3'){
    echo ts3();
  }

inc.php

C’est ici que nous utilisons TeamSpeak 3 PHP Framework.

Dans un premier temps j’ouvre une socket sur le port 30033 (comme pour le Module 4 – Ping de serveur) pour vérifier que le serveur TeamSpeak tourne bien. Si oui, alors j’affiche la bannière du serveur (l’image triton_ts3.png), puis j’utilise  TeamSpeak 3 PHP Framework pour récupérer la liste et l’état des utilisateurs connectés 🙂

  /////////////////////////////////////////////////
  //  TS3
  /////////////////////////////////////////////////

  function ts3 () {

    $host_ip    = '10.0.0.1';
    $host_port  = '30033';
    $socket     = 0;
    $socket     = @fsockopen($host_ip, $host_port, $errno, $errstr, 3);
    $html       = '';

    if($socket && !$errno){
      require_once("./TS3_PHP_Framework-1.1.12/libraries/TeamSpeak3/TeamSpeak3.php");
      $ts3_ServerInstance = TeamSpeak3::factory("serverquery://login:password@10.0.0.1:10011/");
      $ts3_VirtualServer  = $ts3_ServerInstance->serverGetById(1);

      $html .= '<img width="200px" src="pict/triton_ts3.png" style="margin-bottom : 10px;">';
      $html .= '<table cellspacing="0px" cellpadding="0px">';
      foreach($ts3_VirtualServer->clientList() as $client){
        if($client["client_unique_identifier"] == 'serveradmin'){continue;}
        $html .= '  <tr>';
        $html .= '    <td valign="middle">';
        $html .= '      <img style="width : 20px;" src="./TS3_PHP_Framework-1.1.12/images/viewer/'.$client->getIcon().'.png" alt="">';
        $html .= '    </td>';
        $html .= '    <td valign="middle">';
        $html .= '      '.htmlspecialchars($client);
        $html .= '    </td>';
        $html .= '  </tr>';
      }
      $html .= '</table>';
    }

    return $html;
  }

Ce module est très simple à réaliser grâce à la lib  TeamSpeak 3 PHP Framework 🙂