Aller au contenu

Traitement d’image pour la détection de tag Aruco avec Opencv en python : 4/4 

Au dernier cours nous avons réalisé la détection de tag aruco sur une image et une vidéo à l’aide de la bibliothèque Aruco fournie par Opencv et de calculer la distance entre un tag de référence et un autre tag.

L’objectif de ce cours est de voir comment il est possible de faire communiquer des informations entre une Raspberry pi et un ordinateur en utilisant le principe d’API avec Flask

Slides du cours

Le protocole HTTP

La communication entre le navigateur et le serveur se fait en deux temps :

Communication entre navigateur et serveur
  • Le navigateur effectue une requête HTTP
  • Le serveur traite la requête puis envoie une réponse HTTP

Requête HTTP

Une requête HTTP est un ensemble de lignes envoyé au serveur par le navigateur. Elle comprend :

  • Une ligne de requête : c’est une ligne précisant le type de document demandé, la méthode qui doit être appliquée et la version du protocole utilisée. La ligne comprend trois éléments devant être séparés par un espace :
    • Un verbe HTTP (GET, POST, PUT).
    • L’hôte (http://server.org)
    • Le point de terminaison /path/to/resource
    • La version du protocole utilisé par le client (généralement HTTP/1.0)
  • Les champs d’en-tête de la requête : il s’agit d’un ensemble de lignes facultatives permettant de donner des informations supplémentaires sur la requête et/ou le client (Navigateur, système d’exploitation…).
  • Le corps de la requête : c’est un ensemble de lignes optionnelles devant être séparées des lignes précédentes par une ligne vide et permettant par exemple un envoi de données par une commande POST lors de l’envoi de données au serveur par un formulaire.

Réponse HTTP

Une réponse HTTP est un ensemble de lignes envoyées au navigateur par le serveur. Elle comprend :

  • Une ligne de statut : c’est une ligne précisant la version du protocole utilisé et l’état du traitement de la requête à l’aide d’un code et d’un texte explicatif.
    • La version du protocole utilisé
    • Le code de statut
    • La signification du code
  • Les champs d’en-tête de la réponse : il s’agit d’un ensemble de lignes facultatives permettant de donner des informations supplémentaires sur la réponse et/ou le serveur.
  • Le corps de la réponse : il contient le document demandé

Les codes de réponse

Ce sont les codes que vous voyez lorsque le navigateur n’arrive pas à vous fournir la page demandée. Le code de réponse est constitué de trois chiffres : le premier indique la classe de statut et les suivants la nature exacte de l’erreur.

CodeMessageDescription
10xMessage d’informationCes codes ne sont pas utilisés dans la version 1.0 du protocole
20xRéussiteCes codes indiquent le bon déroulement de la transaction
200OKLa requête a été accomplie correctement
201CREATEDElle suit une commande POST, elle indique la réussite, le corps du reste du document est sensé indiquer l’URL à laquelle le document nouvellement créé devrait se trouver.
202ACCEPTEDLa requête a été acceptée, mais la procédure qui suit n’a pas été accomplie
203PARTIAL INFORMATIONLorsque ce code est reçu en réponse à une commande GET, cela indique que la réponse n’est pas complète.
204NO RESPONSELe serveur a reçu la requête mais il n’y a pas d’information à renvoyer
205RESET CONTENTLe serveur indique au navigateur de supprimer le contenu des champs d’un formulaire
206PARTIAL CONTENTIl s’agit d’une réponse à une requête comportant l’en-tête range. Le serveur doit indiquer l’en-tête content-Range
30xRedirectionCes codes indiquent que la ressource n’est plus à l’emplacement indiqué
301MOVEDLes données demandées ont été transférées à une nouvelle adresse
302FOUNDLes données demandées sont à une nouvelle URL, mais ont cependant peut-être été déplacées depuis…
303METHODCela implique que le client doit essayer une nouvelle adresse, en essayant de préférence une autre méthode que GET
304NOT MODIFIEDSi le client a effectué une commande GET conditionnelle (en demandant si le document a été modifié depuis la dernière fois) et que le document n’a pas été modifié il renvoie ce code.
40xErreur due au clientCes codes indiquent que la requête est incorrecte
400BAD REQUESTLa syntaxe de la requête est mal formulée ou est impossible à satisfaire
401UNAUTHORIZEDLe paramètre du message donne les spécifications des formes d’autorisation acceptables. Le client doit reformuler sa requête avec les bonnes données d’autorisation
402PAYMENT REQUIREDLe client doit reformuler sa demande avec les bonnes données de paiement
403FORBIDDENL’accès à la ressource est tout simplement interdit
404NOT FOUNDClassique! Le serveur n’a rien trouvé à l’adresse spécifiée. Parti sans laisser d’adresse… 🙂
50xErreur due au serveurCes codes indiquent qu’il y a eu une erreur interne du serveur
500INTERNAL ERRORLe serveur a rencontré une condition inattendue qui l’a empêché de donner suite à la demande (comme quoi il leur en arrive des trucs aux serveurs…)
501NOT IMPLEMENTEDLe serveur ne supporte pas le service demandé (on ne peut pas tout savoir faire…)
502BAD GATEWAYLe serveur a reçu une réponse invalide de la part du serveur auquel il essayait d’accéder en agissant comme une passerelle ou un proxy
503SERVICE UNAVAILABLELe serveur ne peut pas vous répondre à l’instant présent, car le trafic est trop dense (toutes les lignes de votre correspondant sont occupées veuillez rappeler ultérieurement)
504GATEWAY TIMEOUTLa réponse du serveur a été trop longue vis-à-vis du temps pendant lequel la passerelle était préparée à l’attendre (le temps qui vous était imparti est maintenant écoulé…)

Flask Python

Flask est un framework web, c’est un module Python qui vous permet de développer facilement des applications web. Son noyau est petit et facile à étendre : c’est un micro-framework qui n’inclut pas d’ORM (Object Relational Manager) ou d’autres fonctionnalités.

Il possède cependant de nombreuses fonctionnalités intéressantes comme le routage d’URL, le moteur de modèles. Il s’agit d’un framework d’application web WSGI.

Contrairement au framework Django, Flask est très pythonique. Il est facile de démarrer avec Flask, car il n’y a pas de courbe d’apprentissage énorme.

En outre, il est très explicite, ce qui en augmente la lisibilité. Pour créer l’application « Hello World », vous n’avez besoin que de quelques lignes de code.

Il s’agit d’un exemple de code passe-partout.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

Si vous souhaitez développer sur votre ordinateur local, vous pouvez le faire facilement. Enregistrez ce programme sous le nom de server.py et exécutez-le avec python3 server.py.

$ python server.py
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Il démarre alors un serveur web qui n’est disponible que sur votre ordinateur. Dans un navigateur web, ouvrez localhost sur le port 5000 (l’url) et vous verrez apparaître « Hello World ».

flask

C’est un micro-framework, mais cela ne signifie pas que toute votre application doit se trouver dans un seul fichier Python. Vous pouvez et devez utiliser plusieurs fichiers pour des programmes plus importants, afin de gérer la complexité.

Embarquer sur une Raspberry

Si votre carte SD ne contient pas encore le système d’exploitation Raspberry Pi OS, ou si vous souhaitez réinitialiser votre Raspberry Pi, vous pouvez facilement installer Raspberry Pi OS vous-même. Pour ce faire, vous avez besoin d’un ordinateur doté d’un port pour carte SD – la plupart des ordinateurs portables et de bureau en ont un.

Le système d’exploitation Raspberry Pi OS via l’imageur Raspberry Pi
L’utilisation de l’imageur Raspberry Pi est le moyen le plus simple d’installer le système d’exploitation Raspberry Pi OS sur votre carte SD.

  1. Télécharger une image RasPiOS
  2. Télécharger balenaEtcher
  3. Décompresser l’archive de RasPiOS et utiliser Etcher pour flasher la carte SD

Configurer le wifi

 Il suffit de créer le fichier wpa_supplicant.conf à la racine de la partition /boot sur la carte SD :

country=fr
update_config=1
ctrl_interface=/var/run/wpa_supplicant

network={
 scan_ssid=1
 ssid="MonReseauWIFI_SSID"
 psk="MotDePasse_reseauWIFI"
}

Lancement automatique d’un script au démarrage

systemd est une suite de composants système pour la configuration et le comportement des services sur les systèmes Linux modernes. Il est identifié par un PID (identifiant de processus) de 1, car c’est le premier processus à démarrer au démarrage du système. Dans l’ensemble, le but de systemd est de vous aider à gérer et à exécuter des programmes au démarrage du système. Et c’est ce que vous utiliserez pour lancer votre programme au démarrage sur le Pi.

Comme mentionné initialement, il existe plusieurs méthodes pour exécuter des programmes au démarrage sur des systèmes Linux, tels que rc.local, cron et autostart. Cependant, systemd arrive à une meilleure solution du lot si vous souhaitez lancer des programmes GUI (interface utilisateur graphique), automatiser les applications pour qu’elles s’exécutent après le début de certains processus système ou exécuter des programmes encore et encore jusqu’à ce que votre planification fonctionne.

Comment utiliser systemd pour lancer des programmes au démarrage

systemd est une méthode légèrement plus compliquée de lancement de programmes au démarrage sur des systèmes Linux. Cependant, la flexibilité de planification qu’elle offre par rapport aux autres méthodes – celles que nous avons mentionnées ci-dessus – l’emporte totalement sur sa complexité dans tous les aspects.

La méthode systemd utilise des fichiers d’unité, qui sont un peu comme des fichiers .ini qui contiennent des informations de codage sur les périphériques, les services, les sockets, la cible de démarrage et d’autres composants système essentiels.

Les fichiers d’unité sont de différents types. Ainsi, en fonction du type de ressource que vous souhaitez déclarer, vous devez choisir un type de fichier unitaire en conséquence. Pour les besoins de ce guide, cependant, nous nous en tiendrons aux fichiers d’unité .service, qui vous permettent de gérer le comportement de démarrage des programmes et des scripts sur le système.

Vous trouverez ci-dessous une description des étapes du lancement d’un script / programme au démarrage à l’aide de systemd.

Créer un service

Pour configurer votre programme pour qu’il s’exécute au démarrage, créez un fichier d’unité de service qui indiquera à systemd quel programme exécuter et quand. Voici comment procéder.

1.Dans la fenêtre CLI, saisissez sudo nano /lib/systemd/system/display.service . Vous pouvez utiliser n’importe quel nom pour votre service tant qu’il se termine par l’extension .service.
2.Dans le fichier de service, collez les lignes de code suivantes:

[Unit]
Description=PiCounter
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/PiCounter/display.py
Restart=always
User=pi
[Install]
WantedBy=multi-user.target

Toutes vos options de configuration courantes relèvent des sections Unité et Installation , tandis que les options de configuration spécifiques au service se trouvent dans la section Service.

Voici quelques-unes des paires directive-valeur ci-dessus que vous devrez peut-être modifier:

i. After: il détermine quand démarrer le service. Le paramétrer sur network.target garantit que la valeur répertoriée – network.target dans ce cas – démarre avant de commencer l’unité en cours. Cependant, il ne dirige pas une relation de dépendance pour le service à déclencher; cela se fait via d’autres directives telles que Wants, Requiert et WantedBy.

Bien entendu, vous pouvez modifier cette valeur en fonction des exigences de votre projet. Par exemple, si vous souhaitez que votre programme s’exécute après la connexion de votre Raspberry Pi à un réseau, vous pouvez utiliser la valeur network-online.target . Vous pouvez vous référer à la documentation de Fedora sur systemd pour en savoir plus sur ces valeurs.

ii. ExecStart: il contient le chemin absolu et le nom du programme / script que vous souhaitez exécuter au démarrage. Ainsi, en fonction de ce que vous souhaitez exécuter, vous devez ajouter des valeurs pour ces deux directives.

iii. User: il identifie le nom de votre Raspberry Pi. Si vous avez changé le nom de votre Pi, vous devez mettre cette valeur pour l’utilisateur.

iv. WantedBy: C’est la manière la plus courante de spécifier le déclencheur d’une unité. En le définissant sur multi-user.target , vous pouvez établir une relation de dépendance qui exécutera le programme lorsque le contrôle du système sera transféré au shell multi-utilisateur.

De plus, cela exécute également votre programme avant le démarrage du système X-Windows de Pi, ce qui signifie que votre programme s’exécute avant même que vous vous connectiez au système. Si vous souhaitez qu’un script s’exécute avant de vous connecter à votre Raspberry Pi, cela vous permet de le faire.

Les lignes de code ci-dessus fonctionnent pour les programmes non-GUI. Cependant, si vous souhaitez exécuter un programme GUI à l’aide de systemd, vous devez ajouter le code suivant à votre fichier de service:

[Unit]
Description=PiCounter
After=network.target
[Service]
Environment=Display=:0
Environment=XAUTHORITY/home/pi/.Xauthority
ExecStart=/usr/bin/python3 /home/pi/PiCounter/display.py
Restart=always
[Install]
WantedBy=multi-user.target

Dans la paire directive-valeur ci-dessus, tout ce que vous devez modifier est la valeur de la directive ExecStart . Remplacez celui du bloc de code par le programme que vous souhaitez exécuter au démarrage. Après avoir rempli le fichier de service, appuyez sur CTRL + O pour l’enregistrer.

Testez le service

Avec le service prêt, vérifiez manuellement s’il fonctionne. Pour cela, tapez la commande suivante dans le terminal: sudo systemctl start display.service . Le service doit exécuter vos instructions avec succès.

Une fois que c’est fait, terminez-le avec sudo systemctl stop display.service .

Activer le service

Si vous avez réussi à exécuter votre programme avec succès en utilisant le service, il est temps de l’activer afin qu’il exécute votre programme automatiquement chaque fois que vous démarrez votre Raspberry Pi.

Pour ce faire, tapez sudo systemctl enable display.service dans la fenêtre du terminal. Et une fois que cela est fait, entrez sudo reboot pour redémarrer votre Pi.

Une fois que votre Raspberry Pi démarre, systemd doit exécuter votre programme selon les instructions fournies.