Didacticiel : utiliser MQTT pour développer un client d’appareil IoT sans utiliser de SDK d’appareils

Dans la mesure du possible, vous devez utiliser l’un des SDK d’appareils Azure IoT pour créer des clients d’appareil IoT. Toutefois, dans certains scénarios, par exemple quand la mémoire de l’appareil utilisé est restreinte, vous devrez peut-être utiliser une bibliothèque MQTT pour communiquer avec votre hub IoT.

Les exemples de ce didacticiel utilisent la bibliothèque MQTT Eclipse Mosquitto.

Dans ce tutoriel, vous allez apprendre à :

  • Générez les exemples d’applications de clients d’appareils en langage C.
  • Exécutez un exemple qui utilise la bibliothèque MQTT pour envoyer des données de télémétrie.
  • Exécutez un exemple qui utilise la bibliothèque MQTT pour traiter un message cloud-à-appareil envoyé à partir de votre hub IoT.
  • Exécutez un exemple qui utilise la bibliothèque MQTT pour gérer le jumeau d’appareil sur l’appareil.

Vous pouvez utiliser un ordinateur de développement Windows ou Linux pour suivre les étapes de ce didacticiel.

Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.

Prérequis

Préparation de votre environnement pour Azure CLI

Prérequis de l’ordinateur de développement

Si vous utilisez Windows :

  1. Installez Visual Studio (Community, Professional ou Enterprise). Assurez-vous d’activer la charge de travail Développement de bureau C++.

  2. Installez CMake. Activez l’option Ajouter CMake au chemin d’accès système pour tous les utilisateurs.

  3. Installez la version x64 de Mosquitto.

Si vous utilisez Linux :

  1. Exécutez la commande suivante pour installer les outils de génération :

    sudo apt install cmake g++
    
  2. Exécutez la commande suivante pour installer la bibliothèque cliente Mosquitto :

    sudo apt install libmosquitto-dev
    

Configurer votre environnement

Si vous n’avez pas encore de hub IoT, exécutez les commandes suivantes pour créer un hub IoT de niveau gratuit dans un groupe de ressources appelé mqtt-sample-rg. La commande utilise le nom my-hub comme exemple de nom du hub IoT à créer. Remplacez my-hub par un nom unique de votre choix pour votre hub IoT :

az group create --name mqtt-sample-rg --location eastus
az iot hub create --name my-hub --resource-group mqtt-sample-rg --sku F1 

Notez le nom de votre hub IoT. Vous en aurez besoin ultérieurement.

Inscrivez votre appareil dans votre hub IoT. La commande suivante inscrit un appareil appelé mqtt-dev-01 dans un hub IoT appelé my-hub. Veillez à utiliser le nom de votre hub IoT :

az iot hub device-identity create --hub-name my-hub --device-id mqtt-dev-01

Utilisez la commande suivante pour créer un jeton SAP qui accorde à l’appareil l’accès à votre hub IoT. Veillez à utiliser le nom de votre hub IoT :

az iot hub generate-sas-token --device-id mqtt-dev-01 --hub-name my-hub --du 7200

Notez le jeton SAP que la commande génère, vous en aurez besoin plus tard. Le jeton SAP ressemble à SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Conseil

Par défaut, le jeton SAP est valide pendant 60 minutes. L’option --du 7200 de la commande précédente étend la durée du jeton à deux heures. S’il expire avant que vous ne soyez prêt à l’utiliser, générez-en un nouveau. Vous pouvez également créer un jeton d’une durée plus longue. Pour plus d’informations, consultez az iot hub generate-sas-token.

Clonez l’exemple de dépôt

Utilisez la commande suivante pour cloner l’exemple de dépôt à un emplacement approprié sur votre ordinateur local :

git clone https://github.com/Azure-Samples/IoTMQTTSample.git

Le référentiel comprend également :

  • Exemple Python qui utilise la bibliothèque paho-mqtt.
  • Instructions d’utilisation de l’interface CLI mosquitto_pub pour interagir avec votre hub IoT.

Générer les exemples C

Avant de générer l’exemple, vous devez ajouter les détails du hub IoT et de l’appareil. Dans le référentiel IoTMQTTSample cloné, ouvrez le fichier mosquitto/src/config.h. Ajoutez le nom de votre hub IoT, l’ID d’appareil et le jeton SAP comme suit. Veillez à utiliser le nom de votre hub IoT :

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#define IOTHUBNAME "my-hub"
#define DEVICEID   "mqtt-dev-01"
#define SAS_TOKEN  "SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761"

#define CERTIFICATEFILE CERT_PATH "IoTHubRootCA.crt.pem"

Notes

Le fichier IoTHubRootCA.crt.pem inclut les certificats racine de l’autorité de certification pour la connexion TLS.

Enregistrez les modifications dans le fichier mosquitto/src/config.h.

Pour générer les exemples, exécutez les commandes suivantes dans votre interpréteur de commandes :

cd mosquitto
cmake -Bbuild
cmake --build build

Sur Linux, les fichiers binaires se trouvent dans le dossier ./build sous le dossier mosquitto.

Sur Windows, les fichiers binaires se trouvent dans le dossier .\build\Debug sous le dossier mosquitto.

Envoyer des données de télémétrie

L’exemple mosquitto_telemetry montre comment envoyer un message de télémétrie appareil-à-cloud à votre hub IoT à l’aide de la bibliothèque MQTT.

Avant d’exécuter l’exemple d’application, exécutez la commande suivante pour lancer l’observateur d’événements pour votre hub IoT. Veillez à utiliser le nom de votre hub IoT :

az iot hub monitor-events --hub-name my-hub

Exécutez l’exemple mosquitto_telemetry. Par exemple, sur Linux :

./build/mosquitto_telemetry

Le az iot hub monitor-events génère la sortie suivante qui affiche la charge utile envoyée par l’appareil :

Starting event monitor, use ctrl-c to stop...
{
    "event": {
        "origin": "mqtt-dev-01",
        "module": "",
        "interface": "",
        "component": "",
        "payload": "Bonjour MQTT from Mosquitto"
    }
}

Vous pouvez maintenant arrêter l’observateur d’événements.

Vérifier le code

L’extrait de code suivant provient du fichier mosquitto/src/mosquitto_telemetry.cpp.

Les instructions suivantes définissent les informations de connexion et le nom de la rubrique MQTT que vous utilisez pour envoyer le message de télémétrie :

#define HOST IOTHUBNAME ".azure-devices.net"
#define PORT 8883
#define USERNAME HOST "/" DEVICEID "/?api-version=2020-09-30"

#define TOPIC "devices/" DEVICEID "/messages/events/"

La fonction main définit le nom d’utilisateur et le mot de passe à authentifier auprès de votre hub IoT. Le mot de passe est le jeton SAP que vous avez créé pour votre appareil :

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

L’exemple utilise la rubrique MQTT pour envoyer un message de télémétrie à votre hub IoT :

int msgId  = 42;
char msg[] = "Bonjour MQTT from Mosquitto";

// once connected, we can publish a Telemetry message
printf("Publishing....\r\n");
rc = mosquitto_publish(mosq, &msgId, TOPIC, sizeof(msg) - 1, msg, 1, true);
if (rc != MOSQ_ERR_SUCCESS)
{
    return mosquitto_error(rc);
}
printf("Publish returned OK\r\n");

Pour plus d’informations, consultez Envoi de messages appareil-à-cloud.

Réception d’un message cloud-à-appareil

L’exemple mosquitto_subscribe montre comment s’abonner à des rubriques MQTT et recevoir un message cloud-à-appareil de votre hub IoT à l’aide de la bibliothèque MQTT.

Exécutez l’exemple mosquitto_subscribe. Par exemple, sur Linux :

./build/mosquitto_subscribe

Exécutez la commande suivante pour envoyer un message cloud-à-appareil à partir de votre hub IoT. Veillez à utiliser le nom de votre hub IoT :

az iot device c2d-message send --hub-name my-hub --device-id mqtt-dev-01 --data "hello world"

La sortie de mosquitto_subscribe ressemble à l’exemple suivant :

Waiting for C2D messages...
C2D message 'hello world' for topic 'devices/mqtt-dev-01/messages/devicebound/%24.mid=d411e727-...f98f&%24.to=%2Fdevices%2Fmqtt-dev-01%2Fmessages%2Fdevicebound&%24.ce=utf-8&iothub-ack=none'
Got message for devices/mqtt-dev-01/messages/# topic

Vérifier le code

L’extrait de code suivant provient du fichier mosquitto/src/mosquitto_subscribe.cpp.

L’instruction suivante définit le filtre de rubrique utilisé par l’appareil pour recevoir des messages cloud-à-appareil. Le # est un caractère générique à plusieurs niveaux :

#define DEVICEMESSAGE "devices/" DEVICEID "/messages/#"

La fonction main utilise la fonction mosquitto_message_callback_set pour définir un rappel afin de gérer les messages envoyés à partir de votre hub IoT et utilise la fonction mosquitto_subscribe pour s’abonner à tous les messages. L’extrait de code suivant illustre cette fonction de rappel :

void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message)
{
    printf("C2D message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic);

    bool match = 0;
    mosquitto_topic_matches_sub(DEVICEMESSAGE, message->topic, &match);

    if (match)
    {
        printf("Got message for " DEVICEMESSAGE " topic\r\n");
    }
}

Pour en savoir plus, consultez Utiliser MQTT pour recevoir des messages cloud-à-appareil.

Mettre à jour un jumeau d’appareil

L’exemple mosquitto_device_twin montre comment définir une propriété signalée dans un jumeau d’appareil, puis relire la propriété.

Exécutez l’exemple mosquitto_device_twin. Par exemple, sur Linux :

./build/mosquitto_device_twin

La sortie de mosquitto_device_twin ressemble à l’exemple suivant :

Setting device twin reported properties....
Device twin message '' for topic '$iothub/twin/res/204/?$rid=0&$version=2'
Setting device twin properties SUCCEEDED.

Getting device twin properties....
Device twin message '{"desired":{"$version":1},"reported":{"temperature":32,"$version":2}}' for topic '$iothub/twin/res/200/?$rid=1'
Getting device twin properties SUCCEEDED.

Vérifier le code

L’extrait de code suivant provient du fichier mosquitto/src/mosquitto_device_twin.cpp.

Les instructions suivantes définissent les rubriques que l’appareil utilise pour s’abonner aux mises à jour de jumeau d’appareil, pour lire le jumeau d’appareil et mettre à jour le jumeau d’appareil :

#define DEVICETWIN_SUBSCRIPTION  "$iothub/twin/res/#"
#define DEVICETWIN_MESSAGE_GET   "$iothub/twin/GET/?$rid=%d"
#define DEVICETWIN_MESSAGE_PATCH "$iothub/twin/PATCH/properties/reported/?$rid=%d"

La fonction main utilise la fonction mosquitto_connect_callback_set pour définir un rappel afin de gérer les messages envoyés à partir de votre hub IoT et utilise la fonction mosquitto_subscribe pour s’abonner à la rubrique $iothub/twin/res/#.

L’extrait de code suivant montre la fonction connect_callback qui utilise mosquitto_publish pour définir une propriété signalée dans le jumeau d’appareil. L’appareil publie le message dans la rubrique $iothub/twin/PATCH/properties/reported/?$rid=%d. La valeur %d est incrémentée chaque fois que l’appareil publie un message dans la rubrique :

void connect_callback(struct mosquitto* mosq, void* obj, int result)
{
    // ... other code ...  

    printf("\r\nSetting device twin reported properties....\r\n");

    char msg[] = "{\"temperature\": 32}";
    char mqtt_publish_topic[64];
    snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_PATCH, device_twin_request_id++);

    int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true);
    if (rc != MOSQ_ERR_SUCCESS)

    // ... other code ...  
}

L’appareil s’abonne à la rubrique $iothub/twin/res/# et lorsqu’il reçoit un message de votre hub IoT, la fonction message_callback le gère. Lorsque vous exécutez l’exemple, la fonction message_callback est appelée deux fois. La première fois, l’appareil reçoit une réponse du hub IoT pour la mise à jour de propriété signalée. L’appareil demande ensuite le jumeau d’appareil. La deuxième fois, l’appareil reçoit le jumeau d’appareil demandé. L’extrait de code suivant illustre cette fonction message_callback :

void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message)
{
    printf("Device twin message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic);

    const char patchTwinTopic[] = "$iothub/twin/res/204/?$rid=0";
    const char getTwinTopic[]   = "$iothub/twin/res/200/?$rid=1";

    if (strncmp(message->topic, patchTwinTopic, sizeof(patchTwinTopic) - 1) == 0)
    {
        // Process the reported property response and request the device twin
        printf("Setting device twin properties SUCCEEDED.\r\n\r\n");

        printf("Getting device twin properties....\r\n");

        char msg[] = "{}";
        char mqtt_publish_topic[64];
        snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_GET, device_twin_request_id++);

        int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true);
        if (rc != MOSQ_ERR_SUCCESS)
        {
            printf("Error: %s\r\n", mosquitto_strerror(rc));
        }
    }
    else if (strncmp(message->topic, getTwinTopic, sizeof(getTwinTopic) - 1) == 0)
    {
        // Process the device twin response and stop the client
        printf("Getting device twin properties SUCCEEDED.\r\n\r\n");

        mosquitto_loop_stop(mosq, false);
        mosquitto_disconnect(mosq); // finished, exit program
    }
}

Pour plus d’informations, consultez Utiliser MQTT pour mettre à jour une propriété signalée de jumeau d’appareil et Utiliser MQTT pour récupérer une propriété de jumeau d’appareil.

Nettoyer les ressources

Si vous prévoyez de continuer avec d’autres articles développeurs d’appareils, vous pouvez conserver et réutiliser les ressources que vous avez utilisées dans cet article. Sinon, vous pouvez supprimer les ressources que vous avez créées dans cet article afin d’éviter des frais supplémentaires.

Vous pouvez supprimer simultanément le hub et l’appareil inscrit en supprimant la totalité du groupe de ressources avec la commande Azure CLI suivante. N’utilisez pas cette commande si ces ressources partagent un groupe de ressources avec d’autres ressources que vous souhaitez conserver.

az group delete --name <YourResourceGroupName>

Pour supprimer seulement le hub IoT, exécutez la commande suivante en utilisant Azure CLI :

az iot hub delete --name <YourIoTHubName>

Pour supprimer seulement l’appareil que vous avez inscrit auprès de votre hub IoT, exécutez la commande suivante en utilisant Azure CLI :

az iot hub device-identity delete --hub-name <YourIoTHubName> --device-id <YourDeviceID>

Vous pouvez aussi supprimer les exemples de fichiers clonés de votre ordinateur de développement.

Étapes suivantes

Maintenant que vous avez appris à utiliser la bibliothèque MQTT Mosquitto pour communiquer avec IoT Hub, l’étape suivante recommandée consiste à examiner :