5 façons de créer un serveur Python sur un Raspberry Pi Partie 1

Salut, Habr.

Aujourd'hui, un grand nombre de projets domotiques (et pas seulement) utilisent le Raspberry Pi. En même temps, il est assez pratique d'avoir non seulement un accès direct à l'appareil, mais également d'utiliser un navigateur - cela vous permet d'effectuer les actions nécessaires depuis un ordinateur et un téléphone mobile, et même à distance de n'importe où dans le monde.



Supposons que nous ayons déjà un programme super Python qui fait quelque chose de très important, du clignotement d'une LED au contrôle d'une "maison intelligente" ou au moins d'une mangeoire pour chat. Je vais montrer différentes façons, du plus simple au plus complexe, comment rendre l'accès Web à une telle application en ajoutant du code.

L'article est destiné aux débutants, les pros ne trouveront probablement pas quelque chose de fondamentalement nouveau ici, mais j'espère qu'il sera utile aux débutants sous Linux. Pour ceux qui sont intéressés, continue sous la coupe.

Remarque : cet article est une sorte "d'expérience", une fois dans les commentaires ils se sont plaints qu'il n'y avait pas assez d'articles pour Habré pour les débutants. J'ai essayé de combler le vide, mais d'après les estimations, il sera clair s'il est logique de continuer dans ce format ou non.

Commençons donc.

Configurer Raspberry Pi


Espérons que le lecteur dispose d'un Raspberry Pi connecté au réseau domestique via WiFi ou Ethernet, et que le lecteur sait quelle est l'adresse IP et comment se connecter à distance au Raspberry Pi via SSH en utilisant du mastic. Nous considérerons la configuration dite sans tête - sans clavier ni moniteur. Mais avant de faire quelque chose avec le Raspberry Pi, quelques petits hacks de vie.

Astuce N1 . Pour faire quelque chose à distance avec le Raspberry Pi, vous devez configurer SSH dessus, et par défaut, il est désactivé. Vous pouvez suivre la voie traditionnelle et démarrer le configurateur standard, mais cela peut être plus simple - après l'enregistrement de l'image disque, créez simplement un fichier ssh vide (sans extension) à la racine de la carte SD. De plus, après le chargement du Raspberry Pi, SSH sera immédiatement actif.

Pour accéder à l'appareil à distance, vous devez connaître l'adresse IP du Raspberry Pi. Pour ce faire, ouvrez simplement le panneau de configuration de votre routeur, recherchez-y la liste des clients DHCP, copiez l'adresse IP souhaitée (par exemple, ce sera 192.168.1.102) et entrez la commande putty.exe pi@192.168.1.102 (pour Windows) ou ssh pi @ 192.168.1.102 pour Linux ou OSX.

Cependant, les adresses IP peuvent changer, par exemple, après le redémarrage du routeur, ce n'est pas toujours pratique. De cela suit le conseil N2 - configurez une adresse IP statique. Pour ce faire, exécutez la commande sudo nano /etc/dhcpcd.conf sur le Raspberry Pi et entrez les paramètres suivants:

interface eth0 static ip_address=192.168.1.152/24 static routers=192.168.1.1 static domain_name_servers=192.168.1.1 8.8.8.8 

Si vous avez besoin d'une adresse WiFi, alors l'interface sera wlan0, si Ethernet puis eth0. Les adresses IP, bien sûr, vous devez remplacer les vôtres. Après le redémarrage, assurez-vous que l'adresse IP est correcte en émettant la commande ifconfig .

Maintenant que tout est prêt, nous pouvons démarrer Python. Tous les exemples sont donnés pour Python 3.7, car 2.7 est depuis longtemps obsolète, et cela n'a aucun sens de le maintenir. Mais avec de petits changements de code, tout fonctionnera là-bas, si nécessaire. Soit dit en passant, le langage Python est multiplateforme - cela signifie que tout le code ci-dessous peut être exécuté à la fois sur Windows et OSX, et bien sûr, sur le Raspberry Pi. Le Conseil N3 en découle - vous pouvez déboguer le programme sur un PC normal et télécharger la version finale sur Raspberry Pi. Vous n'aurez peut-être qu'à créer des fonctions d'encapsulation pour les méthodes GPIO; tout le reste fonctionnera.

Notre tâche consiste donc à donner accès à l'application via un navigateur classique. Car il est élégant, à la mode, jeune et «l'Internet des objets» est notre tout.

Méthode 1: ligne de commande


La manière la plus simple, ne nécessitant aucune programmation.

Sélectionnez le dossier souhaité sur le Raspberry Pi et entrez la commande:

 python3 -m http.server 5000 

Ça y est, le serveur de fichiers fonctionne sur le Raspberry Pi! Il suffit d'aller sur la page http: //192.168.1.102►000 et nous verrons nos fichiers dans le navigateur:



C'est assez pratique si vous devez ouvrir l'accès à distance à n'importe quel fichier avec un minimum d'effort. Vous pouvez également entrer la commande sudo python3 -m http.server 80 et démarrer le serveur avec le 80e port standard, cela n'indiquera pas le port dans la barre d'adresse du navigateur.

Soit dit en passant, si nous voulons que le serveur fonctionne même après la fermeture du terminal, nous pouvons utiliser la commande sudo nohup python3 -m http.server 80 & - cela lancera le processus en arrière-plan. Vous pouvez tuer un tel programme en redémarrant ou en entrant la commande sudo killall python3 sur la ligne de commande.

Méthode 2: SimpleHTTPServer


Nous pouvons tout simplement intégrer le même serveur dans notre programme Python, pour cela il suffit de le démarrer dans un thread séparé au démarrage du programme. Maintenant, nous n'avons plus à nous soucier de la ligne de commande, pendant que le programme est en cours d'exécution, le serveur fonctionnera.

 import http.server import socketserver from threading import Thread import os def server_thread(port): handler = http.server.SimpleHTTPRequestHandler with socketserver.TCPServer(("", port), handler) as httpd: httpd.serve_forever() if __name__ == '__main__': port = 8000 print("Starting server at port %d" % port) os.chdir("/home/pi/Documents") Thread(target=server_thread, args=(port,)).start() 

La commande os.chdir est facultative si nous voulons fournir un accès du serveur à un autre dossier que le dossier actuel.

Méthode 3: HTTPServer


Il s'agit déjà d'un serveur Web à part entière capable de traiter les demandes GET et POST, de renvoyer des données différentes, etc. Mais bien sûr, plus de code est nécessaire.

Considérez la version à fonctionnement minimal du serveur:

 from http.server import BaseHTTPRequestHandler, HTTPServer html = "<html><body>Hello from the Raspberry Pi</body></html>" class ServerHandler(BaseHTTPRequestHandler): def do_GET(self): if self.path == "/": self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(html.encode('utf-8')) else: self.send_error(404, "Page Not Found {}".format(self.path)) def server_thread(port): server_address = ('', port) httpd = HTTPServer(server_address, ServerHandler) try: httpd.serve_forever() except KeyboardInterrupt: pass httpd.server_close() if __name__ == '__main__': port = 8000 print("Starting server at port %d" % port) server_thread(port) 

Nous lançons le navigateur et y voyons notre page HTML:



Ce serveur est facile à apprendre pour donner des fichiers, tels que des images.

Ajoutez la balise img au HTML:

 html = '<html><body><h3>Hello from the Raspberry Pi</h3><img src="raspberrypi.jpg"/></body></html>' 

Le fichier source "raspberrypi.jpg", bien sûr, doit être dans le dossier du programme. Ajoutez la possibilité de recevoir des fichiers à la fonction do_GET:

  def do_GET(self): print("GET request, Path:", self.path) if self.path == "/": self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(html.encode('utf-8')) elif self.path.endswith(".jpg"): self.send_response(200) self.send_header('Content-type', 'image/jpg') self.end_headers() with open(os.curdir + os.sep + self.path, 'rb') as file: self.wfile.write(file.read()) else: self.send_error(404, "Page Not Found {}".format(self.path)) 

Nous démarrons le serveur et nous voyons l'image correspondante:



Il est peu probable qu'un tel serveur remporte le concours de conception Web, mais cela fonctionne plutôt bien. Le serveur peut être facilement contraint de fournir des données plus utiles, par exemple, renvoyer des informations sur le fonctionnement du programme. Par exemple, ajoutez un gestionnaire pour la nouvelle fonction d'état:

 import psutil import json def cpu_temperature(): return psutil.sensors_temperatures()['cpu-thermal'][0].current def disk_space(): st = psutil.disk_usage(".") return st.free, st.total def cpu_load() -> int: return int(psutil.cpu_percent()) def ram_usage() -> int: return int(psutil.virtual_memory().percent) def do_GET(self): ... elif self.path == "/status": self.send_response(200) self.send_header('Content-Type', 'application/json') self.end_headers() health = {'CPUTemp': cpu_temperature(), 'CPULoad': cpu_load(), "DiskFree": disk_space()[0], "DiskTotal": disk_space()[1], "RAMUse": ram_usage()} self.wfile.write(json.dumps(health).encode('utf-8')) 

Maintenant, nous pouvons ouvrir le lien http: //192.168.1.102►000/status dans le navigateur et voir les paramètres système actuels:



Soit dit en passant, comme vous pouvez le voir, nous envoyons les données au format JSON, ce qui nous permettra de les utiliser pour d'autres demandes.

Conclusion


Tous conçus en une seule pièce ne correspondaient pas. La deuxième partie est disponible ici .

Important: mesures de sécurité

Si une adresse IP externe sera utilisée pour le Raspberry Pi, vous devez absolument garder à l'esprit les mesures de sécurité. Il peut sembler que personne n'a besoin de votre mini-serveur, mais il est maintenant facile de numériser par lots toutes les plages d'adresses IP (par exemple, l' Ukraine , l' Autriche ) et de trouver tous les appareils disponibles. Vous devez donc absolument changer le mot de passe sur le Raspberry Pi, et vous ne devez pas stocker d'informations confidentielles sur l'appareil (dossiers Dropbox, noms / mots de passe codés en dur dans les scripts, photos, etc.)

PS: Une enquête a été ajoutée pour comprendre l'image

Source: https://habr.com/ru/post/fr472126/


All Articles