Vuole scoprire come realizzare un'infrastruttura IoT nel cloud completamente gestita, con auto-scaling e serverless?
In questa serie di tre articoli dedicati a IoT su GCP ripercorreremo l'intero workflow IoT: dalla registrazione dei dispositivi allo streaming e all'archiviazione a lungo termine dei dati, fino alla loro analisi e visualizzazione.

Best practice per IoT su scala produttiva
Al termine della Parte Uno saprà come registrare in sicurezza milioni di dispositivi IoT che inviano dati di telemetria in streaming al suo ambiente Google Cloud.
Questo è il primo di tre articoli, in cui:
- L'archiviazione e la visualizzazione corrette di flussi di dati ad alto throughput saranno trattate nella Parte Due, e
- La realizzazione di un modello di machine learning funzionante su dati IoT sarà trattata nella Parte Tre.
In tutta la serie utilizzeremo GCP come provider cloud e dispositivi Raspberry Pi con sensori di temperatura come esempio di dispositivi IoT.
Panoramica
La trattazione è suddivisa nelle seguenti sezioni:
- Configurazione software e hardware del Raspberry Pi
- Registrazione pratica del dispositivo e provisioning delle credenziali
- Test di connettività del dispositivo e streaming dei dati di temperatura
- Note sulle funzionalità di Google Cloud IoT
- Archiviazione dei dati in streaming (trattata nella Parte Due)
- Visualizzazione dei dati in streaming (trattata nella Parte Due)
- Realizzazione di un modello di machine learning efficace con dati IoT (trattata nella Parte 3)
Per seguire questo articolo è sufficiente avere esperienza con Bash e Python e una conoscenza di base della Google Cloud Console.
Configurare software e hardware del Raspberry Pi
Per prima cosa, predisponga e renda operativi diversi dispositivi Raspberry Pi: io userò dei Pi 3. Le consiglio di utilizzare il Raspbian OS Imager per automatizzare l'installazione del sistema operativo sulle schede microSD.
Installare i pacchetti Python
Una volta raggiunto il desktop e aggiornato il dispositivo, esegua il seguente comando per installare l'SDK specifico di Google Cloud IoT:
pip3 install -U pyjwt paho-mqtt
Prima di proseguire, è importante capire perché installiamo paho-mqtt anziché l'SDK Python google-api-python-client di uso generale per Google Cloud. L'SDK Python più diffuso, così come la CLI gcloud di GCP, sono basati su HTTP. Si tratta di un protocollo utile per eseguire rapidamente la maggior parte delle operazioni. HTTP, però, non è adatto a inviare messaggi su connessioni di lunga durata con elevata probabilità di interruzioni, in cui il flusso di dati va prevalentemente dal dispositivo connesso verso il cloud.
MQTT è un protocollo utilizzato nell'IoT, tramite pacchetti come paho-mqtt, perché è stato progettato proprio per consentire a un dispositivo di pubblicare messaggi di frequente e riceverne raramente, anche in presenza di problemi di connettività.
Collegare un sensore di temperatura digitale
Ora che il suo Raspberry Pi ha installato i pacchetti Python necessari, dovrà collegarvi un sensore di temperatura digitale. Le consiglio di utilizzare questo sensore DS18B20 se desidera seguire passo passo l'articolo.
Per collegare il sensore al Raspberry Pi servono inoltre:
- Mini breadboard
- Cavi jumper per breadboard
- Kit assortito di resistori (ci serve un resistore da 4,7K Ohm)
Se deve attendere l'arrivo di questi componenti, può comunque proseguire con la lettura: forniremo uno script per lo streaming di temperature simulate.
Se invece i componenti sono già a disposizione, i primi cinque minuti di questo tutorial mostrano come collegare il sensore al Raspberry Pi e verificare che riceva i valori di temperatura.
Oltre alla procedura descritta nel tutorial, le consiglio di aggiungere quanto segue a /etc/modules, in modo che i moduli onewire vengano caricati all'avvio senza dover eseguire modprobe dopo ogni riavvio:
w1-gpio
w1-therm
Registrare i dispositivi IoT
Di seguito un esempio funzionante completo di come configurare il suo IoT Registry con dispositivi registrati in sicurezza, dai quali invieremo in streaming i dati di temperatura alla piattaforma Google Cloud IoT.
Creare un registry per i dispositivi
Nella Google Cloud Console:
- Crei un nuovo progetto (ad es. "IoTTempStreaming")
- Acceda al servizio IoT Core per abilitare l'API IoT
- Clicchi su "Create registry" per creare un registry in cui aggiungere i suoi dispositivi IoT.
I dispositivi IoT che inviano dati a GCP possono trasmettere i propri messaggi a IoT Core solo se vengono validati come dispositivi con credenziali memorizzate nell'IoT Registry: la creazione del registry è quindi un primo passo imprescindibile.

Un ambiente IoT Core nuovo di zecca in attesa di essere popolato con i messaggi
Creare un topic Pub/Sub
I messaggi inviati a IoT Core — insieme a metadati critici come il deviceId univoco di ciascun dispositivo — vengono inoltrati dietro le quinte a un "topic" su Pub/Sub, il sistema di code di messaggi di Google Cloud completamente gestito, con auto-scaling e serverless.
Per questo creeremo i topic Pub/Sub direttamente dalla finestra di configurazione dell'IoT Registry, in modo che i nostri dati di telemetria arrivino infine in Pub/Sub per l'elaborazione a valle.
Segua questi passaggi per creare un topic Pub/Sub dalla finestra di configurazione dell'IoT registry:
- Assegni al Registry ID il nome "RaspberryPiDevices" nella regione us-central1
- Crei un topic Pub/Sub denominato "sensordata", in cui arriveranno per impostazione predefinita i messaggi di telemetria IoT.
- In "Additional topics" crei un nuovo topic Pub/Sub denominato "temperature", in cui arriveranno i messaggi pubblicati su una sottocartella del topic IoT — anch'essa denominata "temperature".
Questa configurazione garantisce che solo i messaggi di temperatura pubblicati sulla specifica sottocartella IoT arrivino nel topic Pub/Sub temperature, mentre tutti gli altri eventi di telemetria (imprevisti) finiranno nel topic predefinito "sensordata".
Le consiglio inoltre di espandere le opzioni avanzate e di consentire solo il protocollo MQTT, deselezionando HTTP:

Configurazione dell'IoT Core Registry per lo streaming dei dati del sensore di temperatura
Una volta creato, il suo registry dovrebbe presentarsi così:

Una configurazione riuscita dell'IoT Core Registry
Creare un dispositivo registrato
Ora che disponiamo di un registry di dispositivi, creiamo un dispositivo registrato.
Per cominciare ci serviranno (1) una coppia di chiavi pubblica-privata da associare al dispositivo e (2) il certificato root di Google.
Di seguito i comandi da eseguire su un Raspberry Pi per generare le chiavi Elliptic Curve e ottenere il certificato root di Google (i comandi si basano sulla relativa documentazione di Google Cloud). Le chiavi EC hanno un footprint dei dati più ridotto rispetto alle tradizionali chiavi RSA e aiuteranno i dispositivi IoT a mantenere un throughput ottimale anche nelle aree con connettività difficoltosa:
$ mkdir -p /home/pi/GCP/iot_keys/
$ cd /home/pi/GCP/iot_keys/
$ wget http://pki.goog/roots.pem
$ openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
$ openssl ec -in ec_private.pem -pubout -out ec_public.pem
$ cat ec_public.pem
$ cd ../
Dopo aver eseguito i comandi sopra:
- Copi la chiave pubblica visualizzata nel terminale
- Acceda all'IoT Registry e vada su Devices
- Clicchi su Add Device
- Assegni un nome al dispositivo (ad es. "device1") e incolli la chiave pubblica ES256 sotto Authentication come mostrato di seguito.
- Clicchi su Create

Registrazione del dispositivo IoT con richiesta di una chiave Elliptic Curve
Una volta create, le credenziali associate a un dispositivo registrato in IoT Core sono pronte per essere utilizzate sul Raspberry Pi.
Prenda nota del Numeric ID assegnato al dispositivo, del Project ID e del Registry ID.
Con questi valori, oltre alle chiavi e al certificato root di Google presenti sul dispositivo, dobbiamo creare un file di configurazione denominato gcp_iot_config.txt. Questo file definirà i dettagli di autenticazione e dell'endpoint IoT da utilizzare per il singolo dispositivo. Poco più avanti nell'articolo descriviamo uno script Python che invia in streaming i valori di temperatura sfruttando questo file di configurazione:
$ pwd
/home/pi/GCP/
$ cat gcp_iot_config.txt
# Set the path to the location containing your keys
KEY_PATH = /home/pi/GCP/iot_keys/# Specify the private key and Google root cert names
PRIVATE_KEY = ec_private.pem
GOOGLE_ROOT_CERT = roots.pem# Set the details required for using your IoT endpoint
REGISTRY_ID = <REGISTRY_ID>
DEVICE_ID = <DEVICE_NUMERIC_ID>
REGION = us-central1
PROJECT_ID = <PROJECT_ID>
Ed ecco fatto! Il suo dispositivo è ora pronto per inviare in streaming, in sicurezza, dati di telemetria a un topic Pub/Sub tramite la piattaforma di autenticazione IoT Core di GCP. Ripeta la procedura per generare credenziali univoche e registrare ogni nuovo dispositivo.
Testare la connettività del dispositivo
Verifichiamo la connettività del dispositivo eseguendo il seguente script, denominato "publish_temps.py", che invia in streaming valori di temperatura reali o simulati, a seconda che la riga 107 o la 108 sia commentata.
(Lo script è un adattamento di due script di esempio di Google Cloud: #1 e #2)
$ pwd
/home/pi/GCP/
$ ./publish_temps.py
Qui succedono parecchie cose: le consiglio vivamente di esaminare il codice per capire meglio come avviene la connessione sicura e lo streaming dei dati.
Eseguendo lo script dovrebbe vedere un output simile al seguente:

Valori di temperatura reali in streaming verso GCP IoT Core via MQTT
Eseguendo lo script al riavvio tramite un job crontab (preceduto da uno sleep di 30s per consentire il caricamento dei moduli onewire all'avvio), il dispositivo IoT riprenderà lo streaming in caso di riavvio, atteso o imprevisto:
$ crontab -e
@reboot sleep 30 && /home/pi/GCP/publish_temps.py -c /home/pi/GCP/gcp_iot_config.txt >> /home/pi/GCP/publish_temps.log 2>&1
Ripeta i processi di onboarding e streaming per tutti i Raspberry Pi distribuiti in casa. È sulla buona strada per lavorare con dati IoT su larga scala!
Verificare che i dati stiano arrivando in streaming
Verifichiamo rapidamente che i messaggi stiano arrivando in Google Cloud osservando i dati di telemetria che raggiungono Pub/Sub.
- Crei una sottoscrizione Pub/Sub al topic "temperature"
- Acceda alla sottoscrizione
- Clicchi su View Messages e selezioni il radio button Pull
Dovrebbe vedere i messaggi man mano che arrivano, completi di temperatura e timestamp inviati nel corpo del messaggio, oltre ai metadati degli attributi che identificano in modo univoco il dispositivo che sta inviando quei valori. Questi metadati sono utili non solo per le analisi e per i dashboard rivolti agli utenti finali, ma anche per identificare e bloccare dispositivi compromessi o utilizzati in modo improprio.

Creazione di una sottoscrizione Pub/Sub per visualizzare i messaggi di telemetria della temperatura in arrivo
Ecco come si presenta una sottoscrizione al topic temperature:

Visualizzazione dei messaggi di una sottoscrizione Pub/Sub al topic Pub/Sub "temperature"
Una volta cliccato "PULL", dovrebbe iniziare a vedere i messaggi e i loro attributi:

Dati di temperatura che raggiungono un topic Pub/Sub e arrivano in una sottoscrizione Pub/Sub: corpo del messaggio

Dati di temperatura che raggiungono un topic Pub/Sub e arrivano in una sottoscrizione Pub/Sub: attributi che identificano in modo univoco
Se è arrivato fin qui, complimenti (sul serio)! Per quanto sia entusiasmante vedere arrivare a Pub/Sub dati reali da dispositivi IoT, abbiamo solo grattato la superficie.
Per sfruttare davvero questi dati dobbiamo eventualmente trasformarli, spostarli o caricarli in batch in un data warehouse e analizzarli. Tutto questo deve avvenire all'interno di un ecosistema di servizi GCP che permettano a questo flusso di dati di funzionare in modo affidabile, scalabile e conveniente, in tutte le fasi di sviluppo: dai test iniziali all'utilizzo in produzione su scala petabyte e oltre, con poca o nessuna manutenzione dell'infrastruttura. Se vuole vedere come si fa, non perda le parti due e tre!
Prossimo capitolo: archiviazione e visualizzazione
Non perda la parte due, in cui parleremo dei servizi di ETL, archiviazione e visualizzazione più adatti per abilitare con relativa facilità un uso concreto dei dati IoT in streaming su larga scala.
Note sulle funzionalità di Google Cloud IoT
Una migliore gestione del deviceId da parte dei servizi GCP completamente gestiti
Avrà notato che lo script Python invia una coppia chiave:valore device_id nel corpo del messaggio, che di fatto duplica l'attributo deviceId presente nel messaggio Pub/Sub e assegnato da IoT Core grazie all'associazione del messaggio con la coppia chiave-valore univoca del dispositivo che sta trasmettendo.
Perché far inviare allo script un device_id che potrebbe essere facilmente falsificato su un dispositivo compromesso, finendo per generare un data warehouse con dati corrotti quando i messaggi vengono spostati nell'archiviazione a lungo termine?
Sto andando un po' avanti rispetto al programma, ma come vedremo nella Parte Due esiste un comodo workflow completamente gestito, con auto-scaling e per lo più serverless, in grado di trasformare e spostare i messaggi Pub/Sub in BigQuery tramite Dataflow, la versione completamente gestita di Apache Beam offerta da Google Cloud.
Purtroppo il template predefinito "Pub/Sub-to-BigQuery" scritto da GCP e disponibile in Dataflow non offre alcun modo per spostare gli attributi dei messaggi in BigQuery: si può spostare solo il contenuto del corpo del messaggio. Vari Engineers di GCP mi hanno confermato che non è possibile scrivere una UDF Javascript Dataflow personalizzata per i template predefiniti che aggiunga gli attributi dei messaggi nei sink Dataflow come BigQuery. In alternativa, scrivere job Dataflow in Java — sia da zero sia come modifica dei template esistenti scritti da GCP — è un'attività che richiede molto tempo e impone manutenzione e aggiornamenti continui dei template, un compito che immagino la maggior parte dei clienti GCP non vorrà affrontare.
Di conseguenza, per impostazione predefinita non esistono modi semplici e sicuri per associare un messaggio IoT che arriva a Pub/Sub e viene instradato verso i sink di destinazione al deviceId del messaggio stesso.
Ho segnalato questa lacuna a GCP e, da quando ho sollevato la questione, è stata avviata una richiesta di funzionalità pubblica affinché i template predefiniti supportino il passaggio di questi valori preziosi — e assolutamente necessari — per coprire il caso d'uso IoT. Aggiornerò l'articolo non appena la FR sarà soddisfatta; fino ad allora, a scopo dimostrativo, è molto più semplice testare l'utilizzo di device_id inviandolo nel corpo del messaggio piuttosto che riscrivere un template Dataflow che dovrebbe essere presente di default.
Come vorrei effettuare idealmente il provisioning di credenziali univoche per dispositivo?
Il processo di registrazione di un singolo dispositivo IoT viene tipicamente descritto così:
- Creare una coppia di chiavi pubblica-privata associata in GCP ai permessi IoT
- Effettuare il provisioning e collocare i file sul dispositivo in fabbrica
- Far registrare alla fabbrica quelle credenziali nell'IoT Registry
- Abilitare la coppia di chiavi a effettuare le chiamate API IoT che inviano dati in streaming al cloud.
Una configurazione di questo tipo, di per sé, non è ideale, perché i casi d'uso IoT del mondo reale coinvolgono milioni di dispositivi che inviano dati in streaming a un ambiente cloud. A ciascun dispositivo di una flotta di queste dimensioni deve essere assegnato un set univoco di credenziali, in modo che, se un dispositivo o le sue credenziali Google Cloud vengono compromessi e utilizzati per scopi illegittimi, quel set possa essere disabilitato senza ripercussioni sugli altri dispositivi della flotta.
GCP offre questa funzionalità e, come si vede nello script sopra, supporta anche la possibilità di consentire a un dispositivo di pubblicare solo su un topic a esso univoco. Tuttavia, date le metodologie di provisioning delle credenziali disponibili, coordinare creazione, deployment e registrazione delle chiavi per milioni di dispositivi resta una sfida.
Come si può semplificare il più possibile il processo di creazione delle credenziali specifiche per dispositivo? È possibile farlo senza creare in anticipo milioni di certificati e coordinarne la collocazione univoca sui dispositivi in fase di produzione? Vuole davvero affidarsi a un produttore per collocare in modo affidabile questi file senza duplicazioni?
In alternativa, si possono effettuare la registrazione e la credenzializzazione del dispositivo senza richiedere al produttore di emettere chiamate API verso il suo IoT Registry per creare nuove credenziali on-demand quando un dispositivo scorre lungo la linea di produzione per essere bootstrappato con software e credenziali? Cosa accade alla linea di produzione se la connessione all'API Gateway che gestisce la registrazione IoT cade?
Preferirei evitare questi approcci, perché sono più complessi, soggetti a errori e impongono un onere inutile al produttore.
Un sistema di registrazione dei dispositivi sicuro e ragionevolmente scalabile, che vorrei vedere supportato da GCP, dovrebbe seguire queste linee guida:
- Si crea un singolo certificato IoT da collocare su tutti i dispositivi IoT. Questo certificato, denominato certificato di "bootstrap", sarebbe associato a una policy di permessi che consente al dispositivo di emettere una richiesta solo per (a) creare e recuperare credenziali specifiche per il dispositivo, qualora la richiesta venga accettata, e (b) aggiungersi all'IoT Registry dei dispositivi.
- Una volta ricevuta e accettata la richiesta di creazione delle credenziali, la piattaforma GCP IoT Core creerà una nuova coppia di chiavi. I permessi IoT associati — come fa Google Cloud oggi — dovrebbero consentire al dispositivo di pubblicare messaggi solo su un topic a esso univoco.
- L'autorizzazione alla creazione di credenziali univoche per dispositivo dovrebbe essere subordinata a una fase di validazione: una Cloud Function scritta da lei che richieda l'invio di identificatori univoci nella richiesta, in modo da poterli confrontare con una whitelist (es. un elenco di numeri di serie prodotti o di indirizzi MAC utilizzati) e/o una blacklist (es. un elenco di numeri di serie associati a dispositivi compromessi, abusivi o già registrati).
- Se la richiesta del certificato univoco per dispositivo viene approvata in fase di validazione, il dispositivo viene inserito nell'IoT Registry e i nuovi file di credenziali vengono consegnati al dispositivo per essere utilizzati nello streaming dei dati.
Con questo workflow, un produttore di dispositivi IoT dovrebbe semplicemente fornire a ciascun dispositivo il certificato di bootstrap. La coppia di chiavi univoca per dispositivo che abilita lo streaming dei dati potrebbe essere creata e ottenuta immediatamente all'interno dello stabilimento di produzione, se desiderato, oppure successivamente, quando il dispositivo è già nelle mani dell'utente finale.
A prescindere dal momento in cui le credenziali vengono ottenute, il produttore dovrebbe semplicemente caricare sul dispositivo il software che lei fornisce, il quale esegue il processo di creazione della coppia di chiavi univoca basato sul certificato di bootstrap quando:
- Il dispositivo si avvia
- È disponibile una connessione Internet, e
- Si rileva che la coppia di chiavi univoca per il dispositivo è mancante
Purtroppo, una funzionalità del genere è (per ora) assente. Ma al di là della registrazione massiva dei dispositivi, l'offerta Google Cloud IoT — abbinata ai servizi di elaborazione dei messaggi completamente gestiti a valle (trattati nella Parte Due) — costituisce nel complesso una soluzione cloud-native robusta, sicura e facilmente scalabile in ambito IoT.