Il nostro fido Raspberry Pi è uno strumento estremamente versatile, che può essere utilizzato per creare qualsiasi tipo di applicazione. In questo articolo vedremo come, partendo da un Raspberry Pi equipaggiato con Pi Cam, potremo creare un'app Android (e, volendo, anche iOS) per la visualizzazione di un flusso video in streaming, che ci permetta di sorvegliare un ambiente in tempo reale.
Setup dell’ambiente di sviluppo
Come ovvio, il primo passo che dovremo intraprendere sarà quello di configurare il nostro ambiente di sviluppo. Teniamo presente che dovremo sviluppare una parte sul nostro fido Raspberry (che supporrò abbiate già configurato con l’ultima versione di Raspbian e con la PiCamera; in caso contrario, date un’occhiata a questo ed a questo articolo), sia una parte per sviluppare l’app mobile. Il mio suggerimento è quindi di usare un unico ambiente di sviluppo, e nello specifico Visual Studio Code, IDE leggera e versatile offerta da Microsoft, e che può essere usata sia su un classico desktop o notebook per lo sviluppo su mobile (in accoppiata con Xcode o Android Studio a seconda che si stia sviluppando per iOS o Android, rispettivamente).
Scarichiamo quindi VS Code dal link ufficiale e completiamo la semplice procedura di installazione. Una volta terminata, dovremo abilitare l’estensione Remote – SSH, che ci permetterà di sviluppare direttamente sul Pi dal nostro PC. Per farlo, una volta avviato VS Code, selezioniamo il menu delle estensioni: in tal senso, possiamo cliccare sulla quinta icona partendo dall’alto sul menu a sinistra, oppure premere Ctrl + Maiusc + X, e scrivere Remote – SSH nella barra delle ricerche. Selezioniamo l’estensione sviluppata da Microsoft, come mostrato in Figura 1, ed installiamola mediante l’opportuno pulsante. Una volta completata la procedura di installazione, riavviamo VS Code qualora necessario.
A questo punto, dovremo stabilire la connessione con il nostro Raspberry. Questo avviene (come dice anche il nome dell’estensione stessa) mediante SSH: assicuriamoci quindi innanzitutto di aver abilitato il Pi per l’accesso da remoto (eventualmente, consultiamo questo articolo per scoprire come fare). Un’altra cosa da avere a portata di mano è l’indirizzo del Pi all’interno della rete locale; ancora meglio, sarebbe avere la possibilità di accedere al router in modo da far sì che l’indirizzo assegnato al Raspberry diventi statico.
Una volta recuperato l’indirizzo del Pi (che indicheremo di seguito con raspberry_pi_add), possiamo aprire la console di VS Code premendo F1, e digitare “remote” per aprire le opzioni di configurazione di Remote SSH, come mostrato in Figura 2.
Una volta aperte le opzioni di connessione, aggiungiamo un nuovo host remoto selezionando Add New SSH Host, e specifichiamo l’istruzione per la connessione:
ssh raspberry_pi_username@raspberry_pi_add
dove raspberry_pi_username è lo username che utilizziamo per loggare nel nostro Raspberry (di default, pi).
Inseriamo la password per la connessione qualora richiesto, e saremo quindi connessi alla cartella home del nostro Pi. Creiamo una nuova cartella, che chiameremo raspdroid:
mkdir raspdroid cd raspdroid
Ovviamente, potete creare questa cartella in un qualsiasi percorso a voi congeniale, e chiamarla come più vi aggrada; nel seguito, però, sarà questo il nome che utilizzeremo per riferirci al progetto.
Assicuriamoci ora che sia installato Python sul Pi, digitando il seguente comando:
python3 –version
Se non riscontriamo alcun errore, il Pi è correttamente configurato; in caso contrario, seguiamo le istruzioni di installazione di Python disponibili sul sito ufficiale. Creiamo quindi un ambiente virtuale (per approfondirne il significato, consultiamo questo articolo), utilizzando il package virtualenvwrapper:
$ pip install virtualenvwrapper $ mkvirtualenv rsenv (rsenv)$ pip install flask
In ultimo, ricordiamo di installare Node.js con npm sul nostro computer di sviluppo; questo ci servirà in seguito per creare l’app Android. Per farlo, anche qui ci riferiremo alle istruzioni reperibili sul sito ufficiale; il consiglio è quello di usare la versione LTS, dato che è ampiamente supportata ed offre estesa compatibilità.
Possiamo adesso passare alla parte di sviluppo, partendo dal server di streaming, che sarà basato su Python e Flask.
Il nostro server di streaming
Introduzione a Flask
Flask è probabilmente uno tra i package Python maggiormente utilizzati in ambito di programmazione web, ed è rivolto principalmente alla creazione di web services abbastanza semplici. In tal senso, la documentazione ufficiale si riferisce a Flask come ad un microframework: il nome, tuttavia, non deve trarci in inganno, in quanto, nonostante questo sia definito come micro, è tutto fuorché limitato, dato che predilige un approccio modulare e componibile a quello “monolitico” di altri framework, come ad esempio Django (tanto per restare in ambito Python).
Il core di un web service Flask è il file app.py, nel quale è incluso tutto il necessario per il funzionamento di un semplice servizio web. Vediamo insieme come definirlo.
Una semplice applicazione Flask
La più semplice applicazione Flask è composta da soltanto due file: in primis, il file app.py, che abbiamo visto essere necessario per definire le parti fondamentali del web service, ed un file index.html, contenuto nella cartella templates, che risiede nella stessa cartella di app.py e che, prevedibilmente, rappresenta il template per la pagina principale del nostro web service.
La struttura è quindi la seguente:
| - app.py | - templates/ | --- index.html
Proviamo quindi ad implementarla, ricreandola all'interno della cartella raspdroid sul nostro Raspberry mediante VS Code o riga di comando. Nel file app.py andremo ad inserire questo codice:
Alla riga 3 del blocco precedente creiamo la nostra app, definendola come un'istanza della classe Flask. Successivamente, dichiariamo la nostra prima route, la quale è contraddistinta da tre elementi:
- il decorator @app.route, indicativo del fatto che si tratta di una route;
- il path relativo della route rispetto all’URL a cui è raggiungibile il server Flask;
- il metodo che verrà eseguito dal server una volta che un client chiamerà quella route.
Ad esempio, che l’URL a cui è possibile raggiungere il nostro server sia http://localhost:5000, Flask interpreterà ogni richiesta verso http://localhost:5000/index (ovvero il path relativo della route definito al punto 2) come una chiamata al metodo definito al punto 3. Nel nostro esempio, quest’ultimo chiama la funzione render_template, che permette di visualizzare il template HTML definito all’interno del file passato come parametro, ovvero index.html. Quest'ultimo avrà la seguente struttura:
Notiamo come, in realtà, il file index.html sia molto semplice, e si limiti a mostrare a schermo soltanto una scritta riportante Hello, Flask!
Per lanciare il nostro web service, rechiamoci all'interno della cartella dove si trova il file app.py, attiviamo (qualora non lo avessimo fatto) l'ambiente virtuale rsenv, e digitiamo la seguente istruzione:
flask run
Puntando il nostro browser all'indirizzo http://localhost:5000, potremo vedere il nostro web service in azione, come mostrato in Figura 3.
Adesso è il momento di definire un particolare costrutto definito dal linguaggio Python, ovvero quello dei generator.
Generator in Python
Un generator è una speciale funzione che restituisce un iteratore sul quale possiamo iterare, valore dopo valore. Un semplice esempio di generatore è il seguente:
A differenza delle normali funzioni, che restituiscono un unico valore, il generator restituirà tre valori, rappresentati dalle tre stringhe riportate a valle delle istruzioni yield.
Utilizzeremo questo tipo di funzione per generare un flusso di immagini, utilizzando una tecnica chiamata Motion JPEG (MJPEG), molto usata nelle IP security camera comunemente in commercio che, nonostante non assicuri una elevata qualità dello streaming, principalmente a causa della codifica JPEG, garantisce una bassa latenza e, generalmente, risultati più che accettabili.
Generazione dello streaming
La risposta HTTP del server
Per far sì che una funzione generator sia in grado di restituire i frame appartenenti al nostro streaming video, dovremo fare in modo che l'istruzione yield restituisca oggetti di tipo Response, che possiamo pensare come definiti all'interno di Flask (in realtà, sono definiti all'interno di una libreria usata da Flask per la gestione delle chiamate HTTP, ovvero Werkzeug) e rappresentativi della risposta che il nostro server invierà ad ogni richiesta HTTP ricevuta.
Ogni valore restituito dal generator concorrerà quindi a definire una risposta HTTP con una struttura di questo tipo:
HTTP/1.1 200 OK Content-Type: multipart/x-mixed-replace; boundary=frame --frame Content-Type: image/jpeg [dati frame 1] --frame Content-Type: image/jpeg [dati frame 2] ...
Nella risposta HTTP notiamo immediatamente due fattori: [...]
ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 3005 parole ed è riservato agli ABBONATI. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici che potrai leggere in formato PDF per un anno. ABBONATI ORA, è semplice e sicuro.