Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Démo de partage de connexion CoreMQTT
Important
Il s'agit d'une version archivée du guide de l'utilisateur de FreeRTOS à utiliser avec la version 202012.00 de FreeRTOS. Pour obtenir la dernière version de ce document, consultez le guide de l'utilisateur de FreeRTOS.
Introduction
Le projet de démonstration du partage de connexion CoreMQTT vous montre comment utiliser une application multithread pour établir une connexion au broker AWS MQTT à l'aide du protocole TLS avec authentification mutuelle entre le client et le serveur. Cette démonstration utilise une implémentation d'interface de transport basée sur MBEDTLS pour établir une connexion TLS authentifiée par le serveur et le client, et illustre le flux de travail d'abonnement/publication de MQTT au niveau QoS 1.
Note
Pour configurer et exécuter les démos de FreeRTOS, suivez les étapes décrites dans. Débuter avec FreeRTOS
Cette démonstration utilise une file d'attente sécurisée par thread pour contenir les commandes permettant d'interagir avec l'API MQTT. Il y a quatre tâches à prendre en compte dans cette démonstration.
-
Une tâche de commande (principale) prend des commandes de la file de commandes et les traite. Les autres tâches placent les commandes dans cette file d'attente pour être traitées. Cette tâche entre dans une boucle au cours de laquelle elle traite les commandes. Si une commande de fin est reçue, cette tâche sera interrompue.
-
Une tâche d'éditeur synchrone crée une série d'opérations de publication et les envoie vers la file de commandes. Ces opérations sont ensuite exécutées par la tâche de commande. Cette tâche utilise la publication synchrone, ce qui signifie qu'elle attendra la fin de chaque opération de publication avant de planifier la suivante.
-
Une tâche d'éditeur asynchrone crée une série d'opérations de publication et les envoie vers la file de commandes. Ces opérations sont ensuite exécutées par la tâche de commande. La différence entre cette tâche et la précédente est qu'elle n'attendra pas la fin d'une opération de publication pour planifier la suivante. Il vérifie le statut de chaque opération de publication une fois que toutes ses opérations de publication ont été ajoutées à la file d'attente. Notez que la distinction entre publication synchrone et publication asynchrone réside uniquement dans le comportement de ces tâches. Il n'y a aucune différence entre les commandes de publication réelles.
-
Une tâche d'abonné crée un abonnement MQTT à un filtre de sujet qui correspond aux sujets de tous les messages publiés par les deux tâches d'éditeur. Cette tâche entre dans une boucle et attend de recevoir les messages publiés par les autres tâches.
Les tâches peuvent comporter des files d'attente pour contenir les messages reçus. La tâche de commande redirige les messages entrants vers la file d'attente de toute tâche abonnée au sujet entrant.
Cette démonstration utilise une connexion TLS avec authentification mutuelle pour se connecter AWS. Si le réseau se déconnecte de façon inattendue pendant la démonstration, le client tente de se reconnecter en utilisant une logique d'interruption exponentielle. Si le client se reconnecte avec succès, mais que le courtier ne parvient pas à reprendre la session précédente, le client se réabonnera aux mêmes sujets que lors de la session précédente.
Monothread ou multithread
Il existe deux modèles d'utilisation de CoreMQTT, monothread et multithread (multitâche). Cette démo vous montre comment créer votre propre schéma de multithreading. Il existe également un autre exemple multithread qui exécute le protocole MQTT en arrière-plan dans une tâche d'agent (ou de démon). Pour plus d'informations, consultez Agent MWTT et démos utilisantMQTT_ProcessLoop
fonction. En outre, si vous utilisez une tâche d'agent, plusieurs tâches d'application peuvent partager une même connexion MQTT sans avoir besoin de primitives de synchronisation, telles que des mutex.
Code source
Le fichier source de démonstration est nommé mqtt_demo_connection_sharing.c
et se trouve dans le
répertoire et GitHubfreertos
/demos/coreMQTT/
Fonctionnalité
Cette démonstration crée quatre tâches au total : trois qui demandent des appels d'API MQTT et une qui traite ces demandes, qui est la tâche principale. Dans cette démonstration, la tâche principale entre dans une boucle qui crée les trois sous-tâches, appelle la boucle de traitement et nettoie ensuite. La tâche principale crée une connexion MQTT unique avec le broker, qui est partagée entre les sous-tâches. Deux des sous-tâches publient des messages destinés au courtier, et la troisième reçoit les messages en retour, en utilisant un abonnement MQTT à un filtre de sujets qui correspond à tous les sujets des messages publiés.
Définitions typographiques
La démo définit les structures, les énumérations et les pointeurs de fonction suivants.
- Commandes
-
Plutôt que d'effectuer des appels d'API MQTT directement, les tâches utilisent
Command_t
des structures pour créer des commandes qui demandent à la tâche principale d'appeler l'opération d'API appropriée pour elles. Les types de commandes sont les suivants :-
PROCESSLOOP
-
PUBLISH
-
SUBSCRIBE
-
UNSUBSCRIBE
-
PING
-
DISCONNECT
-
RECONNECT
-
TERMINATE
La
TERMINATE
commande n'a pas d'opération d'API MQTT correspondante. Il est utilisé dans la démo pour demander à la tâche principale d'arrêter le traitement des commandes et de commencer les opérations de nettoyage. Parce que certaines informations supplémentaires, par exemple des informations de publication ou d'abonnement, sont requises pour certaines commandes MQTT telles queMQTT_Publish
MQTT_Subscribe
, etMQTT_Unsubscribe
, nous utilisons leCommandContext_t
champ. Ce champ est obligatoire pour ces trois commandes, mais il est facultatif pour les autres.Ce contexte étant requis pour ces commandes, ne modifiez pas cette valeur une fois que la commande a été placée dans la file d'attente, tant qu'elle n'est pas terminée. Lorsqu'une commande est terminée, un rappel facultatif peut être invoqué. Dans cette démo, nous utilisons un rappel qui crée une notification de tâche pour informer la tâche appelante que la commande est terminée. Pour les opérations MQTT qui nécessitent des accusés de réception (abonnement, désabonnement et publication avec une QoS supérieure à 0), la commande est considérée comme terminée une fois que l'accusé de réception a été reçu. Dans le cas contraire, la commande est terminée une fois que l'appel d'API MQTT correspondant est renvoyé.
Les définitions suivantes se trouvent dans le
mqtt_demo_connection_sharing.c
fichier : -
- Remerciements
-
Comme certaines opérations MQTT nécessitent un accusé de réception, elles utilisent un tableau de AckInfo_t
qui contient l'identifiant de paquet de l'accusé de réception attendu et la commande d'origine qui l'attend, afin que son rappel de fin puisse être invoqué. - Abonnements
-
Cette démo permet de suivre les abonnements pour chaque tâche. Pour ce faire, chaque tâche demandant un abonnement doit fournir une file de messages dans laquelle elle recevra en retour les messages publiés (SubscriptionElement_t).
Plusieurs tâches peuvent s'abonner au même filtre de rubrique, car elles sont censées utiliser des files de réponses distinctes. - Messages publiés reçus
-
Comme les tâches s'exécutent en parallèle avec la tâche principale, il serait difficile et fastidieux pour celle-ci d'attendre que chaque tâche abonnée lise un message publié reçu. Par conséquent, chaque message reçu est copié dans la file de réponses de toute tâche abonnée au sujet du message publié (PublishElement_t).
Étant donné que les paquets de publication reçus du client MQTT contiennent des pointeurs vers la mémoire tampon réseau du client, la charge utile et le nom du sujet du message entrant sont copiés dans des tampons distincts avant d'être insérés dans une file de réponses. Ainsi, la tâche abonnée peut toujours lire les informations reçues une fois que le client MQTT a vidé sa mémoire tampon réseau.
Tâche principale
La tâche principale de l'application établit une session MQTT persistante, crée trois sous-tâches et exécute la boucle de traitement jusqu'à ce qu'une commande de fin soit reçue. RunCoreMQTTConnectionSharingDemoclean session
drapeau activé, puis se déconnecte et se reconnecte avec le drapeau non activé. Une fois la boucle de traitement terminée, elle se déconnecte du broker, puis recommence à fonctionner à partir du point où elle a effectué la reconnexion au réseau.
Si la démonstration est terminée avec succès, un résultat similaire à l'image suivante sera généré.

- Boucle de commande
-
La boucle de commande attend que les commandes soient placées dans la file d'attente de commandes, puis appelle l'API MQTT appropriée. prvCommandLoop
Toutes les commandes, à DISCONNECT
l'TERMINATE
exception de et,MQTT_ProcessLoop
sont également appelées. Cette démo définit un rappel de réveil du socket pour ajouter unePROCESSLOOP
commande à la file d'attente lorsque des données sont disponibles sur le socket. Cependant, il se peut qu'il y ait de nombreuses commandes devant lui dans la file d'attente à ce stade. Pour s'assurer que nous ne négligeons pas les données entrantes lorsque d'autres commandes sont traitées, une seule itérationMQTT_ProcessLoop
est requise après chaque commande. - Commandes de traitement
-
Voir la prvProcessCommand
fonction.
Tâche d'éditeur synchrone
La tâche d'éditeur synchrone, prvSyncPublishTaskPUBLISH
des opérations de manière synchrone et attend que chaque opération soit terminée avant de planifier la suivante. Cette démonstration utilise QoS 1 pour publier des messages, ce qui signifie que ces opérations ne sont pas considérées comme terminées tant que le paquet d'accusé de réception de publication n'a pas été reçu.
Tâche d'éditeur asynchrone
La tâche d'éditeur asynchrone, prvAsyncPublishTask
Tâche d'abonné
La tâche d'abonné s'abonne à un filtre de sujets qui correspond à tous les sujets des messages publiés à partir des tâches synchrones et asynchrones. prvSubscribeTaskTERMINATE
opération qui indique à la tâche principale de mettre fin à la boucle de commande.