In questa lezione impari a
- capire a cosa serve una piattaforma IoT
- creare un dispositivo e collegarlo con il suo token
- mandare telemetria con MQTT (e con HTTP)
- costruire una dashboard con indicatori e grafici
- impostare un allarme
Nel laboratorio 2 abbiamo costruito un impianto IoT "fatto in casa": il nostro broker, la nostra dashboard. Funziona, ma le aziende usano piattaforme IoT già pronte, che in più salvano tutte le misure in un database, fanno dashboard con pochi clic, mandano allarmi e gestiscono utenti e permessi.
Oggi usiamo una delle più diffuse, ThingsBoard. Gira su ServerLab, il server della scuola: voi non installate niente, vi servono solo Python e il browser.
Il kit della lezione
| File | A cosa serve |
|---|---|
sensore_tb.py |
il sensore: manda temperatura, umidità e CO₂ a ThingsBoard con MQTT |
sensore_tb_http.py |
lo stesso sensore, ma con HTTP (se il docente vi dice che la porta 1883 è chiusa) |
requirements.txt |
le librerie: paho-mqtt e requests |
La prima volta: pip install -r requirements.txt.
ThingsBoard si apre nel browser all'indirizzo http://192.168.104.117:8080 (solo dalla rete della scuola). Il docente vi dà la vostra email e la vostra password.
Cosa cambia rispetto al laboratorio 2
LABORATORIO 2 LABORATORIO 3
sensore.py ──► broker.py ──► app.py sensore_tb.py ──► ┌─────────── ThingsBoard ───────────┐
(nostro) (nostra dashboard) │ broker MQTT · database · dashboard │
│ allarmi · utenti │
└────────────────────────────────────┘
▲
browser (voi)
Dentro ThingsBoard c'è un broker MQTT, proprio come il nostro broker.py. Il sensore funziona allo stesso modo: si collega e pubblica JSON. Cambiano solo tre cose: l'indirizzo del server, un token e il topic, che è fisso.
Passo 1: entrare e creare il dispositivo
- Aprite nel browser
http://192.168.104.117:8080ed entrate con la vostra email e password. Avete uno spazio tutto vostro: i compagni non vedono i vostri dispositivi e voi non vedete i loro. - Nel menu a sinistra: Entità → Dispositivi.
- Pulsante + in alto a destra → Aggiungi nuovo dispositivo. Nome:
sensore-aula. Poi Aggiungi.
Se il docente ha già creato il dispositivo per voi,
sensore-aulaè già nell'elenco: saltate il punto 3.
Passo 2: il token
ThingsBoard deve sapere quale dispositivo sta mandando i dati. Ogni dispositivo ha un token: una specie di password, una ventina di lettere e numeri a caso.
- Cliccate sul dispositivo
sensore-aula: si apre il pannello dei dettagli. - Pulsante Copia token di accesso.
- Nel kit aprite
sensore_tb.pye cambiate una sola riga, quella del token:
SERVER = "192.168.104.117" # ThingsBoard su ServerLab: già giusto, non cambiatelo
TOKEN = "INCOLLA-QUI-IL-TOKEN" # il token del VOSTRO dispositivo
Incollate il token tra le virgolette, al posto di INCOLLA-QUI-IL-TOKEN. SERVER è già giusto.
Passo 3: mandare i dati
python sensore_tb.py
Deve comparire Collegato a ThingsBoard! e poi una riga Inviato -> ... ogni 5 secondi. Tornate nel browser, sul dispositivo, scheda Ultima telemetria: le misure arrivano e si aggiornano da sole.
Ecco le righe nuove del codice:
TOPIC = "v1/devices/me/telemetry" # il topic fisso di ThingsBoard per le misure
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(TOKEN) # il token fa da "nome utente"
client.on_connect = collegato
client.connect(SERVER, 1883)
client.loop_start()
- Il topic è sempre
v1/devices/me/telemetry, per tutti. me vuol dire "io": è il token a dire a ThingsBoard chi è "io". username_pw_set(TOKEN): in MQTT ci si può collegare con nome utente e password. ThingsBoard usa il token come nome utente, e la password non serve.- Il resto è il sensore del laboratorio 2: un dizionario,
json.dumps,publish.
def collegato(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("ThingsBoard ha rifiutato il collegamento:", reason_code)
print("-> Controllate di aver copiato bene il TOKEN.")
else:
print("Collegato a ThingsBoard!")
Se il token è sbagliato, ThingsBoard rifiuta il collegamento (Not authorized). La callback collegato ce lo dice in chiaro.
E se la porta 1883 è chiusa?
In alcune reti la porta di MQTT è bloccata. ThingsBoard accetta le misure anche con HTTP, cioè con una normale richiesta POST, come nell'API della Bacheca. In sensore_tb_http.py il token sta dentro l'indirizzo:
URL = f"http://{SERVER}:8080/api/v1/{TOKEN}/telemetry"
risposta = requests.post(URL, json=misura, timeout=5) # 200 = ok, 401 = token sbagliato
Il risultato su ThingsBoard è identico.
| MQTT | HTTP | |
|---|---|---|
| Collegamento | resta aperto | una richiesta per ogni misura |
| Dove sta il token | nome utente | nell'indirizzo |
| Porta | 1883 | 8080 |
| Il server può mandare comandi al sensore? | sì, subito (Missione 5) | solo se il sensore glieli chiede |
Telemetria e attributi
ThingsBoard distingue due tipi di dati:
- Telemetria: misure che cambiano nel tempo (temperatura, CO₂). ThingsBoard le salva tutte, con l'ora: si possono disegnare in un grafico.
- Attributi: informazioni "fisse" (in che aula sta il sensore, a che piano). Conta solo l'ultimo valore.
Nella Missione 4 il sensore manda anche i suoi attributi.
Se qualcosa non va
| Problema | Causa | Soluzione |
|---|---|---|
Prima incollate in TOKEN… |
non avete cambiato TOKEN |
Passo 2 |
Not authorized |
token sbagliato o incompleto | ricopiatelo con Copia token di accesso |
TimeoutError / ConnectionRefusedError |
non siete sulla rete della scuola, oppure la porta 1883 è chiusa | da scuola, usate sensore_tb_http.py; da casa ThingsBoard non è raggiungibile |
401 (versione HTTP) |
token sbagliato | come sopra |
Non collegato: aspetto… sempre |
ThingsBoard non raggiungibile | chiedete al docente se il server è acceso |
| Le misure non compaiono | state guardando un altro dispositivo | il token deve essere quello di sensore-aula |
Missioni
⭐ Missione 1 – Una misura in più
Aggiungete al dizionario misura di sensore_tb.py la luce (un numero a caso tra 200 e 800). Riavviate il sensore e guardate Ultima telemetria: compare la nuova misura, senza configurare niente su ThingsBoard. Perché secondo voi?
⭐ Missione 2 – La dashboard
Menu Dashboard → + → Crea nuova dashboard (nome: "Aria in aula"). Poi Aggiungi nuovo widget:
- dalla raccolta Analogue gauges un Temperature radial gauge collegato al dispositivo
sensore-aula, chiavetemperatura; - dalla raccolta Charts un Time series chart con la chiave
co2.
Salvate (icona ✓ in alto) e guardate i valori muoversi.
⭐⭐ Missione 3 – L'allarme
Fate scattare un allarme quando l'aria è viziata. Sul dispositivo, scheda Regole allarme → + → Crea nuova regola allarme: tipo di allarme "CO2 alta", condizione co2 maggiore di 1000. Aspettate che la CO₂ salga: l'allarme compare nel menu Allarmi. Aggiungete alla dashboard il widget Alarms table (raccolta Alarm widgets).
⭐⭐ Missione 4 – Chi sono
Fate in modo che il sensore, appena collegato, mandi i suoi attributi: l'aula, il piano e il tipo di sensore. Il topic è v1/devices/me/attributes e il messaggio è un JSON come per la telemetria. Controllate nella scheda Attributi del dispositivo (attributi client).
Aiutino
Dentro collegato, nel ramo else (quando il collegamento è riuscito):
client.publish("v1/devices/me/attributes", json.dumps({"aula": "5A", "piano": 1})).
Lo mettiamo lì perché basta mandarli una volta, all'inizio.
⭐⭐⭐ Missione 5 – La ventola, dalla dashboard
Come nel laboratorio 2, ma con ThingsBoard: dalla dashboard si manda il comando ventola al sensore, che stampa "🌀 Ventola accesa", fa scendere la CO₂ e risponde. In ThingsBoard i comandi si chiamano RPC. Per mandarli, aggiungete alla dashboard il widget RPC debug terminal (raccolta Control widgets), collegato al dispositivo: scrivendo ventola e premendo Invio il comando parte.
Aiutino
I comandi arrivano sul topic v1/devices/me/rpc/request/<numero>: iscrivetevi a v1/devices/me/rpc/request/+ (dentro collegato). Il messaggio è un JSON come {"method": "ventola", "params": {}}. Per rispondere si pubblica su v1/devices/me/rpc/response/<numero>, con lo stesso numero della richiesta: numero = msg.topic.split("/")[-1]. La risposta (es. {"ventola": "accesa"}) compare nel terminale della dashboard.
⭐⭐⭐ Missione 6 – Due aule
Create un secondo dispositivo (sensore-lab), fate una copia di sensore_tb.py con il suo token e avviatela in un altro terminale. Poi fate in modo che il grafico della CO₂ mostri le due aule insieme, con due colori.