Demo sulla condivisione della connessione CoreMQTT - FreeRTOS

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Demo sulla condivisione della connessione CoreMQTT

Importante

Questa è una versione archiviata della FreeRTOS User Guide da utilizzare con la versione FreeRTOS 202012.00. Per l'ultima versione di questo documento, consulta la FreerTOS User Guide.

Introduzione

Il progetto dimostrativo di condivisione della connessione CoreMQTT mostra come utilizzare un'applicazione multithread per stabilire una connessione al broker AWS MQTT utilizzando TLS con autenticazione reciproca tra il client e il server. Questa demo utilizza un'implementazione dell'interfaccia di trasporto basata su MBEDTLS per stabilire una connessione TLS autenticata dal server e dal client e dimostra il flusso di lavoro di sottoscrizione-pubblicazione di MQTT a livello QoS 1. La demo sottoscrive un filtro per argomenti, pubblica gli argomenti che corrispondono al filtro e quindi attende di ricevere quei messaggi dal server a livello QoS 1. Questo ciclo di pubblicazione sul broker e ricezione dello stesso messaggio dal broker si ripete all'infinito. I messaggi in questa demo vengono inviati con QoS 1, che garantisce almeno una consegna secondo le specifiche MQTT.

Nota

Per configurare ed eseguire le demo di FreerTOS, segui i passaggi indicati. Guida introduttiva a FreerTOS

Questa demo utilizza una coda thread-safe per contenere i comandi per interagire con l'API MQTT. Ci sono quattro attività da prendere in considerazione in questa demo.

  • Un'attività di comando (principale) prende i comandi dalla coda dei comandi e li elabora. Le altre attività inseriscono i comandi in questa coda per l'elaborazione. Questa operazione entra in un ciclo durante il quale elabora i comandi. Se viene ricevuto un comando di terminazione, questa operazione verrà interrotta dal ciclo.

  • Un'attività di pubblicazione sincrona crea una serie di operazioni di pubblicazione e le inserisce nella coda dei comandi. Queste operazioni vengono quindi eseguite dal comando task. Questa attività utilizza la pubblicazione sincrona, il che significa che aspetterà il completamento di ogni operazione di pubblicazione prima di pianificare quella successiva.

  • Un'attività di pubblicazione asincrona crea una serie di operazioni di pubblicazione e le inserisce nella coda dei comandi. Queste operazioni vengono quindi eseguite dal comando task. La differenza tra questa attività e quella precedente è che non aspetterà il completamento di un'operazione di pubblicazione prima di pianificare quella successiva. Controlla lo stato di ogni operazione di pubblicazione dopo che tutte le relative operazioni di pubblicazione sono state aggiunte alla coda. Nota che la distinzione tra pubblicazione sincrona e asincrona riguarda solo il comportamento di queste attività. Non ci sono differenze negli effettivi comandi di pubblicazione.

  • Un'attività di sottoscrizione crea una sottoscrizione MQTT a un filtro di argomenti che corrisponde agli argomenti di tutti i messaggi pubblicati dalle due attività di pubblicazione. Questa attività entra in un ciclo continuo e attende di ricevere i messaggi pubblicati dalle altre attività.

Le attività possono avere code per contenere i messaggi ricevuti. L'operazione di comando inserirà i messaggi in arrivo nella coda di qualsiasi attività sottoscritta all'argomento in arrivo.

Questa demo utilizza una connessione TLS con autenticazione reciproca a cui connettersi. AWS Se la rete si disconnette inaspettatamente durante la demo, il client tenta di riconnettersi utilizzando la logica di backoff esponenziale. Se il client si riconnette con successo, ma il broker non riesce a riprendere la sessione precedente, il client riscriverà gli stessi argomenti della sessione precedente.

Thread singolo vs multithread

Esistono due modelli di utilizzo CoreMQTT, a thread singolo e a thread multiplo (multitasking). Questa demo mostra come creare uno schema di multithreading personalizzato. C'è anche un altro esempio multithread che esegue il protocollo MQTT in background all'interno di un'attività agente (o demone). Per ulteriori informazioni, vedere MWTT Agent and Demos using CoreMQTT. Se si esegue il protocollo MQTT in un'attività di agente, non è necessario gestire in modo esplicito alcuno stato MQTT o chiamare la funzione. MQTT_ProcessLoop Inoltre, se si utilizza un'attività agente, più attività dell'applicazione possono condividere una singola connessione MQTT senza la necessità di primitive di sincronizzazione, come i mutex.

Codice sorgente

Il file sorgente della demo è denominato mqtt_demo_connection_sharing.c e può essere trovato nella directory e nel sito Web. freertos/demos/coreMQTT/ GitHub

Funzionalità

Questa demo crea quattro attività in totale: tre che richiedono chiamate API MQTT e una che elabora tali richieste, che è l'attività principale. In questa demo, l'attività principale entra in un ciclo che crea le tre sottoattività, richiama il ciclo di elaborazione e successivamente si pulisce. L'attività principale crea una singola connessione MQTT al broker condivisa tra le sottoattività. Due delle sottoattività pubblicano messaggi sul broker e la terza riceve i messaggi, utilizzando un abbonamento MQTT a un filtro per argomenti che corrisponde a tutti gli argomenti dei messaggi pubblicati.

Typedef

La demo definisce le seguenti strutture, enumerazioni e puntatori di funzioni.

Comandi

Anziché effettuare direttamente le chiamate all'API MQTT, le attività utilizzano Command_t strutture per creare comandi che indicano all'attività principale di richiamare l'operazione API appropriata. I comandi hanno i seguenti tipi:

  • PROCESSLOOP

  • PUBLISH

  • SUBSCRIBE

  • UNSUBSCRIBE

  • PING

  • DISCONNECT

  • RECONNECT

  • TERMINATE

Il TERMINATE comando non ha un'operazione API MQTT corrispondente. Viene utilizzato nella demo per indicare all'attività principale di interrompere l'elaborazione dei comandi e iniziare le operazioni di pulizia. Perché alcune informazioni aggiuntive, ad esempio informazioni di pubblicazione o sottoscrizione, sono necessarie per alcuni comandi MQTT comeMQTT_Publish, e MQTT_SubscribeMQTT_Unsubscribe, utilizziamo il campo. CommandContext_t Questo campo è obbligatorio per questi tre comandi ed è facoltativo per gli altri.

Poiché questo contesto è necessario per questi comandi, non modificate questo valore una volta che il comando è stato messo in coda, fino al completamento del comando. Al termine di un comando, è possibile richiamare un callback opzionale. In questa demo, utilizziamo un callback che crea una notifica di attività per informare l'attività chiamante che il comando è stato completato. Per le operazioni MQTT che richiedono riconoscimenti (sottoscrizione, annullamento dell'iscrizione e pubblicazione con QoS superiore a 0), il comando viene considerato completato una volta ricevuta la conferma. In caso contrario, il comando viene completato una volta restituita la chiamata API MQTT corrispondente.

Nel mqtt_demo_connection_sharing.c file sono disponibili le seguenti definizioni:

Riconoscimenti

Poiché alcune operazioni MQTT richiedono un riconoscimento, utilizzano un array di AckInfo_t che contiene l'identificatore di pacchetto del riconoscimento previsto e il comando originale che lo prevede, in modo da poterne richiamare il callback di completamento.

Sottoscrizioni

Questa demo può tenere traccia delle sottoscrizioni per ogni attività. A tal fine, ogni attività che richiede un abbonamento deve fornire una coda di messaggi in cui riceverà i messaggi pubblicati (SubscriptionElement_t). Più attività possono sottoscrivere lo stesso filtro per argomenti, poiché è previsto che utilizzino code di risposta separate.

Messaggi pubblicati ricevuti

Poiché le attività vengono eseguite in parallelo all'attività principale, sarebbe difficile e dispendioso in termini di tempo per l'attività principale dover attendere che ogni attività sottoscritta legga un messaggio pubblicato ricevuto. Pertanto, ogni messaggio ricevuto viene copiato nella coda di risposta di qualsiasi attività sottoscritta all'argomento del messaggio pubblicato (_t). PublishElement Poiché i pacchetti di pubblicazione ricevuti dal client MQTT contengono puntatori al buffer di rete del client, il payload e il nome dell'argomento del messaggio in arrivo vengono copiati in buffer separati prima di essere inseriti in una coda di risposta. In questo modo, l'operazione sottoscritta può ancora leggere le informazioni ricevute dopo che il client MQTT ha cancellato il buffer di rete.

Attività principale

L'attività principale dell'applicazione stabilisce una sessione MQTT persistente, crea tre sottoattività ed esegue il ciclo di elaborazione fino alla ricezione di un comando di terminazione. RunCoreMQTTConnectionSharingDemo Viene utilizzata una sessione persistente, quindi se la rete si disconnette inaspettatamente, la demo si riconnetterà al broker in background, senza perdere gli abbonamenti o i messaggi pubblicati in arrivo dal broker. Per creare una nuova sessione persistente per ogni esecuzione, la demo si connette al broker con il flag impostato, quindi si disconnette e si riconnette con il clean session flag unset. Una volta terminato, il ciclo di elaborazione si disconnette dal broker e riparte dal punto in cui aveva effettuato la riconnessione di rete.

Un completamento con successo della demo genererà un output simile all'immagine seguente.

Una volta completata con successo la connessione MQTT, condivide l'output del terminale dimostrativo
Ciclo di comando

Il ciclo di comandi prvCommandLoop, attende che i comandi vengano inseriti nella coda dei comandi, quindi chiama l'API MQTT appropriata. Anche tutti i comandi tranne DISCONNECT e TERMINATE risultano MQTT_ProcessLoop richiamati. Questa demo imposta un callback di riattivazione del socket per aggiungere un PROCESSLOOP comando alla coda quando i dati sono disponibili sul socket. Tuttavia, a quel punto potrebbero esserci molti comandi in coda. Per assicurarci di non trascurare i dati in arrivo mentre vengono elaborati altri comandi, MQTT_ProcessLoop viene richiesta una singola iterazione dopo ogni comando.

Comandi di elaborazione

Vedi la prvProcessCommandfunzione.

Attività sincrona di pubblicazione

L'attività sincrona di pubblicazione, prvSyncPublishTask, crea PUBLISH le operazioni in modo sincrono e attende il completamento di ciascuna operazione prima di pianificare quella successiva. Questa demo utilizza QoS 1 per pubblicare messaggi, il che significa che queste operazioni non vengono considerate completate fino alla ricezione del pacchetto di conferma della pubblicazione.

Attività di pubblicazione asincrona

L'attività di pubblicazione asincrona, prvAsyncPublishTask, non attende il completamento di una pubblicazione prima di inserire quella successiva nella coda. Ciò dimostra che non è sempre necessario che un'attività attenda il completamento di un'operazione MQTT prima di poter essere ripresa. Poiché ogni comando di pubblicazione richiede una propria struttura di contesto, questa attività non può riutilizzare una singola struttura di contesto come fa l'attività sincrona di Publisher, poiché un comando precedente potrebbe ancora averne bisogno. Pertanto, alloca memoria per ogni struttura di contesto e quindi attende di liberare tutta la memoria allocata dopo che tutti i messaggi da pubblicare sono stati inseriti nella coda.

Attività per abbonati

L'attività di sottoscrizione prvSubscribeTask, sottoscrive un filtro per argomenti che corrisponde a tutti gli argomenti dei messaggi pubblicati dalle attività sincrone e asincrone. Attende quindi di ricevere nuovamente tutti i messaggi pubblicati prima di annullare l'iscrizione. Questa attività è anche responsabile della creazione dell'TERMINATEoperazione che segnala all'attività principale di terminare il ciclo di comandi.