Créer un serveur Web statique en Python sur la brique EV3

Pourquoi installer un serveur Web sur la brique EV3

La question est légitime. En effet, la brique Lego MindStorm EV3 est utilisée pour construire des robots avec des briques Lego. Autant dire que le concept est plutôt perçu comme un jouet. Cependant, au vu de tous les capteurs et moteurs disponibles, il est possible de construire des robots extrêmement sophistiqués. D'autant qu'il est possible d'y connecter une multitude d'accessoires non Lego pour en étendre les possibilités de base. Malgré tout les données collectées par les capteurs doivent être exploitée en temps réel par le programme, et si l'on veut les consulter on ne peut que les afficher sur un écran LCD minuscule noir & blanc de 178x128 pixels. Encore faut-il courir après le robot avec une loupe si on veut y arriver.
Équiper la brique EV3 d'un serveur Web permet, entre autres, de publier des données statiques au format HTML consultables à distance sur un ordinateur à l'aide d'un navigateur Web.

Création du serveur Web

Pré-requis

Une page Web pour l'exemple

L'objet de l'article n'étant pas d'apprendre le HTML, l'objectif ici est de disposer d'une page Web pour pouvoir tester le fonctionnement du serveur Web. Le code ci-dessous n'est qu'un exemple. Il est stocké dans le fichier index.html dans le répertoire home de l'utilisateur par défaut de la brique EV3 fonctionnant sous Ev3Dev2, à savoir robot. Comme c'est un fichier texet, il peut être saisi à l'aide de n'importe quel éditeur de texte comme vi ou nano.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ma page d'accueil</title>
</head>
<body>
<h1>Titre de ma page d'accueil</h1>
<p>Ceci est le corps du texte de ma page d'accueil.</p>
<p>Le nom du fichier doit être <b>index.html</b>
et le fichier doit être rangé
dans le répertoire <i>home</i> de l'utilisateur <b>robot</b>.</p>
</body>
</html>
Après avoir créer la page Web index.html, on peut lancer très simplement un serveur Web avec Python en lançant l'instruction python3 -m http.server.
login as: robot
Using keyboard-interactive authentication.
Password:
Linux ev3dev 4.14.117-ev3dev-2.3.5-ev3 #1 PREEMPT Sat Mar 7 12:54:39 CST 2020 armv5tejl
             _____     _
   _____   _|___ /  __| | _____   __
  / _ \ \ / / |_ \ / _` |/ _ \ \ / /
 |  __/\ V / ___) | (_| |  __/\ V /
  \___| \_/ |____/ \__,_|\___| \_/

Debian stretch on LEGO MINDSTORMS EV3!
Last login: Sun May  3 12:11:54 2020 from 192.168.1.12
robot@ev3dev:~$ nano index.html
robot@ev3dev:~$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...

Sur la brique EV3, le serveur met plusieurs secondes à démarrer. Quand il est enfin opérationnel, un message de log indique que le service est démarré sur le port 8000. La page peut être consultée sur le navigateur d'un ordinateur connecté au même réseau que la brique EV3. L'url est l'adresse IP de la brique (192.168.1.150 dans l'exemple suivie du numéro de port (8000) :
En consultant la session SSH de la brique EV3, on constate que la consultation de la page à été loguée. La consultation a été effectué à partir d'un ordinateur dont l'adresse IP est 192.168.1.12 et le code retour 200 indique que la page a été transmise avec succès.
login as: robot
Using keyboard-interactive authentication.
Password:
Linux ev3dev 4.14.117-ev3dev-2.3.5-ev3 #1 PREEMPT Sat Mar 7 12:54:39 CST 2020 armv5tejl
             _____     _
   _____   _|___ /  __| | _____   __
  / _ \ \ / / |_ \ / _` |/ _ \ \ / /
 |  __/\ V / ___) | (_| |  __/\ V /
  \___| \_/ |____/ \__,_|\___| \_/

Debian stretch on LEGO MINDSTORMS EV3!
Last login: Sun May  3 12:11:54 2020 from 192.168.1.12
robot@ev3dev:~$ nano index.html
robot@ev3dev:~$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...
192.168.1.12 - - [03/May/2020 14:00:15] "GET / HTTP/1.1" 200 -

Limites... et remède

Problème avec le port utilisé

Le port par défaut utilisé par pour le serveur Web en Python est 8000. Il se peut que celui soit déjà utilisé par une autre application. Ce qui déclenche une erreur au lancement. Pour remédier à ce problème, il suffit de préciser le numéro d'un port non encore utilisé dans la ligne de commande :
robot@ev3dev:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 ...

Lancement du serveur Web dans un script bash

Comme on peut le constater, le lancement du serveur Web en Python est préemptif. Il ne rend pas la main. S'il doit être lancé dans un script bash, les instructions suivantes ne seront pas exécutées tans que le serveur Web ne sera pas arrêté. Il faut bien penser à mettre un & (ET commercial) à la fin de l'instruction dans le script pour indiquer que le serveur fonctionne en arrière-plan.

Gestion du processus du serveur Web

En mode ligne de commande, on peut également utiliser les instructions bg pour mettre le processus en arrière-plan (après l'avoir mis en pause avec Ctrl-Z) et fg pour le récupérer pour pouvoir l'arrêter par Ctrl+C.
robot@ev3dev:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 ...
^Z
[1]+  Stopped                 python3 -m http.server 8080
robot@ev3dev:~$ bg
[1]+ python3 -m http.server 8080 &
robot@ev3dev:~$ jobs
[1]-  Running                 python3 -m http.server 8080 &
robot@ev3dev:~$ fg 1
python3 -m http.server 8080
^C
Keyboard interrupt received, exiting.
robot@ev3dev:~$ jobs
robot@ev3dev:~$
  • Le serveur Web Python est lancé. Celui-ci est préemtif et ne rend pas la main.
  • Le processus peut être mis en pause en tapant Ctrl+Z.
  • La commande bg relance le processus en arrière-plan. Si plusieurs processus en arrière-plan sont déjà en train de fonctionner, on peut préciser le processus en question en ajoutant son numéro (ici le 1). Le système rend la main.
  • La commande jobs permet de lister tous les processus en cours et leur état de fonctionnement (Stopped ou Running).
  • Le contrôle d'un processus peut être repris par la commande fg. Par défaut, c'est le dernier processus utilisé qui est pris en compte. Si plusieurs processus sont en cours, il faut préciser le numéro (celui-qui se trouve entre le crochet). On perd la main.
  • Le processus peut être alors arrêté par un Ctrl+C.
  • La liste des processus en cours est vide.

Le processus s'arrête lorsqu'on quitte la session SSH

Le processus démarré comme ci-dessus est lié à la session SSH par laquelle il est lancé. Aussi lorsqu'on quitte celle-ci, tous les processus s'arrêtent automatiquement. Pour maintenir un processus en route après avoir quitter une session, il faut le lancer en le faisant précéder par nohup et le terminer par le caractère & :
robot@ev3dev:~$ nohup python3 -m http.server &
[1] 2538
nohup: ignoring input and appending output to 'nohup.out'
robot@ev3dev:~$ exit
Le problème est maintenant que si l'on veut arrêter le processus du serveur Web, celui-ci ne fait plus partie des processus que peut gérer la nouvelle session. La commande jobs affiche une liste vide. Il faut utiliser la commande ps pour repérer le processus du serveur Web et utiliser les grands moyens pour tuer le processus avec la commande kill :
login as: robot
Using keyboard-interactive authentication.
Password:
Linux ev3dev 4.14.117-ev3dev-2.3.5-ev3 #1 PREEMPT Sat Mar 7 12:54:39 CST 2020 armv5tejl
             _____     _
   _____   _|___ /  __| | _____   __
  / _ \ \ / / |_ \ / _` |/ _ \ \ / /
 |  __/\ V / ___) | (_| |  __/\ V /
  \___| \_/ |____/ \__,_|\___| \_/

Debian stretch on LEGO MINDSTORMS EV3!
Last login: Sun May  3 16:08:13 2020 from 192.168.1.12
robot@ev3dev:~$ jobs
robot@ev3dev:~$ ps -ef | grep http.server
robot     2422     1  8 16:12 ?        00:00:12 python3 -m http.server
robot     2448  2442  0 16:15 pts/0    00:00:00 grep http.server
robot@ev3dev:~$ kill 2422
robot@ev3dev:~$

On peut remarquer que le logs sont automatiquement redirigés vers le fichier nohup.out. Les affichages ne seront plus polluées par les logs du serveur Web.
A remarquer aussi que même si celui-ci fonctionne en arrière-plan, le serveur ainsi créé en Python s'arrête lorsqu'on éteint la brique EV3. Au redémarrage suivant de la brique, il faudra penser à le relancer.

Conclusion

Dans cet article, la mise en oeuvre d'un serveur Web très simple sur la brique Lego EV3 a été présenté. Pour le moment il ne permet que d'afficher des données statiques contenues dans des page Web au format HTML. Dans le prochain article, on verra que le contenu d'une page Web peut être modifier en python par programmation dans un script. Puis dans l'article suivant, on appliquera ce procédé dans le script d'un robot pour modifier les données affichées en HTML.
Cette manière de faire peut paraître un peu « bricolage ». Mais la solution a le mérite d'exister. Il existe des solutions plus « pros », comme Apache2 et Django. Mais ces logiciels sont gourmands en ressources et semblent peut appropriés pour fonctionner la brique EV3. On les réservera pour des solutions comme PiStorm ou la brique EV3 est remplacée par un Raspberry PI 3. Encore qu'il existe des solutions plus légères comme Lighttpd en alternative à Apache2 et Flask en alternative à Django adaptées à ces micro-contrôleurs.

Commentaires

Posts les plus consultés de ce blog

Connecter ev3dev2 à Internet en WiFi

Connecter Visual Studio Code à un robot MindStorm EV3 avec ev3dev-browser

Installer les modules EV3DEV2 sur Python