Una delle principali caratteristiche di un oggetto nell’ambito dell’Internet of Things è la sua capacità di scambiare messaggi, inviando dati o ricevendo comandi, nel modo più efficace ed efficiente possibile. Esistono numerosi protocolli standard per questo scopo ma uno dei miei preferiti è MQTT.
Nel corso di questo articolo, vedremo come sia possibile utilizzare un client MQTT sulla board Intel Galileo con “Windows for IoT”, in modo da aggiungere a quest’ultima la potenzialità necessaria per poter essere riconosciuta come parte del mondo dell’Internet of Things.
Paho project : il client MQTT
Paho è un progetto open source della Eclipse Foundation che mette a disposizione una serie di client, sviluppati con differenti linguaggi di programmazione, per i principali protocolli utilizzati nell’ambito della M2M (Machine To Machine) communication e dell’IoT (Internet of Things). In particolare, la nostra attenzione è focalizzata sul client MQTT in linguaggio ANSI C che fornisce il supporto Posix/Windows e che espone due tipologie di APIs :
-
Sincrone : ogni chiamata è bloccante e ritorna il controllo al chiamante solo al termine dell’operazione richiesta;
-
Asincrone : l’operazione richiesta viene avviata in maniera asincrona restituendo immediatamente il controllo al chiamante e tutte le notifiche sono eseguite attraverso delle callback (molto utile nell’ambito di software con una UI);
Per poter compilare tale progetto utilizzando Visual Studio 2013, è necessario utilizzare GIT per eseguire il clone del corrispondente repository il cui URL è disponibile nella pagina principale della libreria nella sezione Downloads –> MQTT –> C/C++ –> C (Posix/Windows).
Nella sottocartella “Windows Build”, possiamo trovare la solution “Paho C MQTT APIs” i cui progetti sono i seguenti :
-
MQTTVersion : applicazione console che visualizza la versione corrente di una specifica libreria;
-
paho-mqtt3c, paho-mqtt3a : sono rispettivamente le librerie MQTT sincrone ed asincrone senza il supporto SSL;
-
paho-mqtt3cs, paho-mqttas : sono rispettivamente le librerie MQTT sincrone ed asincrone con il supporto SSL;
-
stdoutsub, stdoutsuba : applicazioni console che forniscono un subscriber in modalità sincrona ed asincrona;
-
test1, test3 : applicazioni console di test per la libreria sincrona rispettivamente senza e con SSL;
-
test4, test5 : applicazioni console di test per la libreria asincrona rispettivamente senza e con SSL;
La solution è ben strutturata ma purtroppo è necessario effettuare una serie di modifiche alle impostazioni per poter compilare i progetti su Windows, per poi passare all’esecuzione sulla Intel Galileo con “Windows for IoT”.
Compiliamo la libreria sincrona
Focalizziamo la nostra attenzione sulla libreria che fornisce l’implementazione sincrona (paho-mqtt3c) senza il supporto SSL nella configurazione di Debug. Essa compila senza alcun problema ma per l’esecuzione sulla Intel Galileo è necessario disabilitare le “enhanced instructions” a causa di un errore a runtime di “illegal instruction” sulla funzione difftime. Ciò è possibile attraverso le proprietà del progetto ed impostando “No Enhanced Instructions (/arch:IA32)” in C/C++ –> Code Generation –> Enable Enhanced Instruction Set.
Le modifiche principali vanno effettuate sul progetto test1 per la libreria suddetta, in quanto esso non compila immediatamente a causa di una serie di impostazioni errate.
In primo luogo fallisce l’inclusione del file MQTTClient.h (Cannot open include file: ‘MQTTClient.h: No such file or directory) che possiamo risolvere aggiungendo la corrispondente directory nelle proprietà del progetto; in particolare va aggiunto il path $(SolutionDir)\..\src in C/C++ –> General –> AdditionalIncludeDirectoris.
Inoltre, è necessario aggiungere le seguenti define in C/C++ –> Preprocessor –> Preprocessor Definitions :
-
_WINDOWS : utilizzata per evitare l’inclusione di alcuni header files legati a Linux e garantire l’inclusione degli header files relativi alle WinSock;
-
_CRT_SECURE_NO_WARNINGS : purtroppo la libreria fa uso di molte funzioni nella versione “unsafe” (es. strtok al posto di strtok_s);
A questo punto, il compilatore riesce a fare il proprio lavoro ma il Linker segnala una serie di “unresolved externals”, in quanto non è in grado di trovare i simboli relativi alla libreria WinSock e la libreria MQTT. Nel caso della libreria WinSock, va aggiunto il riferimento per il Linker alla libreria ws2_32.lib in Linker –> Input –> Additional Dependencies.
Per quanto riguarda la libreria MQTT, possiamo referenziare direttamente il progetto (visto che è nella medesima solution) in Common Properties –> References –> Add New Reference.
Con queste ultime modifiche la compilazione viene eseguita correttamente ma purtroppo se proviamo ad eseguire l’applicazione di test sul nostro PC, ci ritroviamo di fronte ad un errore di “stack corruption”. Ho prontamente segnalato il bug (potete trovare i dettagli qui) che con la versione corrente non è stato ancora messo a posto. La soluzione consiste semplicemente in una modifica nel file MQTTClient.c (funzione MQTTClient_deliverMessage) e nello spostare la seguente riga di codice :
ListRemove(m->c->messageQueue, m->c->messageQueue->first->content);
subito dopo #endif e la chiamata della funzione MQTTPersistence_unpersistQueueEntry.
Il primo test su PC
Prima di lanciare l’esecuzione dell’applicazione di test sulla Intel Galileo, possiamo accertarci che tutto funzioni correttamente eseguendola sul proprio PC. In primo luogo, dobbiamo scegliere un broker MQTT per poter eseguire i test (oppure utilizzare quello online di default). Io ho preferito utilizzare un broker molto leggero come Mosquitto che è possibile scaricare qui. Lanciamo il broker con l’opzione “-v” ossia in modalità “verbose” in modo da poter vedere tutti i messaggi di debug durante il test.
Prima di ricompilare e lanciare l’applicazione test1, è necessario modificare la struttura options che contiene, tra l’altro, l’indirizzo del broker a cui collegarci (nel mio caso, l’indirizzo IP del mio PC).
struct Options
{
char* connection; /**< connection to system under test. */
char** haconnections;
int hacount;
int verbose;
int test_no;
int MQTTVersion;
int iterations;
} options =
{
"tcp://192.168.10.188:1883",
NULL,
0,
0,
0,
MQTTVERSION_DEFAULT,
1,
};
Se tutto è impostato nel modo corretto, l’applicazione di test verrà eseguita senza alcun problema.
MQTT con “Windows for IoT”
Una volta accertato il funzionamento sul PC, possiamo passare alla configurazione del remote debugging per eseguire l’applicazione sulla board Intel Galileo direttamente da Visual Studio; le impostazioni necessarie sono disponibili sul sito ufficiale di Windows On Devices.
Anche in questo caso, lanciando l’applicazione in debug dovremmo vedere tutti i messaggi nella console di Mosquitto che vengono scambiati con la board.
Abbiamo un client MQTT in esecuzione su di essa !
Se siamo curiosi di vedere anche l’output dell’applicazione di test, possiamo lanciarla attraverso una sessione Telnet direttamente dalla board. Al termine dell’esecuzione, viene visualizzato il report con tutti i test superati.
Ovviamente, tutte le modifiche apportati ai progetti relativi alla libreria sincrona, possono essere applicate anche ai progetti relativi alla libreria asincrona senza alcuna differenza con la garanzie di avere il medesimo risultato.