Hola Habr
Hoy en día, una gran cantidad de proyectos de automatización del hogar (y no solo) usan Raspberry Pi. Al mismo tiempo, es lo suficientemente conveniente no solo para tener acceso directo al dispositivo, sino también para usar un navegador; esto le permite realizar las acciones necesarias desde una computadora y desde un teléfono móvil, e incluso de forma remota desde cualquier parte del mundo.

Supongamos que ya tenemos un programa súper Python que hace algo muy importante, desde parpadear un LED hasta controlar un "hogar inteligente" o al menos un alimentador de gatos. Mostraré diferentes formas, desde simples a complejas, cómo hacer que el acceso web a dicha aplicación agregue algún código.
El artículo está dirigido a principiantes, es poco probable que los profesionales encuentren algo radicalmente nuevo aquí, pero espero que sea útil para los recién llegados a Linux. Para aquellos que estén interesados, continúe bajo el corte.
Nota : este artículo es una especie de "experimento", una vez en los comentarios se quejaron de que no había suficientes artículos para Habré para principiantes. Intenté llenar el vacío, pero según las estimaciones quedará claro si tiene sentido continuar en este formato o no.
Entonces comencemos.
Configurar Raspberry Pi
Esperemos que el lector tenga una Raspberry Pi que esté conectada a la red doméstica a través de WiFi o Ethernet, y sepa cuál es la dirección IP y cómo iniciar sesión remotamente en la Raspberry Pi a través de SSH usando masilla. Consideraremos la llamada configuración sin cabeza, sin teclado ni monitor. Pero antes de hacer algo con la Raspberry Pi, un par de pequeños trucos de la vida.
Consejo N1 . Para hacer algo de forma remota con Raspberry Pi, debe configurar SSH y, de forma predeterminada, está desactivado. Puede seguir el camino tradicional e iniciar el configurador estándar, pero puede ser más simple: después de grabar la imagen del disco, simplemente cree un archivo
ssh vacío (sin extensión) en la raíz de la tarjeta SD. Además, después de cargar la Raspberry Pi, SSH estará inmediatamente activo.
Para acceder al dispositivo de forma remota, debe encontrar la dirección IP de Raspberry Pi. Para hacer esto, simplemente abra el panel de control de su enrutador, encuentre la lista de clientes DHCP allí, copie la dirección IP deseada desde allí (por ejemplo, será 192.168.1.102) e ingrese el comando
putty.exe pi@192.168.1.102 (para Windows) o
ssh pi @ 192.168.1.102 para Linux u OSX.
Sin embargo, las direcciones IP pueden cambiar, por ejemplo, después de reiniciar el enrutador, esto no siempre es conveniente. De esto se sigue el
Consejo N2 : configure una dirección IP estática. Para hacer esto, ejecute el comando
sudo nano /etc/dhcpcd.conf en la Raspberry Pi e ingrese la siguiente configuración:
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 necesita una dirección WiFi, la interfaz será wlan0, si Ethernet entonces eth0. Direcciones IP, por supuesto, debe sustituir la suya. Después del reinicio, asegúrese de que la dirección IP sea correcta
emitiendo el comando
ifconfig .
Ahora todo está listo, podemos iniciar Python. Todos los ejemplos se dan para Python 3.7, porque 2.7 ha quedado en desuso y no tiene sentido mantenerlo. Pero con pequeños cambios en el código, todo funcionará allí, si es necesario. Por cierto, el lenguaje Python es multiplataforma, esto significa que todo el código a continuación se puede ejecutar tanto en Windows como en OSX y, por supuesto, en Raspberry Pi. De esto se desprende el
Consejo N3 : puede depurar el programa en una PC normal y cargar la versión final en Raspberry Pi. Es posible que solo tenga que hacer funciones de envoltura para los métodos GPIO; todo lo demás funcionará.
Por lo tanto, nuestra tarea es proporcionar acceso a la aplicación a través de un navegador normal. Porque es elegante, moderno, juvenil, y el "Internet de las cosas" es nuestro todo.
Método 1: línea de comando
La forma más fácil, sin necesidad de programación.
Seleccione la carpeta deseada en Raspberry Pi e ingrese el comando:
python3 -m http.server 5000
Eso es todo, ¡el servidor de archivos se ejecuta en Raspberry Pi! Es suficiente ir a la página
http: //192.168.1.102►000 y veremos nuestros archivos en el navegador:

Esto es lo suficientemente conveniente si necesita abrir el acceso remoto a cualquier archivo con un mínimo de esfuerzo. También puede ingresar el comando
sudo python3 -m http.server 80 e iniciar el servidor con el puerto 80 estándar, esto no indicará el puerto en la barra de direcciones del navegador.
Por cierto, si queremos que el servidor funcione incluso después de cerrar la terminal, podemos usar el
comando sudo nohup python3 -m http.server 80 & - esto iniciará el proceso en segundo plano. Puede matar dicho programa reiniciando o ingresando el comando
sudo killall python3 en la línea de comando.
Método 2: SimpleHTTPServer
Simplemente podemos integrar el mismo servidor en nuestro programa Python, para esto es suficiente iniciarlo en un hilo separado al inicio del programa. Ahora, no necesitamos molestarnos con la línea de comando, mientras el programa se está ejecutando, el servidor funcionará.
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()
El comando os.chdir es opcional si queremos proporcionar acceso desde el servidor a otra carpeta que no sea la actual.
Método 3: HTTPServer
Este ya es un servidor web completo, capaz de procesar solicitudes GET y POST, devolver datos diferentes, etc. Pero, por supuesto, necesitará más código.
Considere la versión mínimamente funcional del servidor:
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)
Iniciamos el navegador y vemos nuestra página HTML en él:

Este servidor es fácil de enseñar a dar archivos, como imágenes.
Agregue la etiqueta img al HTML:
html = '<html><body><h3>Hello from the Raspberry Pi</h3><img src="raspberrypi.jpg"/></body></html>'
El archivo fuente "raspberrypi.jpg", por supuesto, debe estar en la carpeta del programa. Agregue la capacidad de recibir archivos a la función 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))
Iniciamos el servidor y vemos la imagen correspondiente:

Es poco probable que dicho servidor gane el concurso de diseño web, pero funciona bastante bien. El servidor puede verse obligado fácilmente a proporcionar datos más útiles, por ejemplo, para devolver información sobre el funcionamiento del programa. Por ejemplo, agregue un controlador para la nueva función de estado:
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'))
Ahora podemos abrir el enlace
http: //192.168.1.102►000/status en el navegador y ver los parámetros actuales del sistema:

Por cierto, como puede ver, enviamos los datos en formato JSON, lo que nos permitirá usarlos para otras solicitudes.
Conclusión
Todo concebido en una sola pieza no encajaba. La segunda parte
está disponible aquí .
Importante: medidas de seguridadSi se utilizará una dirección IP externa para Raspberry Pi, definitivamente debe tener en cuenta las medidas de seguridad. Puede parecer que nadie necesita su mini servidor, pero ahora es fácil escanear por lotes todos los rangos de direcciones IP (por ejemplo,
Ucrania ,
Austria ) y encontrar todos los dispositivos disponibles. Por lo tanto,
definitivamente debe cambiar la contraseña en la Raspberry Pi, y no debe almacenar ninguna información confidencial en el dispositivo (carpetas de Dropbox, nombres / contraseñas codificados en scripts, fotos, etc.).
PD: se agregó una encuesta para comprender la imagen