Självstudie – Använda MQTT för att utveckla en IoT-enhetsklient utan att använda en enhets-SDK

Du bör använda en av SDK:erna för Azure IoT-enheter för att skapa dina IoT-enhetsklienter om det är möjligt. I scenarier som att använda en minnesbegränsad enhet kan du dock behöva använda ett MQTT-bibliotek för att kommunicera med din IoT-hubb.

Exemplen i den här självstudien använder Eclipse Mosquitto MQTT-biblioteket.

I den här självstudien lär du dig att:

  • Skapa C-språkenhetens klientexempelprogram.
  • Kör ett exempel som använder MQTT-biblioteket för att skicka telemetri.
  • Kör ett exempel som använder MQTT-biblioteket för att bearbeta ett meddelande från molnet till enheten som skickas från din IoT-hubb.
  • Kör ett exempel som använder MQTT-biblioteket för att hantera enhetstvillingen på enheten.

Du kan använda antingen en Windows- eller Linux-utvecklingsdator för att slutföra stegen i den här självstudien.

Om du inte har någon Azure-prenumeration skapar du ett kostnadsfritt konto innan du börjar.

Förutsättningar

Förbereda din miljö för Azure CLI

Förutsättningar för utvecklingsdator

Om du använder Windows:

  1. Installera Visual Studio (Community, Professional eller Enterprise). Se till att aktivera skrivbordsutveckling med C++ -arbetsbelastning.

  2. Installera CMake. Aktivera alternativet Lägg till CMake i systemsökvägen för alla användare.

  3. Installera x64-versionen av Mosquitto.

Om du använder Linux:

  1. Kör följande kommando för att installera byggverktygen:

    sudo apt install cmake g++
    
  2. Kör följande kommando för att installera Mosquitto-klientbiblioteket:

    sudo apt install libmosquitto-dev
    

Konfigurera din miljö

Om du inte redan har en IoT-hubb kör du följande kommandon för att skapa en IoT-hubb på den kostnadsfria nivån i en resursgrupp med namnet mqtt-sample-rg. Kommandot använder namnet my-hub som ett exempel för namnet på IoT-hubben för att skapa. Välj ett unikt namn för din IoT-hubb som ska användas i stället my-hubför :

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

Anteckna namnet på din IoT-hubb. Du behöver den senare.

Registrera en enhet i din IoT-hubb. Följande kommando registrerar en enhet som heter mqtt-dev-01 i en IoT-hubb med namnet my-hub. Se till att använda namnet på din IoT-hubb:

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

Använd följande kommando för att skapa en SAS-token som ger enheten åtkomst till din IoT-hubb. Se till att använda namnet på din IoT-hubb:

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

Anteckna SAS-token som kommandot utdata när du behöver det senare. SAS-token ser ut som SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Dricks

Som standard är SAS-token giltig i 60 minuter. Alternativet --du 7200 i föregående kommando förlänger tokenvaraktigheten till två timmar. Om den upphör att gälla innan du är redo att använda den genererar du en ny. Du kan också skapa en token med en längre varaktighet. Mer information finns i az iot hub generate-sas-token.

Klona exempellagringsplatsen

Använd följande kommando för att klona exempellagringsplatsen till en lämplig plats på den lokala datorn:

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

Lagringsplatsen innehåller även:

  • Ett Python-exempel som använder paho-mqtt biblioteket.
  • Instruktioner för hur du använder mosquitto_pub CLI för att interagera med din IoT-hubb.

Skapa C-exemplen

Innan du skapar exemplet måste du lägga till IoT-hubben och enhetsinformationen. Öppna filen mosquitto/src/config.h i den klonade IoTMQTTSample-lagringsplatsen. Lägg till ditt IoT Hub-namn, enhets-ID och SAS-token på följande sätt. Se till att använda namnet på din IoT-hubb:

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

Kommentar

IoTHubRootCA.crt.pem-filen innehåller CA-rotcertifikaten för TLS-anslutningen.

Spara ändringarna i filen mosquitto/src/config.h .

Skapa exemplen genom att köra följande kommandon i gränssnittet:

cd mosquitto
cmake -Bbuild
cmake --build build

I Linux finns binärfilerna i mappen ./build under mappen mosquitto .

I Windows finns binärfilerna i mappen .\build\Debug under mappen mosquitto .

Skicka telemetri

Det mosquitto_telemetry exemplet visar hur du skickar ett telemetrimeddelande från enhet till moln till din IoT-hubb med hjälp av MQTT-biblioteket.

Innan du kör exempelprogrammet kör du följande kommando för att starta händelseövervakaren för din IoT-hubb. Se till att använda namnet på din IoT-hubb:

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

Kör mosquitto_telemetry exempel. Till exempel i Linux:

./build/mosquitto_telemetry

az iot hub monitor-events Genererar följande utdata som visar nyttolasten som skickas av enheten:

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

Nu kan du stoppa händelseövervakaren.

Granska koden

Följande kodfragment hämtas från filen mosquitto/src/mosquitto_telemetry.cpp .

Följande instruktioner definierar anslutningsinformationen och namnet på det MQTT-ämne som du använder för att skicka telemetrimeddelandet:

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

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

Funktionen main anger användarnamnet och lösenordet för att autentisera med din IoT-hubb. Lösenordet är den SAS-token som du skapade för enheten:

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

Exemplet använder MQTT-ämnet för att skicka ett telemetrimeddelande till din IoT-hubb:

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

Mer information finns i Skicka meddelanden från enhet till moln.

Ta emot ett meddelande från moln till enhet

Det mosquitto_subscribe exemplet visar hur du prenumererar på MQTT-ämnen och tar emot ett meddelande från molnet till enheten från din IoT-hubb med hjälp av MQTT-biblioteket.

Kör mosquitto_subscribe exempel. Till exempel i Linux:

./build/mosquitto_subscribe

Kör följande kommando för att skicka ett meddelande från molnet till enheten från din IoT-hubb. Se till att använda namnet på din IoT-hubb:

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

Utdata från mosquitto_subscribe ser ut som i följande exempel:

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

Granska koden

Följande kodfragment hämtas från filen mosquitto/src/mosquitto_subscribe.cpp .

Följande instruktion definierar det ämnesfilter som enheten använder för att ta emot meddelanden från molnet till enheten. # är ett jokertecken på flera nivåer:

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

Funktionen main använder mosquitto_message_callback_set funktionen för att ställa in ett återanrop för att hantera meddelanden som skickas från din IoT-hubb och använder mosquitto_subscribe funktionen för att prenumerera på alla meddelanden. Följande kodfragment visar återanropsfunktionen:

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

Mer information finns i Använda MQTT för att ta emot meddelanden från moln till enhet.

Uppdatera en enhetstvilling

Exemplet mosquitto_device_twin visar hur du anger en rapporterad egenskap i en enhetstvilling och läser sedan tillbaka egenskapen.

Kör mosquitto_device_twin exempel. Till exempel i Linux:

./build/mosquitto_device_twin

Utdata från mosquitto_device_twin ser ut som i följande exempel:

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.

Granska koden

Följande kodfragment hämtas från filen mosquitto/src/mosquitto_device_twin.cpp .

Följande instruktioner definierar de ämnen som enheten använder för att prenumerera på enhetstvillinguppdateringar, läsa enhetstvillingen och uppdatera enhetstvillingen:

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

Funktionen main använder mosquitto_connect_callback_set funktionen för att ange ett återanrop för att hantera meddelanden som skickas från din IoT-hubb och använder mosquitto_subscribe funktionen för att prenumerera på ämnet $iothub/twin/res/# .

Följande kodfragment visar funktionen connect_callback som använder mosquitto_publish för att ange en rapporterad egenskap i enhetstvillingen. Enheten publicerar meddelandet till ämnet $iothub/twin/PATCH/properties/reported/?$rid=%d . Värdet %d ökas varje gång enheten publicerar ett meddelande till ämnet:

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

Enheten prenumererar på ämnet $iothub/twin/res/# och när den tar emot ett meddelande från din IoT-hubb message_callback hanterar funktionen det. När du kör exemplet anropas message_callback funktionen två gånger. Första gången tar enheten emot ett svar från IoT-hubben till den rapporterade egenskapsuppdateringen. Enheten begär sedan enhetstvillingen. Den andra gången tar enheten emot den begärda enhetstvillingen. Följande kodfragment visar message_callback funktionen:

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

Mer information finns i Använda MQTT för att uppdatera en enhetstvilling rapporterad egenskap och Använda MQTT för att hämta en enhetstvillingegenskap.

Rensa resurser

Om du planerar att fortsätta med fler artiklar för enhetsutvecklare kan du behålla och återanvända de resurser som du använde i den här artikeln. Annars kan du ta bort de resurser som du skapade i den här artikeln för att undvika fler avgifter.

Du kan ta bort både hubben och den registrerade enheten samtidigt genom att ta bort hela resursgruppen med följande Azure CLI-kommando. Använd inte det här kommandot om dessa resurser delar en resursgrupp med andra resurser som du vill behålla.

az group delete --name <YourResourceGroupName>

Om du bara vill ta bort IoT-hubben kör du följande kommando med Hjälp av Azure CLI:

az iot hub delete --name <YourIoTHubName>

Om du bara vill ta bort enhetsidentiteten som du registrerade med din IoT-hubb kör du följande kommando med Hjälp av Azure CLI:

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

Du kanske också vill ta bort de klonade exempelfilerna från utvecklingsdatorn.

Nästa steg

Nu när du har lärt dig hur du använder Mosquitto MQTT-biblioteket för att kommunicera med IoT Hub är ett föreslaget nästa steg att granska: