La Raspberry Pi es un microordenador muy potente que tiene la particularidad de integrar un chip para gestionar la conexión Wifi. Esto lo convierte en un objeto ideal para desarrollar objetos conectados y, en particular, servidores web. En este tutorial veremos cómo crear y alojar una interfaz web para controlar tu Raspberry Pi.
Prerrequisitos: Programar su Raspberry Pi, Conectar su Raspberry a Wifi
Material
- Ordenador
- Raspberry Pi 3 B+ o Zero (con Raspbian y conexión remota VNC)
- Fuente de alimentación de 5V 2A
N.B.: Este tutorial fue escrito en torno a una Raspberry Pi pero puede aplicarse a cualquier ordenador con Python instalado.
Código
Para crear una página web, se necesita una estructura de archivos. Un archivo HTML en combinación con un archivo CSS para describir la página (front-end) y un script de Python para gestionar las peticiones del navegador al servidor (back-end). Es posible añadir archivos PHP y JavaScript para estructurar y añadir funcionalidad a la aplicación web.
Para organizar estos archivos, los colocaremos en subcarpetas:
- En la carpeta principal (acwebapp), el script RaspWebInterface.py
- Una subcarpeta estática, en la que colocaremos el script css
- Una subcarpeta templates, en la que colocaremos el script HTML
Código Python con Flask
Crearemos un script en Python usando Flask para mostrar la página rpi3b_webcontroller.html cuando sea solicitada por el navegador web. La librería utilizada para generar una aplicación web de forma sencilla es el microframework Flask.
Funciones a recordar:
app=Flask(name) para instanciar la aplicación Flask
El decorador @app.route(‘/’) para gestionar las solicitudes de URL
return render_template(‘rpi3b_webcontroller.html’,**templateData) para enviar la página web al navegador
devolver » OK 200 » para validar la recepción de una solicitud
app.run(debug=True, port=5000, host=’0.0.0′,threaded=True) para ejecutar la aplicación en la IP local con el puerto 5000
import os import RPi.GPIO as GPIO from flask import Flask, render_template, Response import datetime GPIO.setmode(GPIO.BCM) dataPin=[i for i in range(2,28)] for dp in dataPin: GPIO.setup(dp,GPIO.IN)#,pull_up_down=GPIO.PUD_UP) data=[] now=datetime.datetime.now() timeString=now.strftime("%Y-%m-%d %H:%M") templateData={ 'title':'Raspberry Pi 3B+ Web Controller', 'time':timeString, 'data':data, } def getData(): data=[] for i,dp in enumerate(dataPin): data.append(GPIO.input(dataPin[i])) return data app=Flask(__name__) @app.route('/') def index(): #return 'hello world!' now=datetime.datetime.now() timeString=now.strftime("%Y-%m-%d %H:%M") data=getData() templateData={ 'title':'Raspberry Pi 3B+ Web Controller', 'time':timeString, 'data':data, } #return render_template('rpi_index.html',**templateData) return render_template('rpi3b_webcontroller.html',**templateData) @app.route('/<actionid>') def handleRequest(actionid): print("Button pressed : {}".format(actionid)) return "OK 200" if __name__=='__main__': os.system("sudo rm -r ~/.cache/chromium/Default/Cache/*") app.run(debug=True, port=5000, host='0.0.0.0',threaded=True) #local web server http://192.168.1.200:5000/ #after Port forwarding Manipulation http://xx.xx.xx.xx:5000/
Código HTML de la página
El archivo .html contiene la descripción de la página web, así como el código JavaScript para gestionar los botones.
<!DOCTYPE HTML> <html> <head> <title> AranaCorp </title> <meta http-equiv='content-type' content='text/html; charset=UTF-8'> <meta name='apple-mobile-web-app-capable' content='yes' /> <meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' /> <meta http-equiv='refresh' content='10'> <link rel="stylesheet" href='../static/rpi_style.css'/> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> </head> <body bgcolor = '#70706F'> <hr/><hr> <h1 style='color : #3AAA35;'><center> AranaCorp - {{title}} </center></h1> <hr/><hr> <br><br> <h2><center><p>Date and time : {{time}}</p></center></h2> <br><br><h2> Digital Inputs/Ouputs </h2> <div id='btnContainer'> <center> Pin GPIO2 <input value={{data[0]}} readonly></input> <button id='dig2on'>Turn On </button></a> <button id='dig2off'>Turn Off </button></a><br /> </center> <center> Pin GPIO3 <input value={{data[1]}} readonly></input> <button id='dig3on'>Turn On </button></a> <button id='dig3off'>Turn Off </button></a><br /> </center><center> Pin GPIO4 <input value={{data[2]}} readonly></input> <button id='dig4on'>Turn On </button></a> <button id='dig4off'>Turn Off </button></a><br /> </center><center> Pin GPIO5 <input value={{data[3]}} readonly></input> <button id='dig5on'>Turn On </button></a> <button id='dig5off'>Turn Off </button></a><br /> </center><center> Pin GPIO6 <input value={{data[4]}} readonly></input> <button id='dig6on'>Turn On </button></a> <button id='dig6off'>Turn Off </button></a><br /> </center><center> Pin GPIO7 <input value={{data[5]}} readonly></input> <button id='dig7on'>Turn On </button></a> <button id='dig7off'>Turn Off </button></a><br /> </center><center> Pin GPIO8 <input value={{data[6]}} readonly></input> <button id='dig8on'>Turn On </button></a> <button id='dig8off'>Turn Off </button></a><br /> </center><center> Pin GPIO9 <input value={{data[7]}} readonly></input> <button id='dig9on'>Turn On </button></a> <button id='dig9off'>Turn Off </button></a><br /> </center><center> Pin GPIO10 <input value={{data[8]}} readonly></input> <button id='dig10on'>Turn On </button></a> <button id='dig10off'>Turn Off </button></a><br /> </center><center> Pin GPIO11 <input value={{data[9]}} readonly></input> <button id='dig11on'>Turn On </button></a> <button id='dig11off'>Turn Off </button></a><br /> </center><center> Pin GPIO12 <input value={{data[10]}} readonly></input> <button id='dig12on'>Turn On </button></a> <button id='dig12off'>Turn Off </button></a><br /> </center><center> Pin GPIO13 <input value={{data[11]}} readonly></input> <button id='dig13on'>Turn On </button></a> <button id='dig13off'>Turn Off </button></a><br /> </center><center> Pin GPIO14 <input value={{data[12]}} readonly></input> <button id='dig14on'>Turn On </button></a> <button id='dig14off'>Turn Off </button></a><br /> </center><center> Pin GPIO15 <input value={{data[13]}} readonly></input> <button id='dig15on'>Turn On </button></a> <button id='dig15off'>Turn Off </button></a><br /> </center><center> Pin GPIO16 <input value={{data[14]}} readonly></input> <button id='dig16on'>Turn On </button></a> <button id='dig16off'>Turn Off </button></a><br /> </center><center> Pin GPIO17 <input value={{data[15]}} readonly></input> <button id='dig17on'>Turn On </button></a> <button id='dig17off'>Turn Off </button></a><br /> </center> <center> Pin GPIO18 <input value={{data[16]}} readonly></input> <button id='dig18on'>Turn On </button></a> <button id='dig18off'>Turn Off </button></a><br /> </center><center> Pin GPIO19 <input value={{data[17]}} readonly></input> <button id='dig19on'>Turn On </button></a> <button id='dig19off'>Turn Off </button></a><br /> </center> <center> Pin GPIO20 <input value={{data[18]}} readonly></input> <button id='dig20on'>Turn On </button></a> <button id='dig20off'>Turn Off </button></a><br /> </center> <center> Pin GPIO21 <input value={{data[19]}} readonly></input> <button id='dig21on'>Turn On </button></a> <button id='dig21off'>Turn Off </button></a><br /> </center> <center> Pin GPIO22 <input value={{data[20]}} readonly></input> <button id='dig22on'>Turn On </button></a> <button id='dig22off'>Turn Off </button></a><br /> </center> <center> Pin GPIO23 <input value={{data[21]}} readonly></input> <button id='dig23on'>Turn On </button></a> <button id='dig23off'>Turn Off </button></a><br /> </center> <center> Pin GPIO24 <input value={{data[22]}} readonly></input> <button id='dig24on'>Turn On </button></a> <button id='dig24off'>Turn Off </button></a><br /> </center> <center> Pin GPIO25 <input value={{data[23]}} readonly></input> <button id='dig25on'>Turn On </button></a> <button id='dig25off'>Turn Off </button></a><br /> </center> <center> Pin GPIO26 <input value={{data[24]}} readonly></input> <button id='dig26on'>Turn On </button></a> <button id='dig26off'>Turn Off </button></a><br /> </center> <center> Pin GPIO27 <input value={{data[25]}} readonly></input> <button id='dig27on'>Turn On </button></a> <button id='dig27off'>Turn Off </button></a><br /> </center> </div> <script> // Event Listener var buttonClick = document.getElementById('btnContainer').addEventListener('click', function(event) { if (event.target.nodeName == "BUTTON") { var tar = event.target.id; console.log(tar); $.getJSON('/'+tar, function(data) { //do nothing }); return false; } }); </script> </body> </html>
Centrarse en el código JavaScript
El código JavaScript nos permitirá gestionar la pulsación de los botones de la interfaz. Para ello, crearemos un escuchador de eventos «click» (eventListener) en el elemento «btnContainer» que detectará si se hace clic en un botón y devolverá su identificador mediante una petición json.
// Event Listener var buttonClick = document.getElementById('btnContainer').addEventListener('click', function(event) { if (event.target.nodeName == "BUTTON") { var tar = event.target.id; console.log(tar); $.getJSON('/'+tar, function(data) { //do nothing }); return false; } });
Archivo rpi_style.css
El archivo css contiene el estilo de la página y en particular los botones para que la página tenga un aspecto personalizado.
body{ background-color:#70706F; } h1{ color:#3AAA35; } h3{ #width:100%; border: 3px solid #3AAA35; border-radius: 6px; overflow: hidden; text-align:center; padding:20px; } button{ width:auto; height:60px; background-color: #3aaa35;/* Green */ border: none; color: white; /*padding: 15px 32px;*/ text-align: center; vertical-align:middle; text-decoration: none; display: inline-block; font-size: 20px; border-radius: 12px; -webkit-transition-duration: 0.4s; /* Safari */ transition-duration: 0.4s; margin: 5px; } button:hover{ background-color: #4CAF50; /* Green */ color: white; }
Recuperar la dirección IP de la Raspberry Pi
Para acceder a la interfaz web alojada en la Raspberry Pi, necesitamos conocer la dirección IP para poder conectarnos a la red local desde un navegador web. Para ello, basta con introducir la línea de comandos ifconfig en el terminal de la Raspberry Pi.
N.B.: Es posible acceder a la Raspberry Pi fuera de la red local haciendo algo en la caja a la que está conectada la Raspberry Pi. Este procedimiento se denomina Reenvío de Puertos.
Resultado
Cuando ejecutes el script de Python en la Raspberry Pi, podrás introducir la dirección IP de tu Raspberry Pi seguida del puerto (aquí 192.168.1.200:5000) en tu ordenador o smartphone. La página web debería aparecer
A continuación, puedes ver lo que ocurre cuando pulsas los botones del terminal a través de la aplicación VNC.
Aplicaciones
- Crear un sistema de automatización del hogar controlable a través de Wifi
- Controla tu Raspberry Pi desde cualquier lugar
Fuentes
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie