Usare MQTT per comunicare con Rasberry

In questa breve nota, descrivo come installare un broker MQTT nel caso sia necessaria una comunicazione a due vie su Internet (o più precisamente su TCP/IP) con una applicazione configurata su di una scheda Raspberry.

Il modello a code di MQTT

Il broker come gestore di code multiple

Un broker MQTT è un programma che gestisce code per conto di client remoti che si collegano tramite Internet (TCP/IP).
I client possono sia pubblicare messaggi testuali nel broker (pubblicatori) e/o possono connettersi al broker ed essere notificati di tutti o alcuni messaggi trasmessi da qualche pubblicatore. In questo caso i client solo sottoscrittori.

I Topic

Un concetto importante nel protocollo MQTT è quello di "topic". Un broker MQTT può essere pensato come amministratore di un numero imprecisato di code, ciascuna contraddistinta da un nome chiamato appunto topic, cioè argomento. Questo permette ai client sottoscrittori che si connetteranno al broker di essere informati solo di alcuni messaggi, appartenenti cioè a quei topic che hanno selezionato al momento della sottoscrizione
Un client pubblicatore dovrà associare un topic ad ogni messaggio, così il broker capirà se accodare il messaggio in qualche coda, se la coda per quel topic già esiste, o creare una nuova coda per un topic non usato in precedenza.

Topic e code gerarchiche

Le code di un broker MQTT non sono semplici code, ma code gerarchiche
Un topic è identificato da una chiave gerarchica, cioè una serie di nomi separati da punti, un po' come per gli indirizzi di internet. Ad esempio ci possono essere questi topic:

topic1.area1.sezioneC
topic1.area1.sezioneD
topic1.area2
topic2

Questo permette ad un sottoscrittore di configurarsi come ascoltatore di una categoria di messaggi, cioè messaggi provenienti da più di una coda, contraddistinta dagli identificatori più a destra. Per esempio:

- chi si sottoscrive a topic1.* riceverà i messaggi di topic1.area1.sezioneC,
topic1.area1.sezioneD e topic1.area2 ma non di topic2.
- chi si sottoscrive a topic1.area2 riceverà solo i messaggi di topic1.area2 ma non quelli di topic1.area1.sezioneCtopic1.area1.sezioneD
- chi si sottoscrive a topic2, riceverà solo i messaggi di topic2 e nessun altro.

Questo modello gerarchico conferisce ad MQTT una estrema flessibilità e generalità di utilizzo.
Accenno solo che esistono anche strutture di sottoscrizione più complesse di questa, ma potete far riferimento alla documentazione di MQTT (http://mqtt.org/documentation).

Passi di Configurazione

1. Installare il Broker MQTT

MQTT è definito primariamente in un'architettura centralizzata, in cui cioè è definito un unico gestore delle code dei messaggi detto broker.
Essendo MQTT un protocollo standard OASIS, siamo liberi di scegliere il broker che più ci piace per le nostre applicazioni. Trattandosi però di utilizzare Raspberry come nodo centrale dell'applicazione, dovremmo cercare di trovare un broker che usi il minor numero di risorse possibile, ovvero che non carichi la CPU di processi non strettamente necessari e che non utilizzi troppa memoria.

La mia scelta è caduta su Mosquitto , ma altri broker possono essere altrettanto validi.
Mosquitto (http://mosquitto.org/) è realizzato in C ed è un server molto leggero. E' stato sviluppato dallo stesso gruppo che ha fornito il codice client ad Eclipse.org per dar vita al progetto Paho (che vedremo in seguito).
La sua semplicità di realizzazione gli permette di essere supportato praticamente da qualsiasi sistema, Linux, Windows, Mac. Essere scritto in C gli permette di essere utilizzato praticamente ovunque.

Gli sviluppatori di Mosquitto hanno anche creato un repository Debian apposito per l'uso su Raspberry e questo è un'altra buona ragione per sceglierlo come broker MQTT su questa scheda.

Per installare pacchetti SW su Raspberry possiamo sia scaricare il file .deb corrispondente, copiarlo su Raspberry ed installarlo con l'utility dpkg, o utilizzare il comando apt-get per installare il pacchetto e le sue dipendenze. La seconda opzione richiede ovviamente che Raspberry acceda autonomamente ad Internet. 
Io considero valida solo questa seconda possibilità, perchè Mosquitto è un software orientato all'Internet delle Cose, per cui non avrebbe senso installarlo su di un Raspberry non abilitato alla rete. Nel mio caso, il Raspberry accede alla rete per mezzo di una comunissima chiavetta WiFi, ma è possibile anche collegare Raspberry ad un router WiFi con un cavo Ethernet.

1.1 Configurare il repository su Raspberry

Se non è stato già fatto in precedenza, è necessario configurare apt su Raspberry per utilizzare il repository di Mosquitto.

I passi sono descritti dalla schermata:

  • Si scarica la chiave di autenticazione del repository (con wget) e la si installa fra le chiavi di apt (con sudo apt-key)
  • Poi si scarica la lista aggiornata dei pacchetti disponibili sotto /etc/apt/sources.list.d, sempre usando wget preceduto dal solito sudo.
  • Alla fine si aggiorna la configurazione di apt con il comando apt-get update. Questo provoca l'aggiornamento di tutte le liste dei repository
Prestate attenzione agli URL utilizzati nelle wget e controllate che siano quelli aggiornati. Al momento di quando è stato scritto il tutorial il repo di Mosquitto per Debian era mosquitto-stable.list, ma nel frattempo è cambiato in mosquitto-jessie.list.

1.2 Installazione del pacchetto

Se quanto fatto finora è andato bene, l'installazione di Mosquitto è semplice come dare il solo comando:

# sudo apt-get install mosquitto 

L'installazione termina normalmente con successo. Mosquitto è pronto!

1.3 Installare i client per i test

Anche se non strettamente necessario, è buona norma installare anche i programmi "client" di Mosquitto, ovvero delle utility a riga di comando che permettono di dialogare con il broker per verificarne le funzionalità.
I client si installano con il solito apt-get:

# apt-get install mosquitto-clients

vedremo poi come usarli.

2. Prima verifica

Mosquitto viene installato come servizio di Linux. Una volta installato, apt lo avvia e Mosquitto verrà avviato ad ogni avvio di Raspberry, se non diversamente configurato, tra i servizi Linux.

Per verificare lo stato di esecuzione, possiamo usare il solito comando service:

# sudo service mosquitto status

Il comando risponde con un semplice:

[ ok ] mosquitto is running.

Per fermare o riavviare il servizio, si usano i soliti comandi di service:

# sudo service mosquitto stop

# sudo service mosquitto reload

Il secondo comando è utile se viene modificata qualche configurazione di Mosquitto.

3. Configurazione

Il file di configurazione di mosquitto si trova in /etc/mosquitto/mosquitto.conf

Il pacchetto include anche la directory /etc/mosquitto/conf.d/  ed è consigliabile di scrivere in questa directory i settaggi di configurazione personalizzati piuttosto che modificare il file mosquitto.conf. Questo permette di proteggere le personalizzazioni da eventuali sovrascritture successive per aggiornamenti.
Un file di configurazione aggiuntivo è un semplice file di testo con la semplice struttura a coppie separate da spazi.

Ad esempio: mio_broker.conf

opzione1 valore1
opzione2 valore2
...

Normalmente Mosquitto si avvia dopo l'installazione senza alcun bisogno di configurarlo, utilizzando i valori di default. Tuttavia può essere necessario in certi casi modificare la configurazione. 
Queste che seguno sono le situazioni più comuni, ma tutte le opzioni di configurazione possono essere trovate nella documentazione di mosquitto.conf.
  • Selezionare l'interfaccia di rete e la porta su cui ascoltare i client (di default ascolta su tutte le interfacce e sulla porta IP 1883)
  • Disattivare l'accesso anonimo e forzare l'utilizzo di username e password
  • Utilizzare un servizio esterno per l'autenticazione
  • Attivare il broker solo su connessione sicura TSL/SSL (certificazione del server)
  • Redirigere i log files verso altre destinazioni 
  • Attivare una persistenza, così che i messaggi attivi vengono ricaricati dopo l'arresto e riavvio del broker
  • Far dialogare più broker fra di loro (modalità "bridge", per reti complesse)

4. Test di rete

Per testare mosquitto sulla rete, è necessario usare un'altro PC come client ed installare su di esso i client di Mosquitto (mosquitto_clients).
Un'esperimento facile potrebbe essere quello di inviare un messaggio da un PC e vederlo apparire in di una console aperta sul Raspberry. 
Il video che segue mostra questo semplice test. In esso, la finestra azzurra è quella del PC client, quella nera è la console del Raspberry.

  • Sul Raspberry, una sessione client si sottoscrive al broker sul topic raspi.test
  • Sul PC, una sessione client pubblica il messaggio "Hello World" sul broker in funzione all'indirizzo 192.168.0.11 (cioè sul Raspberry) nel topic raspi.test
  • Il Raspberry mostra il messaggio "Hello World" ricevuto via rete dal broker e notificato alla sessione client
Un'altro test interessante è quello di usare l'app MyMQTT per Android ed collegare lo smartphone nella rete in cui è presente il Raspberry con il broker in funzione. Questo test è mostrato nel video seguente

  • Sullo smartphone, una sessione client con MyMQTT si sottoscrive al broker sul topic raspi.smart
  • Sul PC, una sessione client pubblica il messaggio "Questo è per lo smartphone" sul broker in funzione sul Raspberry nel topic raspi.smart
  • Lo smartphone mostra il messaggio "Questo è per lo smartphone" ricevuto via rete dal broker e notificato alla sessione client
  • Il client sottoscritto come prima al topic raspi.test non mostra nulla perchè è su di un topic diverso.

5. Sviluppo 

Per poter interfacciare un'applicazione al broker, è necessario che essa faccia uso di librerie opportune che supportino il dialogo con il protocollo MQTT.
Come detto in precedenza, il progetto Paho di Eclipse.org, fornisce tutte le librerie che possono essere integrate nei vostri programmi per dialogare con un broker MQTT. In particolare la libreria Python di Paho è uno strumento che permette di creare semplici script per comunicare con un broker MQTT.

Un'altro modo per interfacciarsi con Mosquitto è quello di utilizzare la libreria C libmosquitto.(documentata in http://mosquitto.org/man/libmosquitto-3.html). 
libmosquitto è una semplice libreria C che può essere inclusa in programmi C/C++ per interagire con Mosquitto.
Esistono comunque anche librerie Java, Javascript, Python.





13 commenti:

  1. Ciao, il repository sembra essere cambiato, da mosquitto-stable.list a mosquitto-jessie.list, quindi si riceve un errore 404 cercando il vecchio repository, per il resto tutto funziona come spiegato. Grazie per aver pubblicato questo articolo

    RispondiElimina
    Risposte
    1. Ciao.
      Grazie del feedback. Correggo la nota al più presto

      Elimina
  2. ciao volevo fare una domanda, ma è possibile memorizzare i dati in mysql invece che in mosquito.db?

    RispondiElimina
    Risposte
    1. Ciao. Non mi risulta. Guardando la configurazione della persistence, non ci sono altre opzioni. Di fatto la persistence è il dump dell'in-memory DB utilizzato da Mosquitto, per cui (credo) non sia stato fatto uno sforzo per utilizzare altre forme di memorizzazione su disco.

      Elimina
  3. Ciao, una domanda. La connessione sicura con TSL/SSL è attivata di default? oppure bisogna configurarla?
    Grazie in anticipo per la disponibilità.

    RispondiElimina
    Risposte
    1. Ciao Michele
      Posso risponderti riguardo al broker che ho utilizzato, ovvero Mosquitto, e per esso la connessione sicura non è attiva per default. Va configurata. Questo richiede la creazione e gestione dei certificati server che verranno utilizzati per certificare la provenienza della comunicazione e la cifratura dei messaggi.

      Per altri broker non ti saprei dire, ma mi viene da pensare che dovrebbe essere lo stesso, visto che è improbabile che uno abbia già di default configurati correttamente i certificati.

      Mi viene in mente che questa pagina potrebbe esse completata proprio aggiungendo i passi di configurazione TSL/SSL, visto che questa è una condizione necessaria per qualsiasi applicazione basata su MQTT accessibile esternamente.

      Elimina
    2. Questo commento è stato eliminato dall'autore.

      Elimina
    3. Ciao , grazie per l'articolo di cui ho apprezzato la chiarezza in quanto novizio.

      Per quanto riguarda la configurazione SSL/TLS di Mosquitto sapresti indicarmi una guida online?

      Inoltre se ho capito bene l'abilitazione di SSL/TLS certifica il server e permette la comunicazione criptata tra disposivi e broker.
      Ma non impedirebbe a un dispositivo sconosciuto di connedderti al broker , sbaglio?

      grazie per la disponibilità
      Roberto

      Elimina
    4. Ciao Roberto
      Riguardo alla guida on-line, sono al tuo stesso livello, dovrei guardarci.
      Tuttavia, se apri il file di configurazione di Mosquitto, vedrai che tutta la sezione SSL/TLS è ricca di commenti e di indicazioni sull'uso di questo sistema.
      Su Linux, se chiami il comando "man mosquitto-tls" ottieni la pagina di help per questa configurazione.

      Mosquitto usa il layer SSL/TLS come qualunque altro software, essendo questa modalità uno standard. Per cui io inizierei con il capire come funziona in generale la comunicazione SSL/TLS e dopo darei un'occhiata al file di configurazione per avere le indicazioni di come configurare il server ed il client per l'uso della criptazione.

      Riguardo ai dispositivi sconosciuti, SSL/TLS non impedisce la loro connessione, come avviene del resto anche con l'https. Questo si ottiene configurando le password e le Access Control List (ACL) nella configurazione di Mosquitto.

      Elimina
  4. Ciao, guida molto interessante e ben fatta. Volevo chiederti se con mosquitto potevo far comunicare il raspberry con WeMos D1. In modo tale da mandare al raspberry dati, analizzarli e rimandare al WeMos l'azione corrispondente per quei dati.

    Grazie mille

    RispondiElimina
    Risposte
    1. Ti ringrazio molto.
      In generale, le condizioni per cui due entità possano comunicare con MQTT sono:
      1. supportino il TCP/IP
      2. esistano per entrambi la libreria client MQTT
      3. (nel caso non ci sia un broker esterno) uno dei due possa far girare un broker MQTT

      Nello specifico, Raspberry senz'altro ha tutto quello che serve.
      WeMos D1 essendo compatibile NodeMCU supporta la libreria PubSub, per cui, pur non avendo una esperienza diretta con WeMos, mi aspetto che si possa fare.
      Fammi sapere quando ci riesci.

      Elimina
  5. Ciao, grazie per la guida chiara ed efficace!
    Vorrei porti solo una domanda: sembrerebbe, secondo le caratteristiche descritte del protocollo MQTT, che sia possibile realizzare una comunicazione tra un client ed un broker senza che questi abbiamo indirizzo IP pubblico. Confermi questa possibilità? Ovvero, un dispositivo con una semplice connessione 3G, può ricevere ed inviare messaggi?
    Grazie mille per la tua disponibilità!

    RispondiElimina
  6. ciao,
    una domanda, ammettiamo due schede che si scambiano dati tramite MQTT, lettura scrittura, ad esempio, se una scheda invia un dato all'altra, ma per x motivi è offline, il dato resta nel topic e al prossimo collegamento viene letto o viene perso? esempio per accendere e spegnere una caldaia
    grazie

    RispondiElimina