Dela via


Handledning - Använd MQTT för att utveckla en klient för IoT-enheter utan att använda en enhetens SDK

Du bör använda en av Azure IoT Device SDK:erna för att bygga dina IoT-enhetsklienter, om det alls är möjligt. Men i scenarier där du använder en enhet med begränsat minne kan du behöva använda ett MQTT-bibliotek för att kommunicera med din IoT-hubb.

De exempel som finns i denna handledning använder Eclipse Mosquitto-biblioteket för MQTT.

I den här tutorialen lär du dig följande:

  • 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 moln-till-enhet meddelande skickat 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 kan du skapa ett kostnadsfritt konto innan du börjar.

Förutsättningar

Utvecklingsmaskinens förutsättningar

  1. Installera Visual Studio (Community, Professional eller Enterprise). Se till att aktivera arbetsbelastningen Desktoputveckling med C++.

  2. Installera CMake. Aktivera Lägg till CMake i systemets PATH för alla användare alternativet.

  3. Installera x64-versionen av Mosquitto.

Förbereda din miljö för Azure CLI

Konfigurera din miljö

Om du inte redan har ett IoT-hubb, kör följande kommandon för att skapa ett IoT-hubb i gratisnivå i en resursgrupp kallad mqtt-sample-rg. Kommandot använder namnet my-hub som ett exempel på namnet på den IoT-hubb som ska skapas. Välj ett unikt namn för din IoT-hubb som ska användas istället för 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 

Gör en anteckning om namnet på din IoT-hubb, du behöver det senare.

Registrera en enhet i din IoT-hubb. Kommandot nedan registrerar en enhet kallad mqtt-dev-01 i en IoT-hub kallad 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 ger ut eftersom du behöver den senare. SAS-tokenet ser ut som SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Tips/Råd

Som standard är SAS-token giltig i 60 minuter. Alternativet --du 7200 i det föregående kommandot förlänger tokentiden till två timmar. Om det går ut innan du är redo att använda det, generera ett nytt. Du kan också skapa en token med en längre varaktighet. För att lära dig mer, se az iot hub generate-sas-token.

Viktigt!

Den här artikeln innehåller steg för att ansluta en enhet med en signatur för delad åtkomst, även kallad symmetrisk nyckelautentisering. Den här autentiseringsmetoden är praktisk för testning och utvärdering, men att autentisera en enhet med X.509-certifikat är en säkrare metod. Mer information finns i Metodtips för säkerhet för IoT-lösningar > Anslutningssäkerhet.

Klona exempellagringsplatsen

Använd följande kommando för att klona exempelförrådet till en lämplig plats på din lokala maskin.

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

Arkivet innehåller också:

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

Bygg C-exemplen

Innan du bygger exemplet måste du lägga till IoT-hubbens och enhetens detaljer. I det klonade IoTMQTTSample-förrådet öppnar du filen mosquitto/src/config.h. Lägg till ditt IoT-hubnamn, enhets-ID och SAS-token enligt följande. 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"

Anmärkning

Filen IoTHubRootCA.crt.pem innehåller CA-rotcertifikat för TLS-anslutningen.

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

För att bygga exemplen, kör följande kommandon i ditt skal:

cd mosquitto
cmake -Bbuild
cmake --build build

På Linux ligger binärfilerna i ./build-mappen under mosquitto-mappen.

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

Skicka telemetri

Exemplet mosquitto_telemetry visar hur man skickar ett enhets-till-moln-telemetrimeddelande till din IoT-hubb med hjälp av MQTT-biblioteket.

Innan du kör exempeltillämpningen, kör följande kommando för att starta händelseövervakning 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-exemplet. Till exempel, på Linux:

./build/mosquitto_telemetry

az iot hub monitor-events genererar följande output som visar den data 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"
    }
}

Du kan nu stoppa händelsemonitorn.

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 SAS-token som du skapade för din enhet.

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 exemplet mosquitto_subscribe. Till exempel, på 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 kodsnuttar är tagna 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 flernivå-jokertecken

#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 kodexempel visar återropsfunktionen:

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

För att lära dig mer, se Använd MQTT för att ta emot meddelanden från moln-till-enhet.

Uppdatera en enhetstvilling

Exemplet mosquitto_device_twin visar hur man ställer in en rapporterad egenskap i en enhetskopia och sedan läser tillbaka egenskapen.

Kör exemplet mosquitto_device_twin. Till exempel, på 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 kodstycken är tagna från filen mosquitto/src/mosquitto_device_twin.cpp.

Följande meningar definierar ämnena som enheten använder för att prenumerera på uppdateringar av enhetsdubblering, läsa enhetsdubbleringen och uppdatera enhetsdubbleringen.

#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 funktionen mosquitto_connect_callback_set för att sätta en återanrop som hanterar meddelanden skickade från din IoT-hubb och använder funktionen mosquitto_subscribe för att prenumerera på ämnet $iothub/twin/res/#.

Följande kodsnutt visar connect_callback-funktionen som använder mosquitto_publish för att ställa in 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 får enheten ett svar från IoT-hubben på den rapporterade egenskapsuppdateringen. Enheten begär sedan enhetens digitala tvilling. Den andra gången tar enheten emot den begärda enhetens tvilling. Följande kodsnutt visar funktionen 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
    }
}

För att lära dig mer, se Använd MQTT för att uppdatera enhetstvillingens rapporterade egenskap och Använd MQTT för att hämta enhetstvillingens egenskap.

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 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 detta kommando om dessa resurser delar en resursgrupp med andra resurser som du vill behålla.

az group delete --name <YourResourceGroupName>

För att bara radera IoT-hubb, kör följande kommando med Azure CLI:

az iot hub delete --name <YourIoTHubName>

För att ta bort endast den enhetsidentitet du registrerade med din IoT-hubb, kör följande kommando med 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 din utvecklingsdator.

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, föreslås det nästa steget att gå igenom MQTT Applikations exempel på GitHub.