Share via


Esercitazione: Usare MQTT per sviluppare un client di dispositivi IoT senza usare un SDK per dispositivi

È consigliabile usare uno degli SDK per dispositivi IoT di Azure per creare i client dei dispositivi IoT, se possibile. Tuttavia, in scenari come l'uso di un dispositivo con vincoli di memoria, potrebbe essere necessario usare una libreria MQTT per comunicare con l'hub IoT.

Gli esempi in questa esercitazione usano la libreria Eclipse Mosquitto MQTT.

In questa esercitazione apprenderai a:

  • Compilare le applicazioni di esempio client del dispositivo del linguaggio C.
  • Eseguire un esempio che usa la libreria MQTT per inviare dati di telemetria.
  • Eseguire un esempio che usa la libreria MQTT per elaborare un messaggio da cloud a dispositivo inviato dall'hub IoT.
  • Eseguire un esempio che usa la libreria MQTT per gestire il dispositivo gemello nel dispositivo.

È possibile usare un computer di sviluppo Windows o Linux per completare i passaggi descritti in questa esercitazione.

Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.

Prerequisiti

Preparare l'ambiente per l'interfaccia della riga di comando di Azure

Prerequisiti dei computer di sviluppo

Se si usa Windows:

  1. Installare Visual Studio (Community, Professional o Enterprise). Assicurarsi di abilitare il carico di lavoro Sviluppo di applicazioni desktop con C++ .

  2. Installare CMake. Abilitare l'opzione Aggiungi CMake al percorso di sistema per tutti gli utenti .

  3. Installare la versione x64 di Mosquitto.

Se si usa Linux:

  1. Eseguire il comando seguente per installare gli strumenti di compilazione:

    sudo apt install cmake g++
    
  2. Eseguire il comando seguente per installare la libreria client Mosquitto:

    sudo apt install libmosquitto-dev
    

Configurazione dell'ambiente

Se non si ha già un hub IoT, eseguire i comandi seguenti per creare un hub IoT di livello gratuito in un gruppo di risorse denominato mqtt-sample-rg. Il comando usa il nome my-hub come esempio per il nome dell'hub IoT da creare. Scegliere un nome univoco per l'hub IoT da usare al posto di 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 

Prendere nota del nome dell'hub IoT, che sarà necessario in un secondo momento.

Registrare un dispositivo nell'hub IoT. Il comando seguente registra un dispositivo denominato mqtt-dev-01 in un hub IoT denominato my-hub. Assicurarsi di usare il nome dell'hub IoT:

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

Usare il comando seguente per creare un token di firma di accesso condiviso che concede al dispositivo l'accesso all'hub IoT. Assicurarsi di usare il nome dell'hub IoT:

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

Prendere nota del token di firma di accesso condiviso che il comando restituisce come necessario in un secondo momento. Il token di firma di accesso condiviso ha un aspetto simile al seguente SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

Suggerimento

Per impostazione predefinita, il token di firma di accesso condiviso è valido per 60 minuti. L'opzione --du 7200 nel comando precedente estende la durata del token a due ore. Se scade prima di essere pronti per usarlo, generarne uno nuovo. È anche possibile creare un token con una durata più lunga. Per altre informazioni, vedere az iot hub generate-sas-token.

Clonare il repository di esempio

Usare il comando seguente per clonare il repository di esempio in una posizione adatta nel computer locale:

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

Il repository include anche:

  • Esempio python che usa la paho-mqtt libreria.
  • Istruzioni per l'uso dell'interfaccia della riga di comando per interagire con l'hub mosquitto_pub IoT.

Compilare gli esempi C

Prima di compilare l'esempio, è necessario aggiungere i dettagli dell'hub IoT e del dispositivo. Nel repository IoTMQTTSample clonato aprire il file mosquitto/src/config.h . Aggiungere il nome dell'hub IoT, l'ID dispositivo e il token di firma di accesso condiviso come indicato di seguito. Assicurarsi di usare il nome dell'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"

Nota

Il file IoTHubRootCA.crt.pem include i certificati radice della CA per la connessione TLS.

Salvare le modifiche apportate al file mosquitto/src/config.h .

Per compilare gli esempi, eseguire i comandi seguenti nella shell:

cd mosquitto
cmake -Bbuild
cmake --build build

In Linux i file binari si trovano nella cartella ./build sotto la cartella mosquitto .

In Windows i file binari si trovano nella cartella .\build\Debug sotto la cartella mosquitto .

Inviare dati di telemetria

L'esempio di mosquitto_telemetry illustra come inviare un messaggio di telemetria da dispositivo a cloud all'hub IoT usando la libreria MQTT.

Prima di eseguire l'applicazione di esempio, eseguire il comando seguente per avviare il monitoraggio eventi per l'hub IoT. Assicurarsi di usare il nome dell'hub IoT:

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

Eseguire l'esempio di mosquitto_telemetry . Ad esempio, in Linux:

./build/mosquitto_telemetry

az iot hub monitor-events Genera l'output seguente che mostra il payload inviato dal dispositivo:

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

È ora possibile arrestare il monitoraggio eventi.

Esaminare il codice

I frammenti di codice seguenti sono tratti dal file mosquitto/src/mosquitto_telemetry.cpp .

Le istruzioni seguenti definiscono le informazioni di connessione e il nome dell'argomento MQTT usato per inviare il messaggio di telemetria:

#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 main funzione imposta il nome utente e la password per l'autenticazione con l'hub IoT. La password è il token di firma di accesso condiviso creato per il dispositivo:

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

L'esempio usa l'argomento MQTT per inviare un messaggio di telemetria all'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");

Per altre informazioni, vedere Invio di messaggi da dispositivo a cloud.

Ricevere un messaggio da cloud a dispositivo

L'esempio di mosquitto_subscribe illustra come sottoscrivere gli argomenti MQTT e ricevere un messaggio da cloud a dispositivo dall'hub IoT usando la libreria MQTT.

Eseguire l'esempio di mosquitto_subscribe . Ad esempio, in Linux:

./build/mosquitto_subscribe

Eseguire il comando seguente per inviare un messaggio da cloud a dispositivo dall'hub IoT. Assicurarsi di usare il nome dell'hub IoT:

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

L'output di mosquitto_subscribe è simile all'esempio seguente:

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

Esaminare il codice

I frammenti di codice seguenti sono tratti dal file mosquitto/src/mosquitto_subscribe.cpp .

L'istruzione seguente definisce il filtro dell'argomento usato dal dispositivo per ricevere messaggi da cloud a dispositivo. # è un carattere jolly multilivello:

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

La main funzione usa la mosquitto_message_callback_set funzione per impostare un callback per gestire i messaggi inviati dall'hub IoT e usa la mosquitto_subscribe funzione per sottoscrivere tutti i messaggi. Il frammento di codice seguente mostra la funzione di callback:

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

Per altre informazioni, vedere Usare MQTT per ricevere messaggi da cloud a dispositivo.

Aggiornare un dispositivo gemello

L'esempio di mosquitto_device_twin mostra come impostare una proprietà segnalata in un dispositivo gemello e quindi leggere nuovamente la proprietà.

Eseguire l'esempio di mosquitto_device_twin . Ad esempio, in Linux:

./build/mosquitto_device_twin

L'output di mosquitto_device_twin è simile all'esempio seguente:

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.

Esaminare il codice

I frammenti di codice seguenti provengono dal file mosquitto/src/mosquitto_device_twin.cpp .

Le istruzioni seguenti definiscono gli argomenti usati dal dispositivo per sottoscrivere gli aggiornamenti dei dispositivi gemelli, leggere il dispositivo gemello e aggiornare il dispositivo gemello:

#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 main funzione usa la mosquitto_connect_callback_set funzione per impostare un callback per gestire i messaggi inviati dall'hub IoT e usa la mosquitto_subscribe funzione per sottoscrivere l'argomento $iothub/twin/res/# .

Il frammento di codice seguente mostra la connect_callback funzione che usa mosquitto_publish per impostare una proprietà segnalata nel dispositivo gemello. Il dispositivo pubblica il messaggio nell'argomento $iothub/twin/PATCH/properties/reported/?$rid=%d . Il %d valore viene incrementato ogni volta che il dispositivo pubblica un messaggio nell'argomento:

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

Il dispositivo sottoscrive l'argomento $iothub/twin/res/# e quando riceve un messaggio dall'hub IoT, la message_callback funzione la gestisce. Quando si esegue l'esempio, la message_callback funzione viene chiamata due volte. La prima volta, il dispositivo riceve una risposta dall'hub IoT all'aggiornamento della proprietà segnalata. Il dispositivo richiede quindi il dispositivo gemello. La seconda volta, il dispositivo riceve il dispositivo gemello richiesto. Il frammento di codice seguente illustra la message_callback funzione :

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

Per altre informazioni, vedere Usare MQTT per aggiornare una proprietà segnalata del dispositivo gemello e Usare MQTT per recuperare una proprietà del dispositivo gemello.

Pulire le risorse

Se si prevede di continuare con altri articoli per sviluppatori di dispositivi, è possibile mantenere e riutilizzare le risorse usate in questo articolo. In caso contrario, è possibile eliminare le risorse create in questo articolo per evitare altri addebiti.

È possibile eliminare l'hub e il dispositivo registrato contemporaneamente eliminando l'intero gruppo di risorse con il comando dell'interfaccia della riga di comando di Azure seguente. Non usare questo comando se queste risorse condividono un gruppo di risorse con altre risorse che si vogliono conservare.

az group delete --name <YourResourceGroupName>

Per eliminare solo l'hub IoT, eseguire questo comando usando l'interfaccia della riga di comando di Azure:

az iot hub delete --name <YourIoTHubName>

Per eliminare solo l'identità del dispositivo registrato con l'hub IoT, eseguire questo comando usando l'interfaccia della riga di comando di Azure:

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

È anche possibile rimuovere dal computer di sviluppo i file di esempio clonati.

Passaggi successivi

Ora che si è appreso come usare la libreria Mosquitto MQTT per comunicare con hub IoT, è consigliabile esaminare il passaggio successivo consigliato: