Zelfstudie: MQTT gebruiken om een IoT-apparaatclient te ontwikkelen zonder een apparaat-SDK te gebruiken

U moet een van de Azure IoT Device SDK's gebruiken om uw IoT-apparaatclients te bouwen, indien mogelijk. In bepaalde scenario's, zoals wanneer u een apparaat met beperkt geheugen gebruikt, moet u echter mogelijk een MQTT-bibliotheek gebruiken om met uw IoT-hub te communiceren.

De voorbeelden in deze zelfstudie gebruiken de Eclipse Mosquitto MQTT-bibliotheek.

In deze zelfstudie leert u het volgende:

  • Bouw de voorbeeldtoepassingen van de C-taalapparaatclient.
  • Voer een voorbeeld uit dat gebruikmaakt van de MQTT-bibliotheek om telemetrie te verzenden.
  • Voer een voorbeeld uit dat gebruikmaakt van de MQTT-bibliotheek om een cloud-naar-apparaat-bericht te verwerken dat vanuit uw IoT-hub wordt verzonden.
  • Voer een voorbeeld uit dat gebruikmaakt van de MQTT-bibliotheek om de apparaatdubbel op het apparaat te beheren.

U kunt een Windows- of Linux-ontwikkelcomputer gebruiken om de stappen in deze zelfstudie uit te voeren.

Als u geen Azure-abonnement hebt, maakt u een gratis account voordat u begint.

Vereisten

De omgeving voorbereiden op de Azure CLI

Vereisten voor ontwikkelcomputers

Als u Windows gebruikt:

  1. Installeer Visual Studio (Community, Professional of Enterprise). Zorg ervoor dat u de desktopontwikkeling met de C++ -workload inschakelt.

  2. Installeer CMake. Schakel de optie CMake toevoegen aan het systeemPAD in voor alle gebruikers .

  3. Installeer de x64-versie van Mosquitto.

Als u Linux gebruikt:

  1. Voer de volgende opdracht uit om de buildhulpprogramma's te installeren:

    sudo apt install cmake g++
    
  2. Voer de volgende opdracht uit om de Mosquitto-clientbibliotheek te installeren:

    sudo apt install libmosquitto-dev
    

Uw omgeving instellen

Als u nog geen IoT-hub hebt, voert u de volgende opdrachten uit om een gratis IoT-hub te maken in een resourcegroep met de naam mqtt-sample-rg. De opdracht gebruikt de naam my-hub als voorbeeld voor de naam van de IoT-hub die moet worden gemaakt. Kies een unieke naam voor uw IoT-hub die u wilt gebruiken in plaats van my-hub:

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

Noteer de naam van uw IoT-hub. U hebt deze later nodig.

Registreer een apparaat in uw IoT-hub. Met de volgende opdracht wordt een apparaat geregistreerd dat wordt aangeroepen mqtt-dev-01 in een IoT-hub met de naam my-hub. Zorg ervoor dat u de naam van uw IoT-hub gebruikt:

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

Gebruik de volgende opdracht om een SAS-token te maken waarmee het apparaat toegang verleent tot uw IoT-hub. Zorg ervoor dat u de naam van uw IoT-hub gebruikt:

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

Noteer het SAS-token dat de opdracht later nodig heeft. Het SAS-token ziet er als volgt uit SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Tip

Standaard is het SAS-token 60 minuten geldig. De --du 7200 optie in de vorige opdracht breidt de duur van het token uit tot twee uur. Als deze verloopt voordat u klaar bent om deze te gebruiken, genereert u een nieuwe. U kunt ook een token maken met een langere duur. Zie az iot hub generate-sas-token voor meer informatie.

De voorbeeldopslagplaats klonen

Gebruik de volgende opdracht om de voorbeeldopslagplaats te klonen op de gewenste locatie op uw lokale computer:

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

De opslagplaats bevat ook:

  • Een Python-voorbeeld dat gebruikmaakt van de paho-mqtt bibliotheek.
  • Instructies voor het gebruik van de mosquitto_pub CLI om te communiceren met uw IoT-hub.

De C-voorbeelden bouwen

Voordat u het voorbeeld bouwt, moet u de IoT-hub en apparaatdetails toevoegen. Open in de gekloonde IoTMQTTSample-opslagplaats het bestand mosquitto/src/config.h . Voeg als volgt uw IoT Hub-naam, apparaat-id en SAS-token toe. Zorg ervoor dat u de naam van uw IoT-hub gebruikt:

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

Notitie

Het IoTHubRootCA.crt.pem-bestand bevat de CA-basiscertificaten voor de TLS-verbinding.

Sla de wijzigingen op in het bestand mosquitto/src/config.h .

Voer de volgende opdrachten uit in uw shell om de voorbeelden te bouwen:

cd mosquitto
cmake -Bbuild
cmake --build build

In Linux bevinden de binaire bestanden zich in de map ./build onder de map mosquitto .

In Windows bevinden de binaire bestanden zich in de map .\build\Debug onder de map mosquitto .

Telemetrie verzenden

In het mosquitto_telemetry voorbeeld ziet u hoe u een apparaat-naar-cloud-telemetriebericht naar uw IoT-hub verzendt met behulp van de MQTT-bibliotheek.

Voordat u de voorbeeldtoepassing uitvoert, voert u de volgende opdracht uit om de gebeurtenismonitor voor uw IoT-hub te starten. Zorg ervoor dat u de naam van uw IoT-hub gebruikt:

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

Voer het mosquitto_telemetry voorbeeld uit. Bijvoorbeeld in Linux:

./build/mosquitto_telemetry

De az iot hub monitor-events volgende uitvoer genereert de nettolading die door het apparaat wordt verzonden:

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

U kunt nu de gebeurtenismonitor stoppen.

De code bekijken

De volgende fragmenten zijn afkomstig uit het bestand mosquitto/src/mosquitto_telemetry.cpp .

De volgende instructies definiëren de verbindingsgegevens en de naam van het MQTT-onderwerp dat u gebruikt om het telemetriebericht te verzenden:

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

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

De main functie stelt de gebruikersnaam en het wachtwoord in voor verificatie met uw IoT-hub. Het wachtwoord is het SAS-token dat u voor uw apparaat hebt gemaakt:

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

In het voorbeeld wordt het MQTT-onderwerp gebruikt om een telemetriebericht naar uw IoT-hub te verzenden:

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

Zie Apparaat-naar-cloud-berichten verzenden voor meer informatie.

Een cloud-naar-apparaat-bericht ontvangen

In het mosquitto_subscribe voorbeeld ziet u hoe u zich kunt abonneren op MQTT-onderwerpen en hoe u een cloud-naar-apparaat-bericht van uw IoT-hub ontvangt met behulp van de MQTT-bibliotheek.

Voer het mosquitto_subscribe voorbeeld uit. Bijvoorbeeld in Linux:

./build/mosquitto_subscribe

Voer de volgende opdracht uit om een cloud-naar-apparaat-bericht te verzenden vanuit uw IoT-hub. Zorg ervoor dat u de naam van uw IoT-hub gebruikt:

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

De uitvoer van mosquitto_subscribe ziet er als volgt uit:

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

De code bekijken

De volgende codefragmenten zijn afkomstig uit het bestand mosquitto/src/mosquitto_subscribe.cpp .

De volgende instructie definieert het onderwerpfilter dat het apparaat gebruikt om cloud-naar-apparaatberichten te ontvangen. Het # is een jokerteken op meerdere niveaus:

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

De main functie gebruikt de mosquitto_message_callback_set functie om een callback in te stellen voor het afhandelen van berichten die zijn verzonden vanuit uw IoT-hub en gebruikt de mosquitto_subscribe functie om u te abonneren op alle berichten. Het volgende codefragment toont de callback-functie:

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

Zie MQTT gebruiken om cloud-naar-apparaat-berichten te ontvangen voor meer informatie.

Een apparaatdubbel bijwerken

In het mosquitto_device_twin voorbeeld ziet u hoe u een gerapporteerde eigenschap instelt in een apparaatdubbel en de eigenschap vervolgens weer leest.

Voer het mosquitto_device_twin voorbeeld uit. Bijvoorbeeld in Linux:

./build/mosquitto_device_twin

De uitvoer van mosquitto_device_twin ziet er als volgt uit:

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.

De code bekijken

De volgende fragmenten zijn afkomstig uit het bestand mosquitto/src/mosquitto_device_twin.cpp .

In de volgende instructies worden de onderwerpen gedefinieerd die het apparaat gebruikt om u te abonneren op updates van apparaatdubbels, de apparaatdubbel te lezen en de apparaatdubbel bij te werken:

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

De main functie gebruikt de mosquitto_connect_callback_set functie om een callback in te stellen voor het verwerken van berichten die zijn verzonden vanuit uw IoT-hub en gebruikt de mosquitto_subscribe functie om u te abonneren op het $iothub/twin/res/# onderwerp.

In het volgende codefragment ziet u de connect_callback functie die wordt gebruikt mosquitto_publish om een gerapporteerde eigenschap in te stellen in de apparaatdubbel. Het apparaat publiceert het bericht naar het $iothub/twin/PATCH/properties/reported/?$rid=%d onderwerp. De %d waarde wordt verhoogd telkens wanneer het apparaat een bericht naar het onderwerp publiceert:

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

Het apparaat abonneert zich op het $iothub/twin/res/# onderwerp en wanneer het een bericht van uw IoT-hub ontvangt, verwerkt de message_callback functie het. Wanneer u het voorbeeld uitvoert, wordt de message_callback functie tweemaal aangeroepen. De eerste keer ontvangt het apparaat een reactie van de IoT-hub naar de gerapporteerde eigenschapsupdate. Het apparaat vraagt vervolgens de apparaatdubbel aan. De tweede keer ontvangt het apparaat de aangevraagde apparaatdubbel. In het volgende codefragment ziet u de message_callback functie:

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

Zie MQTT gebruiken om een gerapporteerde eigenschap van een apparaatdubbel bij te werken en MQTT gebruiken om een eigenschap van een apparaatdubbel op te halen.

Resources opschonen

Als u van plan bent om door te gaan met meer artikelen over apparaatontwikkelaars, kunt u de resources die u in dit artikel hebt gebruikt, behouden en opnieuw gebruiken. Anders kunt u de resources die u in dit artikel hebt gemaakt, verwijderen om meer kosten te voorkomen.

U kunt zowel de hub als het geregistreerde apparaat tegelijk verwijderen door met de volgende Azure CLI-opdracht de hele resourcegroep te verwijderen. Gebruik deze opdracht niet als deze resources een resourcegroep delen met andere resources die u wilt houden.

az group delete --name <YourResourceGroupName>

Als u alleen de IoT-hub wilt verwijderen, voert u de volgende opdracht uit met behulp van Azure CLI:

az iot hub delete --name <YourIoTHubName>

Als u alleen de apparaat-id wilt verwijderen die u hebt geregistreerd bij de IoT-hub, voert u de volgende opdracht uit met behulp van Azure CLI:

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

Mogelijk wilt u ook de gekloonde voorbeeldbestanden verwijderen van uw ontwikkelcomputer.

Volgende stappen

Nu u hebt geleerd hoe u de Mosquitto MQTT-bibliotheek kunt gebruiken om te communiceren met IoT Hub, is een voorgestelde volgende stap het controleren: