Créer un serveur Web Lighttpd sur la brique EV3

Pourquoi installer un serveur Web sur la brique EV3

La brique EV3 étant utilisée pour construire des robots à l'aide de briques Lego, la question peut se poser. Mais, OUI, il peut y avoir un intérêt à installer un serveur Web sur la brique.
En effet, les robots Lego Mindstorm disposent de nombreux capteurs permettant de collecter des données dans son environnement. Ces données peuvent être exploitées par programmation, ou statiquement, a posteriori. Mais l'existence d'un serveur Web permet
  • Lorsqu'on veut consulter des données collectées par le capteurs en temps réel.
  • Lorsqu'on veut commander un robot à distance.
Le serveur Web peut être consulté à distance avec un navigateur et le langage HTML permet de créer des interfaces conviviales.

Installation du serveur Web

Pré-requis

Choix du serveur Web

La version de Linux installée sur la brique avec la distribution EV3Dev2 est Debian (Stretch au moment de la rédaction de cet article). Cette distribution dispose d'une version apache2 installable par l'utilitaire apt. Cependant cette version de serveur Web, très complète par ailleurs, est très gourmande en ressource. Aussi est-il préférable d'utiliser une version allégée plus compatible avec les limites de la  brique EV3. Ligttpd est un excellent compromis.

Installation de Lighttpd

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: Fri May  1 16:45:18 2020 from 192.168.1.12
robot@ev3dev:~$ sudo apt update
. . .
robot@ev3dev:~$ sudo apt upgrade
. . .
robot@ev3dev:~$ sudo apt install lighttpd
. . .
robot@ev3dev:~$ sudo reboot

Test de l'installation

Après avoir redémarré la brique EV3, et s'être connecté en SSH, quelques opérations permettent de vérifier que le serveur Web fonctionne.
Tout d'abord, on peut vérifier que le service Lighttpd est bien lancé automatiquement au démarrage :
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: Sat May  2 07:59:40 2020 from 192.168.1.12
robot@ev3dev:~$ sudo service --status-all
[sudo] password for robot:
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ + ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$
Si le serveur web est installé et opérationnel, le service lighttpd doit être présent dans la liste et un plus [+] doit se trouver devant.
Si tel est le cas, il est possible d'invoquer le serveur Web, à partir d'un ordinateur, avec n'importe quel navigateur Web, en tapant l'adresse IP de la brique (192.168.1.150 dans l'exemple). L'adresse IP de la brique est affichée en haut de l'écran LCD de celle-ci. Ce n'est possible, évidemment, que si la brique est connectée au même réseau que l'ordinateur. Si tout se passe bien, la page d'accueil par défaut de lighttpd par défaut s'affiche.

Configuration du serveur Web

Activer ou désactiver le service lighttpd

Le service lighttpd utilise des ressources de la brique. Ce qui peut être gênant pour un projet gourmand en ressources, mais pour lequel point n'est besoin d'un serveur Web. Pour ne pas avoir à désinstaller puis à réinstaller le service ligghttp en fonction des besoin, il est plus simple de l'arrêter, ou de le redémarrer à volonté. Ceci se fait grâce à la commande Linux service déjà utilisée pour vérifier que le service était installé et opérationnel.
robot@ev3dev:~$ sudo service --status-all
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ + ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$ sudo service lighttpd stop
robot@ev3dev:~$ sudo service --status-all
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ - ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$ sudo service lighttpd start
robot@ev3dev:~$ sudo service --status-all
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ + ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$

La présence du service dans la liste prouve que celui-ci est installé. Mais lorsqu'il est précédé par un [-] signifie qu'il est arrêté alors que s'il est précédé par un [+], c'est qu'il est opérationnel.

Désactiver ou activer le service lighttpd au démarrage

Le problème des commandes précédentes est que lorsque le système EV3Dev2 redémarre, le service ligttpd est à nouveau actif. 
Pour le désactiver de façon persistante au démarrage  :
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: Sat May  2 12:36:47 2020 from 192.168.1.12
robot@ev3dev:~$ sudo service --status-all
[sudo] password for robot:
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ + ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$ sudo systemctl disable lighttpd
Synchronizing state of lighttpd.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable lighttpd
robot@ev3dev:~$

Pour l'activer de façon persistante au démarrage :
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: Sat May  2 13:33:39 2020 from 192.168.1.12
robot@ev3dev:~$ sudo service --status-all
[sudo] password for robot:
 [ - ]  alsa-utils
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ + ]  connman
 [ - ]  console-setup.sh
 [ + ]  dbus
 [ + ]  fake-hwclock
 [ - ]  firstboot
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ - ]  lighttpd
 [ - ]  mosquitto
 [ + ]  networking
 [ - ]  nfs-common
 [ + ]  ntp
 [ + ]  procps
 [ - ]  rpcbind
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ - ]  sudo
 [ + ]  udev
 [ - ]  x11-common
robot@ev3dev:~$ sudo systemctl enable lighttpd
Synchronizing state of lighttpd.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable lighttpd
robot@ev3dev:~$
A remarquer que, quelque soit l'état du service lighttpd au démarrage, celui-ci peut être activé ou désactivé à volonté avec la commande service.

Modifier les droits sur le répertoire /var/www/html

Pour que les pages Web (les fichiers HTML) soient accessibles par un navigateur Web, elles doivent se trouver dans le répertoire /var/www/html. Après l'installation, ce répertoire est configuré pour appartenir à l'utilisateur root et faire partie du groupe root
robot@ev3dev:~$ ls -l /var/www
total 8
drwxr-xr-x 2 root root 4096 Jan 14  2017 cgi-bin
drwxr-xr-x 2 root root 4096 May  1 16:47 html
robot@ev3dev:~$
En conséquence toute modification dans ce répertoire va nécessiter de passer en mode super-utilisateur. Ce qui va être fastidieux. Il est donc habituel de modifier les droits sur ce répertoire pour permettre à des utilisateurs de créer des pages Web avec une éditeur de texte comme vi ou nano. Pour cela il est d'une bonne pratique de créer un nouveau groupe à cet usage, par exemple www-data, et de lui donner les droits de propriété sur toute l'arborescence /var/www/html. Pour qu'un utilisateur puisse créer des pages Web (ce sont en fait des fichiers texte dont l'extension est html), il suffira qu'il appartienne à ce groupe.
robot@ev3dev:~$ sudo chown -R www-data:www-data /var/www
robot@ev3dev:~$ sudo chmod -R g+rwx /var/www
robot@ev3dev:~$ ls -l /var/www
total 8
drwxrwsr-x 2 www-data www-data 4096 Jan 14  2017 cgi-bin
drwxrwxr-x 2 www-data www-data 4096 May  1 16:47 html
robot@ev3dev:~$ sudo usermod -a -G www-data robot
robot@ev3dev:~$ groups robot
robot : robot tty dialout cdrom floppy sudo audio www-data video plugdev users ev3dev input i2c bluetooth
robot@ev3dev:~$
  • la commande chown change le propriétaire du répertoire /var/www/html. L'option -R effectue cette opération de façon récursive  sur le répertoire et sur tout son contenu. Le nouveau propriétaire est maintenant www-data.
  • La commande chmod accorde les droits en lecture, écriture et exécution (pour pouvoir créer de nouveaux sous-répertoires) sur le répertoire /var/www/html  et son contenu (option -R) à tous les membres du groupe www-data.  Ce qui peut être vérifié par la commande ls -l qui suit.
  • La commande usermod ajoute (option -a) à l'utilisateur robot le groupe www-data aux groupes (option -G www-data) dont il est déjà membre. Ce qui peut être vérifié par la commande groups robot qui suit.

Activer les scripts CGI

Par défaut, la possibilité d'exécuter des script CGI est désactivée sur Lighttpd. Comme le suggère la page d'accueil index.lighttpd.html, le module CGI de Lighttpd doit être activé explicitement par la commande lighty-enable-mod cgi.
robot@ev3dev:~$ sudo lighty-enable-mod cgi
[sudo] password for robot:
Enabling cgi: ok
Run "service lighttpd force-reload" to enable changes
robot@ev3dev:~$

Cette commande effectue une copie du fichier 10-cgi.conf du répertoire /etc/lighttpd/conf-available dans le répertoire /etc/lighttpd/conf-enabled. Ce fichier contient la configuration du module CGI. Par défaut, par soucis de sécurité, ce fichier n'est pas configuré pour exécuter des script Python. En effet, activer cette option permet d'effectuer à peu près tout ce qu'on veut sur le système de fichiers de la brique EV3. Le robot fonctionnant sur un réseau domestique, cela n'a pas d'importance. Si l'on veut activer les scripts Python,  il faut modifier 10-cgi.conf avec un éditeur de texte comme nano ou vi.
# /usr/share/doc/lighttpd/cgi.txt

server.modules += ( "mod_cgi" )

$HTTP["url"] =~ "^/cgi-bin/" {
        cgi.assign = ( ".py"  => "/usr/bin/python3" )
}

## Warning this represents a security risk, as it allow to execute any file
## with a .pl/.py even outside of /usr/lib/cgi-bin.
#
#cgi.assign      = (
#       ".pl"  => "/usr/bin/perl",
#       ".py"  => "/usr/bin/python",
#)
Attention ! Sur la brique EV3, la commande python exécute la version 2.7 de l'interpréteur. Si le script est écrit pour la version 3.x de Python, il vaut mieux le préciser.
Comme l'indique le message affiché à l'activation du module CGI, pour que les modifications apportées à Lighttpd, le service doit être redémarré :
robot@ev3dev:~$ sudo service lighttpd force-reload
robot@ev3dev:~$

Ma première page Web

La configuration du serveur Web étant achevée, il est maintenant possible de créer des pages Web. Ce sont des fichiers texte dont l'extension est .html. Ceux-ci doivent être rangés dans le répertoire géré par les serveur Web, à savoir le répertoire /var/www/html. Leur contenu doit respecter quelques règles de syntaxe.
L'objet de cet article ne porte pas sur le langage HTML. D'autant qu'il existe une multitude de tutoriels sur Internet. Il suffira de créer ici une page d'accueil et de vérifier son fonctionnement.
La page d'accueil d'un site web doit avoir index.html comme nom. Voici le contenu de cette page :
<!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 <b>/var/www/html</b>.</p>
</body>
</html>
Ce fichier peut être créé avec n'importe quel éditeur de texte comme vi ou nano. Et il doit être créé dans le répertoire /var/www/html.
En tapant l'adresse IP de la brique (192.168.1.150 dans l'exemple) la page d'accueil par défaut de lighttpd est remplacée par celle qui vient d'être créée.
La page de lighttpd, qui contient des informations techniques importantes, n'est pas perdue pour autant. Elle se trouve dans le fichier index.lighttpd.html. Elle peut être affichée en précisant ce nom derrière l'adresse IP :

Mon premier script CGI en Python

Le problème des pages Web est quelles sont statiques. C'est à dire que l'on ne peut afficher que ce qu'elles contiennent. Il est vrai, comme exposé dans l'article intitulé « Modification du contenu d'une page Web en Python », que l'on peut modifier leur contenu par programmation. Mais il est possible, grâce à la technologie CGI (Common Gateway Interface), de construire des pages Web dynamiques par programmation de scripts avec un langage informatique. Et l'utilisation du langage peut dépasser de très loin, la construction HTML de pages Web. Il est aussi possible de déclencher n'importe quel action comme accéder à des fichiers ou à une base de données et accéder aux données saisies dans un formulaire. Ce qui permet même d'envisager de contrôler un robot à distance.
Si PHP est le langage le plus utilisé, CGI, correctement configuré, permet d'utiliser à peu prêt tous les langages informatiques pour scripter en ajoutant quelques lignes au fichier 10-cgi.conf, du moment que l'interpréteur de ce langage est installé sur le système. Si les pages Web statiques doivent être rangées dans le répertoire /var/www/html, les scripts CGI doivent l'être dans le répertoire /var/www/cgi-bin. Cette séparation permet d'assurer la sécurité du système pour accorder des droits différents et éviter ainsi les dégâts que pourraient causer des scripts malveillants.
Dans cet exemple, une page Web va être utilisée pour afficher la date et l'heure du système.
Ci-dessus, le serveur Web Lighttpd a été configurer pour fonctionner en Python (version 3.x). C'est donc dans ce langage que va être écrit le script de cet exemple.

Conclusion

Le serveur Web Lighttpd est une alternative plus légère à Apache pour installer un serveur Web sur la brique EV3. Ce logiciel est vu par Debian comme un service. Celui-ci peut donc être activé et désactivé à volonté comme n'importe quel autre service Debian grâce aux commandes service, ou systemctl lorsque la persistance est nécessaire. Ce service sert des pages statiques au format HTML (ou en XHTML dans l'exemple proposé), mais aussi de scripts CGI si des données dynamiques collectées par un robot doivent être affichées, le programme du robot devra soit maintenir le code HTML de la page Web concernée grâce à l'API etree, soit en construisant dynamiquement la réponse à une requête par un script CGI. Encore faudra-t-il que l'utilisateur procède au rafraîchissement manuel de la page dans son navigateur. Cela fera l’objet d'un article futur.

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