Tutorial: Verwenden von MQTT zum Entwickeln eines IoT-Geräteclients ohne Verwendung eines Geräte-SDK

IoT-Geräteclients sollten nach Möglichkeit immer mithilfe eines der Azure IoT-Geräte-SDKs erstellt werden. In Szenarien, in denen beispielsweise ein Gerät mit eingeschränktem Arbeitsspeicher verwendet wird, muss jedoch für die Kommunikation mit Ihrem IoT-Hub unter Umständen eine MQTT-Bibliothek verwendet werden.

In den Beispielen in diesem Tutorial wird die Eclipse Mosquitto MQTT-Bibliothek verwendet.

In diesem Tutorial lernen Sie Folgendes:

  • Das Erstellen von Geräteclient-Beispielanwendungen in der Sprache C.
  • Das Ausführen eines Beispiels, das die MQTT-Bibliothek zum Senden von Telemetriedaten verwendet.
  • Das Ausführen eines Beispiels, das die MQTT-Bibliothek verwendet, um eine von Ihrem IoT Hub gesendete Cloud-zu-Gerät-Nachricht zu verarbeiten.
  • Das Ausführen eines Beispiels, das die MQTT-Bibliothek verwendet, um den Gerätezwilling auf dem Gerät zu verwalten.

Sie können entweder einen Windows- oder Linux-Entwicklungscomputer verwenden, um die Schritte in diesem Tutorial auszuführen.

Wenn Sie kein Azure-Abonnement besitzen, können Sie ein kostenloses Konto erstellen, bevor Sie beginnen.

Voraussetzungen

Vorbereiten der Umgebung für die Azure CLI

  • Verwenden Sie die Bash-Umgebung in Azure Cloud Shell. Weitere Informationen finden Sie unter Schnellstart für Bash in Azure Cloud Shell.

  • Wenn Sie CLI-Referenzbefehle lieber lokal ausführen, installieren Sie die Azure CLI. Wenn Sie Windows oder macOS ausführen, sollten Sie die Azure CLI in einem Docker-Container ausführen. Weitere Informationen finden Sie unter Ausführen der Azure CLI in einem Docker-Container.

    • Wenn Sie eine lokale Installation verwenden, melden Sie sich mithilfe des Befehls az login bei der Azure CLI an. Führen Sie die in Ihrem Terminal angezeigten Schritte aus, um den Authentifizierungsprozess abzuschließen. Informationen zu anderen Anmeldeoptionen finden Sie unter Anmelden mit der Azure CLI.

    • Installieren Sie die Azure CLI-Erweiterung beim ersten Einsatz, wenn Sie dazu aufgefordert werden. Weitere Informationen zu Erweiterungen finden Sie unter Verwenden von Erweiterungen mit der Azure CLI.

    • Führen Sie az version aus, um die installierte Version und die abhängigen Bibliotheken zu ermitteln. Führen Sie az upgrade aus, um das Upgrade auf die aktuelle Version durchzuführen.

Voraussetzungen für Entwicklungscomputer

Wenn Sie Windows verwenden:

  1. Installieren Sie Visual Studio (Community, Professional oder Enterprise). Stellen Sie sicher, dass die Workload Desktopentwicklung mit C++ verfügbar ist.

  2. Installieren Sie CMake. Aktivieren Sie die Option CMake zum Systempfad für alle Benutzer hinzufügen.

  3. Installieren Sie die x64-Version von Mosquitto.

Wenn Sie Linux verwenden:

  1. Führen Sie den folgenden Befehl aus, um die Buildtools zu installieren:

    sudo apt install cmake g++
    
  2. Führen Sie den folgenden Befehl aus, um die Mosquitto-Clientbibliothek zu installieren:

    sudo apt install libmosquitto-dev
    

Erstellen Ihrer Umgebung

Wenn Sie noch keinen IoT Hub besitzen, führen Sie die folgenden Befehle aus, um einen IoT Hub im Free-Tarif in einer Ressourcengruppe mit dem Namen mqtt-sample-rg zu erstellen. Im Befehl wird der Name my-hub als Beispiel für den Namen des zu erstellenden IoT Hubs verwendet. Wählen Sie einen eindeutigen Namen für Ihren IoT Hub aus, der statt my-hub verwendet werden soll:

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

Notieren Sie sich den Namen Ihres IoT Hubs. Sie werden ihn später benötigen.

Registrieren Sie ein Gerät bei Ihrem IoT Hub. Mit dem folgenden Befehl wird ein Gerät namens mqtt-dev-01bei einem IoT Hub namens my-hub registriert. Verwenden Sie unbedingt den Namen Ihres IoT Hubs:

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

Verwenden Sie den folgenden Befehl, um ein SAS-Token zu erstellen, das dem Gerät Zugriff auf Ihren IoT Hub gewährt. Verwenden Sie unbedingt den Namen Ihres IoT Hubs:

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

Notieren Sie sich das SAS-Token, den der Befehl ausgibt, da Sie ihn später benötigen. Das SAS-Token sieht so aus: SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Tipp

Standardmäßig ist das SAS-Token 60 Minuten lang gültig. Die Option --du 7200 im vorherigen Befehl erweitert die Gültigkeitsdauer des Token auf zwei Stunden. Wenn das Token abläuft, bevor Sie es verwenden können, generieren Sie ein neues. Sie können auch ein Token mit einer längeren Gültigkeitsdauer erstellen. Weitere Informationen finden Sie unter az iot hub generate-sas-token.

Klonen des Beispielrepositorys

Verwenden Sie den folgenden Befehl, um das Beispielrepository an einem geeigneten Ort auf Ihrem lokalen Computer zu klonen:

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

Das Repository umfasst außerdem Folgendes:

  • Ein Python-Beispiel, das die paho-mqtt-Bibliothek verwendet.
  • Anweisungen für die Verwendung der mosquitto_pub-CLI für die Interaktion mit Ihrem IoT Hub.

Erstellen der C-Beispiele

Bevor Sie das Beispiel erstellen, müssen Sie die IoT Hub- und Gerätedetails hinzufügen. Öffnen Sie im geklonten IoTMQTTSample-Repository die Datei mosquitto/src/config.h. Fügen Sie den Namen Ihres IoT Hubs, die Geräte-ID und Ihr SAS-Token wie folgt hinzu. Verwenden Sie unbedingt den Namen Ihres IoT Hubs:

// 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"

Hinweis

Die Datei IoTHubRootCA.crt.pem enthält die Zertifizierungsstellen-Stammzertifikate für die TLS-Verbindung.

Speichern Sie die Änderungen in der Datei mosquitto/src/config.h.

Führen Sie zum Erstellen der Beispiele die folgenden Befehle in Ihrer Shell aus:

cd mosquitto
cmake -Bbuild
cmake --build build

Unter Linux befinden sich die Binärdateien im Ordner ./build unter dem Ordner mosquitto.

Unter Windows befinden sich die Binärdateien im Ordner .\build\Debug unterhalb des Ordners mosquitto.

Senden von Telemetriedaten

Das Beispiel mosquitto_telemetry zeigt, wie Sie mithilfe der MQTT-Bibliothek eine Geräte-zu-Cloud-Telemetrienachricht an Ihren IoT Hub senden.

Führen Sie vor dem Ausführen der Beispielanwendung den folgenden Befehl aus, um den Ereignismonitor für Ihren IoT Hub zu starten. Verwenden Sie unbedingt den Namen Ihres IoT Hubs:

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

Führen Sie das Beispiel mosquitto_telemetry aus. Zum Beispiel unter Linux:

./build/mosquitto_telemetry

Generiert az iot hub monitor-events die folgende Ausgabe, die die vom Gerät gesendete Nutzlast anzeigt:

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

Sie können den Ereignismonitor jetzt beenden.

Überprüfen des Codes

Die folgenden Codeausschnitte stammen aus der Datei mosquitto/src/mosquitto_telemetry.cpp.

Die folgenden Anweisungen definieren die Verbindungsinformationen und den Namen des MQTT-Themas, das Sie zum Senden der Telemetrienachricht verwenden:

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

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

Die main-Funktion legt den Benutzernamen und das Kennwort für die Authentifizierung bei Ihrem IoT Hub fest. Das Kennwort ist das SAS-Token, das Sie für Ihr Gerät erstellt haben:

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

Im Beispiel wird das MQTT-Thema verwendet, um eine Telemetrienachricht an Ihren IoT Hub zu senden:

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");

Weitere Informationen finden Sie unter Senden von Geräte-zu-Cloud-Nachrichten.

Empfangen einer Cloud-zu-Gerät-Nachricht

Das Beispiel mosquitto_subscribe zeigt, wie Sie MQTT-Themen abonnieren und eine Cloud-zu-Gerät-Nachricht von Ihrem IoT Hub mithilfe der MQTT-Bibliothek empfangen.

Führen Sie das Beispiel mosquitto_subscribe aus. Zum Beispiel unter Linux:

./build/mosquitto_subscribe

Führen Sie den folgenden Befehl aus, um eine Cloud-zu-Gerät-Nachricht von Ihrem IoT Hub zu senden. Verwenden Sie unbedingt den Namen Ihres IoT Hubs:

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

Die Ausgabe von mosquitto_subscribe sieht wie das folgende Beispiel aus:

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

Überprüfen des Codes

Die folgenden Codeausschnitte stammen aus der Datei mosquitto/src/mosquitto_subscribe.cpp.

Die folgende Anweisung definiert den Themenfilter, den das Gerät zum Empfangen von Cloud-zu-Gerät-Nachrichten verwendet. # ist ein Mehrebenen-Platzhalter:

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

Die main-Funktion verwendet die mosquitto_message_callback_set-Funktion, um einen Rückruf festzulegen, um Nachrichten zu behandeln, die von Ihrem IoT Hub gesendet werden, und verwendet die mosquitto_subscribe-Funktion, um alle Nachrichten zu abonnieren. Der folgende Codeausschnitt zeigt diese Rückruffunktion:

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");
    }
}

Weitere Informationen finden Sie unter Verwenden von MQTT zum Empfangen von Cloud-zu-Gerät-Nachrichten.

Aktualisieren eines Gerätezwillings

Im Beispiel mosquitto_device_twin wird gezeigt, wie eine gemeldete Eigenschaft in einem Gerätezwilling festgelegt und dann die Eigenschaft zurückgelesen wird.

Führen Sie das Beispiel mosquitto_device_twin aus. Zum Beispiel unter Linux:

./build/mosquitto_device_twin

Die Ausgabe von mosquitto_device_twin sieht wie das folgende Beispiel aus:

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.

Überprüfen des Codes

Die folgenden Codeausschnitte stammen aus der Datei mosquitto/src/mosquitto_device_twin.cpp.

Die folgenden Anweisungen definieren die Themen, die das Gerät zum Abonnieren von Gerätezwillingsupdates, zum Lesen des Gerätezwillingen und zum Aktualisieren des Gerätezwillings verwendet:

#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"

Die main-Funktion verwendet die mosquitto_connect_callback_set-Funktion, um einen Rückruf zum Behandeln von Nachrichten festzulegen, die von Ihrem IoT Hub gesendet werden, und verwendet die mosquitto_subscribe-Funktion, um das Thema $iothub/twin/res/# zu abonnieren.

Der folgende Codeausschnitt zeigt die connect_callback-Funktion, die mosquitto_publish verwendet, um eine gemeldete Eigenschaft im Gerätezwilling festzulegen. Das Gerät veröffentlicht die Nachricht im Thema $iothub/twin/PATCH/properties/reported/?$rid=%d. Der %d-Wert wird jedes Mal erhöht, wenn das Gerät eine Nachricht für das Thema veröffentlicht:

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 ...  
}

Das Gerät abonniert das Thema $iothub/twin/res/# und wenn es eine Nachricht von Ihrem IoT Hub empfängt, wird diese von der message_callback-Funktion verarbeitet. Wenn Sie das Beispiel ausführen, wird die message_callback-Funktion zweimal aufgerufen. Beim ersten Mal empfängt das Gerät eine Antwort vom IoT Hub für die Aktualisierung der gemeldeten Eigenschaft. Das Gerät fordert dann den Gerätezwilling an. Beim zweiten Mal empfängt das Gerät den angeforderten Gerätezwilling. Der im Anschluss bereitgestellte Codeausschnitt zeigt die message_callback-Funktion:

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
    }
}

Weitere Informationen finden Sie unter Verwenden von MQTT zum Aktualisieren einer gemeldeten Eigenschaft eines Gerätezwillings und Verwenden von MQTT zum Abrufen einer Gerätezwillingseigenschaft.

Bereinigen von Ressourcen

Wenn Sie den Vorgang mit weiteren Artikeln zu Geräteentwicklern fortsetzen möchten, können Sie die in diesem Artikel verwendeten Ressourcen beibehalten und wiederverwenden. Andernfalls können Sie die in diesem Artikel erstellten Ressourcen löschen, um weitere Gebühren zu vermeiden.

Sie können den Hub und das registrierte Gerät gleichzeitig löschen, indem Sie die gesamte Ressourcengruppe mit dem folgenden Azure CLI-Befehl löschen. Verwenden Sie diesen Befehl nicht, wenn für diese Ressourcen eine Ressourcengruppe genutzt wird, in der auch andere Ressourcen enthalten sind, die Sie beibehalten möchten.

az group delete --name <YourResourceGroupName>

Um nur den IoT-Hub zu löschen, führen Sie den folgenden Befehl über die Azure-Befehlszeilenschnittstelle aus:

az iot hub delete --name <YourIoTHubName>

Führen Sie mit der Azure-Befehlszeilenschnittstelle die folgenden Befehle aus, um nur die bei Ihrem IoT-Hub registrierte Geräte-ID zu löschen:

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

Möglicherweise sollten Sie auch die geklonten Beispieldateien von Ihrem Entwicklungscomputer entfernen.

Nächste Schritte

Nachdem Sie nun erfahren haben, wie Sie die Mosquitto MQTT-Bibliothek für die Kommunikation mit IoT Hub verwenden, sollten Sie als nächstes folgendes überprüfen: