Contattaci

Azure MQTT 

Azure MQTT
  • Data: 19 Dicembre 2022
  • Autore: Alessio Benedetti
  • Categorie

  • Giuneco Tech

    Il nostro settore richiede uno studio continuo e una forte attenzione all’innovazione. Incentiviamo quindi dei programmi formativi annuali per tutti i componenti del team, con ore dedicate (durante l’orario di lavoro) e serate formative sia online che in presenza. Sponsorizziamo eventi, sia come partner che semplicemente come partecipanti, e scriviamo articoli su quello che abbiamo imparato per essere, a nostra volta, dei divulgatori.

    Vai alla sezione Team
  • Azure MQTT 

    MQTT (Message Queue Telemetry Transport) è un protocollo di messaggi client/server di tipo publisher/subscriber costruito utilizzando TCP/IP. È stato progettato per essere leggero e avere un basso impatto nell’uso della rete; queste caratteristiche lo rendono ideale per l’uso in molte situazioni, inclusi ambienti vincolati, come ad esempio per la comunicazione in contesti Machine to Machine (M2M) e Internet of Things (IoT) in cui è richiesto un basso uso di dati trasmessi e/o larghezza di banda di rete. 

    Caratteristiche di MQTT 

    ◊ Utilizza un modello publisher/subscriber che fornisce la distribuzione di messaggi uno a molti e il disaccoppiamento delle applicazioni che ne fanno uso. 

    ◊ Il trasporto di messaggi è indipendente dal contenuto. 

    ◊ Qualità del servizio (QoS) che definisce le possibilità d’invio di messaggi a seconda della rete sottostante  

    • QoS = 0 Al massimo una volta: i messaggi vengono consegnati secondo i migliori sforzi dell’ambiente operativo. Può verificarsi la perdita di messaggi. Questo livello potrebbe essere utilizzato, ad esempio, con i dati di sensori ambientali, dove non importa se una singola lettura viene persa poiché quella successiva verrà pubblicata subito dopo. 
    •  QoS = 1 Almeno una volta: dove è garantito l’arrivo dei messaggi ma possono verificarsi duplicati. 
    •  QoS = 2 Esattamente una volta: dove è garantito che i messaggi arrivino esattamente una volta. Questo livello potrebbe essere utilizzato, ad esempio, con sistemi di fatturazione in cui i messaggi duplicati o persi potrebbero comportare l’applicazione di addebiti errati. 

    ◊ Un meccanismo per notificare alle parti interessate quando si verifica una disconnessione anomala

     

    Esempio d’interazione del protocollo MQTT:

     

     

    CONNECT:

    Richiesta di connessione tra client e server, la richiesta contiene uno o più campi codificati: un identificatore client univoco (ClientId), un argomento, un payload, nome utente e password. Tutto tranne l’identificatore del client può essere omesso e la loro presenza è determinata in base ai flag nell’intestazione della richiesta.

    • Clean Session: Flag che se impostato su 0 obbliga il server a riprendere le comunicazioni con il client in base allo stato della sessione corrente (come identificato dall’identificatore del client). Se non vi è alcuna sessione associata all’identificatore del client, il server deve crearne una nuova. Il client e il server archiviano la sessione dopo che sono stati disconnessi. Dopo la disconnessione di una sessione che aveva CleanSession impostato su 0, il server deve archiviare tutti i messaggi QoS 1 e QoS 2 che corrispondono a qualsiasi sottoscrizione che il client aveva al momento della disconnessione come parte dello stato della sessione. Se CleanSession è impostato su 1, il client e il server devono eliminare qualsiasi sessione precedente e avviarne una nuova. Questa sessione dura quanto la connessione di rete. I dati sullo stato associati a questa sessione non devono essere riutilizzati in alcuna sessione successiva

    CONNACK:

    Il server risponde ad una richiesta di connessione con il risultato (Success) oppure richiedendo opzioni aggiuntive di autenticazione (tramite richieste AUTH) se utilizzate.

    SUBSCRIBE:

    Viene inviato al server per creare una o più sottoscrizioni. Ciascuna sottoscizione registra l’interesse di un client per uno o più Argomenti. Il server invia pacchetti PUBLISH al client per inoltrare i messaggi dell’applicazione che sono stati pubblicati su argomenti che corrispondono a queste sottoscrizioni. Il pacchetto SUBSCRIBE specifica inoltre (per ogni sottoscizione) la QoS massima con cui il server può inviare messaggi al client.

    Retain Handling option: Se il server ha abilitato la policy di RETAIN sui messaggi ricevuti è possibile specificare come il client vorrebbe gestire i vecchi messaggi salvati dal server.

    • 0. Invia al client messaggi conservati precedentemente al momento della sottoscrizione
    • 1. Invia al client messaggi conservati precedentemente alla sottoscrizione solo se la sottoscrizione è nuova
    • 2. Non inviare i messaggi conservati

    PUBLISH:

    Possono essere inviati sia da client a server che viceversa. I messaggi utilizzati dal protocollo contengono i dati del payload, un informazione sulla qualità del servizio (QoS), una raccolta di proprietà e il nome dell’argomento.

    • QoS : è possibile specificare nell’header del messaggio quale livello si intende utilizzare
    • DUP: Flag per determinare la re-spedizione del messaggio (a seconda del livello di QoS)
    • RETAIN: Se il flag è impostato su 1 in un pacchetto PUBLISH inviato da un client a un server, il server DEVE sostituire qualsiasi messaggio conservato esistente per questo argomento e memorizzare il messaggio dell’applicazione in modo che possa essere consegnato ai futuri sottoscrittor. Se il payload contiene zero byte, viene elaborato normalmente dal server, ma qualsiasi messaggio conservato con lo stesso nome dell’argomento verrà rimosso e qualsiasi futuro sottoscrittore per l’argomento non riceverà un messaggio conservato. Se il server non supporta la policy di RETAIN verrà inviato un messaggion di DISCONNECT al client che ha fatto richiesta.

    DISCONNECT:

    Messaggio di controllo MQTT finale inviato dal client o dal server che chiude la connessione. Indica il motivo per cui la connessione di rete viene chiusa.

    Esistono poi altre tipologie di comandi definiti dallo standard MQTT:

    • PUBACK : per la gestione QoS 1
    • PUBREC, PUBREL, PUBCOMP: Per la gestione QoS 2
    • SUBACK, UNSUBSCRIBE, UNSUBACK: per la gestione della sottoscrizione
    • PINGREQ, PINGRESP: per la verifica di attività

     

    Azure IoT Hub

    Azure IoT Hub offre comunicazioni bidirezionali sicure con i propri dispositivi per comunicare mediante l’invio di messaggi dai propri dispositivi alle soluzioni di back-end e viceversa.

    Azure ha integrato nella sua piattaforma di gestione IoT il protocollo MQTT, tramite l’uso dello IoT Hub è possibile mettere in comunicazione tra loro i dispositivi ad esso connessi. L’hub IoT non è un broker MQTT completo e non supporta tutti i comportamenti specificati nello standard MQTT v3.1.1 (esiste poi anche un implementazione in preview di MQTT v5).

    Un dispositivo può usare il protocollo MQTT per connettersi a un IoT Hub usando l’SDK fornito da Microsoft che utilizza la porta 8883 oppure, tramite WebSocket, la porta 443. SDK che puo essere utilizzato in diversi linguaggi: Node.JS, Java, C, C#, Python.

    Di seguito un esempio, utilizzando la libreria .NET C#:

    Come prima cosa è necessario creare un DeviceClient, classe che si occuperà di gestire tutte le comunicazioni descritte in precedenza per il protocollo MQTT:

    var deviceClient = DeviceClient.CreateFromConnectionString(parameters.PrimaryConnectionString, TransportType.Mqtt);
    

    Per inviare messaggi dal dispositivo al IoT HUB utilizzando il protocollo MQTT possiamo utilizzare un procedimento simile al seguente:

    private async Task SendDeviceToCloudMessagesAsync(CancellationToken ct)
    {
        // Initial telemetry values
        double minTemperature = 20;
        double minHumidity = 60;
        var rand = new Random();
    
        try
        {
            while (!ct.IsCancellationRequested)
            {
                double currentTemperature = minTemperature + rand.NextDouble() * 15;
                double currentHumidity = minHumidity + rand.NextDouble() * 20;
    
                // Create JSON message
                string messageBody = JsonSerializer.Serialize(
                    new
                    {
                        temperature = currentTemperature,
                        humidity = currentHumidity,
                    });
                using var message = new Message(Encoding.ASCII.GetBytes(messageBody))
                {
                    ContentType = "application/json",
                    ContentEncoding = "utf-8",
                };
    
                // Add a custom application property to the message.
                message.Properties.Add("temperatureAlert", (currentTemperature > 30) ? "true" : "false");
    
                // Send the telemetry message
                await _deviceClient.SendEventAsync(message, ct);
                Console.WriteLine($"{DateTime.Now} > Sending message: {messageBody}");
    
                await Task.Delay(1000, ct);
            }
        }
        catch (TaskCanceledException) { } 
    }
    

    Nella fase d’invio esistono alcune limitazioni:

    • L’hub IoT non supporta i messaggi QoS 2. Quando un’app per dispositivo pubblica un messaggio con QoS 2, l’hub IoT chiude la connessione di rete.
    • L’hub IoT non mantiene i messaggi. Se un dispositivo invia un messaggio con il flag RETAIN impostato su 1, l’hub IoT aggiunge la proprietà dell’applicazione mqtt-retain al messaggio. In tal caso, anziché rendere persistente il messaggio di mantenimento, l’hub IoT potrebbe passarlo invece all’app back-end.
    • L’hub IoT supporta solo una connessione MQTT attiva per ogni dispositivo. Qualsiasi nuova connessione MQTT per conto dello stesso ID dispositivo causa l’eliminazione della connessione esistente dell’hub IoT e un eccezione (400027 ConnectionForcesedOnNewConnection) verrà registrata nei log dell’hub IoT.
    • Per instradare i messaggi in base al corpo del messaggio, è necessario aggiungere prima la proprietà ‘contentType’ e impostare il relativo valore su application/json;charset=utf-8. Come illustrato nell’esempio sopra.

    Per sottoscriversi alla ricezioni di messaggi invece è possibile utilizzare la funzione “SetReceiveMessageHandlerAsync” messa a disposizione dalla libreria, di seguito un esempio:

    // Subscribe to receive C2D messages through a callback.
    await _deviceClient.SetReceiveMessageHandlerAsync(OnC2dMessageReceivedAsync, _deviceClient);
    Console.WriteLine($"\n{DateTime.Now}> Subscribed to receive C2D messages over callback.");
    
    Console.WriteLine($"\n{DateTime.Now}> Device waiting for C2D messages from the hub...");
    Console.WriteLine($"{DateTime.Now}> Use the Azure Portal IoT Hub blade or Azure IoT Explorer to send a message to this device.");
    
    // Unsubscribe from receiving the callback.
    await _deviceClient.SetReceiveMessageHandlerAsync(null, null);

    Fatto questo è possibile ricevere tramite eventi di callback i messaggi relativi alla sottoscrizione che abbiamo fatto. È possibile anche specificare l’argomento per il quale vogliamo ricevere messaggi.

    Conclusioni: potenzialità di uno strumento per la comunicazione tra dispositivi

    Come descritto, Azure IoT Hub offre un semplice meccanismo di gestione messaggi publisher/subscriber, implementando, anche se non al 100%, il protocollo MQTT (Esistono anche altri protocolli messi a disposizione dal IoT Hub come ad esempio AMQP). Oltre a questo loT Hub mette a disposizione anche una serie di altre funzionalità utili alla costruzione di un’infrastruttura di comunicazione tra dispositivi, come adesempio l’uso di dispositivi Gemelli che rappresentano su cloud la loro controparte fisica oppure l’utilizzo di chiamate dirette a metodi HTTP (invece di utilizzare MQTT). In questo articolo è stato riportato un esempio che mostra una piccola parte delle possibilità offerte da Azure IoT Hub.