Controllo remoto di utenze da interfaccia web con la GPIO di Raspberry Pi, Python e Flask
Avere la possibilità di controllare da remoto le utenze domestiche tramite un qualunque dispositivo connesso ad Internet, come uno smartphone, tablet o PC portatile, offre tanti spunti alla remotizzazione di cio’ che non si può avere sempre a portata di mano o che per contingenze varie è ubicato in un luogo diverso da quello dove si vive abitualmente. Nel caso specifico di una stazione radio, si può pensare di installare antenne e apparati in un luogo più consono a questo tipo di attività, come la casa in campagna e disporne comodamente dall’appartamento di città. O anche di essere costretti a trascorrere lunghi periodi fuori dalla propria abitazione e non voler rinunciare all’opportunità di fare QSO dalla propria stazione.
Raspberry Pi con la sua versatile interfaccia GPIO (General Purpose Input Output) si presta in modo ottimale alla realizzazione di un server web, grazie all’utilizzo di Python con RPi.GPIO, per la gestione degli input/output e Flask, un micro framework per la realizzazione di pagine web dinamiche ed interfacciabili con l’hardware.
Flask
Flask [1] è un microframework per Python, sviluppato da Armin Ronacher, per la realizzazione di un web server con contenuti dinamici. Flask è un framework molto semplice e leggero nel quale però possono essere integrate una serie di estensioni che consentono la creazioni di siti web anche complessi. Nel nostro caso ciò che riveste maggiore interesse è che sia sviluppato in Python, consentendone quindi un facile interfacciamento alle funzioni hardware del Rapsberry Pi.
In alternativa, ovvero disponendo di un web server classico come Apache o NGINX, ci si dovrà preoccupare di richiamare tramite PHP uno script in Python, C o altri linguaggi senza avere la diretta integrazione degli stessi nella pagina web e con un carico aggiuntivo di consumo delle risorse del sistema. In tal caso si veda il progetto RPi Remote Switch che utilizza appunto PHP, Javascript e l’utility gpio della libreria WiringPi.
RPi.GPIO
RPi.GPIO [2], ovvero raspberry-gpio-python di Ben Croston, è un modulo Python per il controllo delle porte GPIO del Raspberry Pi.
Fare attenzione perché RPi.GPIO identifica le porte in base alla numerazione del processore Broadcom o alla disposizione sul connettore GPIO della scheda RPi. Negli esempi seguenti utilizzeremo la seconda opzione, in modo che i pin utilizzati siano facilmente identificabili ed il codice indipendente dalla versione di RPi.
Installazione
Supponendo di avere il nostro Raspberry Pi con sistema operativo Raspbian installato e aggiornato, quindi con Python 3 già incluso, si procede con l’installazione di Flask. Poiché Flask supporta Python 3 (versione 3.3 o superiore), è opportuno cominciare un nuovo sviluppo da questa versione, essendo la 2 non più supportata.
Installiamo innanzitutto PIP (Python Package Index), il gestore di librerie di Python 3
sudo apt-get install python3-pip
Quindi Flask, il micro framework Python
sudo pip3 install flask
E la libreria Python RPi.GPIO, per la gestione dell’interfaccia di I/O del Raspberry Pi, modulo che di solito è già installato
sudo pip3 install rpi.gpio
Creare la cartella dove verranno conservati gli script Python, ad esempio con il nome “flask-webserver”
mkdir flask-webserver
Ora testiamo l’installazione di Flask con un codice prova. Entriamo nella cartella e creiamo il file per lo script
cd flask-webserver
nano flask-test.py
Inserire all’interno il seguente codice
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "<html><body><h1>Flask test</h1>OK</body></html>"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, debug=True)
Quindi lanciare lo script (visto che è stata selezionata la porta http 80 sono richiesti i privilegi di amministratore)
sudo python3 flask-test.py
Dal PC aprire il browser ed inserire l’indirizzo IP del proprio Raspberry, apparirà la seguente pagina
Remote control
Dopo aver verificato il funzionamento di Flask si può procedere con lo scopo che ci eravamo prefissati. Scaricare il file zip allegato Remote 1.0beta, copiarne il contenuto nella cartella di lavoro ed eseguirlo
sudo python3 remote.py
Il file remote.py contiene il seguente codice, adeguatamente commentato per descriverne il funzionamento:
# RPi Remote control web interface
# by IZ8EWD www.pianetaradio.it
# v 1.0 beta
import RPi.GPIO as GPIO
import datetime
from flask import Flask, render_template
app = Flask(__name__)
GPIO.setmode(GPIO.BOARD)
#Create a dictionary called port_io to store the pin number, name and status
port_io = {
11 : {'name' : 'Device 1', 'status' : GPIO.LOW},
13 : {'name' : 'Device 2', 'status' : GPIO.LOW},
15 : {'name' : 'Device 3', 'status' : GPIO.LOW},
16 : {'name' : 'Device 4', 'status' : GPIO.LOW}
}
#Set each pin as an output and make it low
for pin in port_io:
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, GPIO.LOW)
#Create the dynamic content of main page
@app.route("/")
def index():
#For each pin, read the pin state and store it in the port_io dictionary
for pin in port_io:
port_io[pin]['state'] = GPIO.input(pin)
#Read current time
time = datetime.datetime.now()
time_string = time.strftime("%Y-%m-%d %H:%M")
#Dictionary with return data for the html page
return_data = {
'port_io' : port_io,
'return_message' : "Welcome",
'return_time' : time_string
}
#Create html page from template
return render_template('remote_template.html', **return_data)
#Switch the pin status on user request and update the web interface
@app.route("/<pin_control>/", methods=['POST'])
def GPIO_control(pin_control):
pin_control = int(pin_control)
if port_io[pin_control]['status'] == GPIO.LOW:
GPIO.output(pin_control, GPIO.HIGH) #Set the pin high
else:
port_io[pin_control]['status'] = GPIO.LOW
GPIO.output(pin_control, GPIO.LOW) #Set the pin low
port_io[pin_control]['status'] = GPIO.input(pin_control) #Read the pin value and assign to pin status in port_io
#Update the time
time = datetime.datetime.now()
time_string = time.strftime("%Y-%m-%d %H:%M")
#Update the return data in the html page
return_data = {
'port_io' : port_io,
'return_message' : port_io[pin_control]['name'] + " is " + str(port_io[pin_control]['status']),
'return_time' : time_string
}
return render_template('remote_template.html', **return_data)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=False) #Web server running on localhost, port 80
E nella cartella templates il file remote_template.html con il template di pagina utilizzato da flask per realizzare la pagina web dinamica:
<! DOCTYPE html>
<html>
<head>
<style>
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
padding: 10px;
}
</style>
<title>Remote</title>
</head>
<body>
<h1>RPi GPIO Remote Control</h1>
<hr style="color:blue" />
<p>{{ return_time }}</p>
<table>
<tr><th>ID</th><th>Name</th><th>Status</th><th>Switch</th></tr>
{% for pin in port_io %}
<tr><td>{{ pin }}</td>
<td>{{ port_io[pin].name }}</td>
{% if port_io[pin].status == 1 %}
<td style="color:green;">On
{% else %}
<td style="color:red;">Off
{% endif %}
</td>
<td><form action="/{{ pin }}/" method="post"><button name="status" type="submit"> on / off </button></form></td></tr>
{% endfor %}
</table>
<p>Message: {{ return_message }}</p>
<hr style="color:blue" />
<p>by Gianfranco IZ8EWD, <a href="https://www.pianetaradio.it" target="_blank">PianetaRadio.it</a>, v1.0 beta</p>
</body>
</html>
Dal PC aprire il browser ed inserire l’indirizzo IP del proprio Raspberry, apparirà la seguente pagina
Cliccando sui pulsanti si abilitano o disabilitano le rispettive uscite della GPIO, come visibile dall’acquisizione degli stati eseguita con analizzatore logico, dove le quattro porte, inizialmente spente, sono state abilitate in sequenza
Sviluppo
Quanto presentato è solo un esempio delle potenzialità di questo sistema, ma va completato con ulteriori funzionalità e soprattutto la gestione del login di accesso per motivi di sicurezza. Pertanto in futuro sono previsti aggiornamenti e sviluppi. Nel frattempo sono ben accetti commenti e suggerimenti.
Hardware
La parte hardware è composta, oltre che dal Raspberry e suo alimentatore, da una scheda relè 5V optoisolata, di quelle che si trovano comunemente sul web. La scheda andrà opportunamente interconnessa ai pin della GPIO per il pilotaggio e l’alimentazione.
Riferimenti
- Flask;
- RPi.GPIO;
- Flask installation guide by Matt Richardson;
- Raspberry Pi Web Server using Flask to Control GPIOs, Random Nerd Tutorials;
- Flask – un web server in Python su Raspberry, Meccanismo Complesso;
- The Flask Mega-Tutorial, by Miguel Grinberg.
Argomenti correlati
Questa opera è distribuita con:
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Italia.
Si declina ogni responsabilità per eventuali errori ed omissioni e gli eventuali danni che ne dovessero conseguire. Per ulteriori informazioni consultare le note legali.
ciao,
bel progetto, ma accessibile solo dalla LAN locale, non riesco ad accedere per esempio da smartphone…. come fare?
Salve Severino,
l’accesso esterno alla propria rete locale richiede una serie di passaggi che esulano dallo scopo dell’articolo. Sintetizzo di seguito:
1) attivare servizio DNS per identificare l’IP pubblico e dinamico della propria rete con un nome di riferimento;
2) aprire porta sul modem/router con reindirizzamento all’IP locale del Raspberry verso la porta 80 del server Flask.
In alternativa utilizzare una VPN per una connessione sicura.