次の方法で共有


チュートリアル - MQTT を使用して、デバイス SDK を使用せずに IoT デバイス クライアントを開発する

可能であれば、Azure IoT Device SDK のいずれかを使用して IoT デバイス クライアントを構築する必要があります。 ただし、メモリ制約付きデバイスの使用などのシナリオでは、MQTT ライブラリを使用して IoT ハブと通信することが必要になる場合があります。

このチュートリアルのサンプルでは、 Eclipse Mosquitto MQTT ライブラリを使用します。

このチュートリアルでは、以下の内容を学習します。

  • C 言語デバイス クライアント サンプル アプリケーションをビルドします。
  • MQTT ライブラリを使用してテレメトリを送信するサンプルを実行します。
  • MQTT ライブラリを使用して、IoT ハブから送信されたクラウドからデバイスへのメッセージを処理するサンプルを実行します。
  • MQTT ライブラリを使用してデバイス上のデバイス ツインを管理するサンプルを実行します。

Windows または Linux の開発マシンを使用して、このチュートリアルの手順を完了できます。

Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。

[前提条件]

開発用コンピューターの前提条件

  1. Visual Studio (Community、Professional、または Enterprise) をインストールします。 C++ ワークロードを使用した デスクトップ開発 を必ず有効にしてください。

  2. CMake をインストールします。 [ すべてのユーザーのシステム パスに CMake を追加する] オプションを 有効にします。

  3. x64 バージョンMosquitto をインストールします。

Azure CLI の環境を準備する

  • Azure Cloud Shell で Bash 環境を使用します。 詳細については、「Azure Cloud Shell の概要」を参照してください。

  • CLI 参照コマンドをローカルで実行する場合は、Azure CLI を インストール します。 Windows または macOS で実行している場合は、Docker コンテナーで Azure CLI を実行することを検討してください。 詳細については、「Docker コンテナーで Azure CLI を実行する方法」を参照してください。

    • ローカル インストールを使用する場合は、az login コマンドを使用して Azure CLI にサインインします。 認証プロセスを完了するには、ターミナルに表示される手順に従います。 その他のサインイン オプションについては、「 Azure CLI を使用した Azure への認証」を参照してください。

    • 初回使用時にインストールを求められたら、Azure CLI 拡張機能をインストールします。 拡張機能の詳細については、「Azure CLI で拡張機能を使用および管理する」を参照してください。

    • az version を実行し、インストールされているバージョンおよび依存ライブラリを検索します。 最新バージョンにアップグレードするには、az upgrade を実行します。

環境を設定する

IoT ハブがまだない場合は、次のコマンドを実行して、 mqtt-sample-rgというリソース グループに Free レベルの IoT ハブを作成します。 このコマンドは、作成する IoT ハブの名前の例として my-hub 名前を使用します。 my-hubの代わりに使用する IoT ハブの一意の名前を選択します。

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

IoT ハブの名前を書き留めます。後で必要になります。

IoT ハブにデバイスを登録します。 次のコマンドは、mqtt-dev-01と呼ばれる IoT ハブに my-hub というデバイスを登録します。 必ず IoT ハブの名前を使用してください。

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

次のコマンドを使用して、デバイスに IoT ハブへのアクセスを許可する SAS トークンを作成します。 必ず IoT ハブの名前を使用してください。

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

後で必要に応じて、コマンドによって出力される SAS トークンを書き留めます。 SAS トークンは次のようになります。 SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761

ヒント

既定では、SAS トークンは 60 分間有効です。 前のコマンドの --du 7200 オプションを使用すると、トークンの期間が 2 時間に延長されます。 使用する準備が整う前に有効期限が切れた場合は、新しい有効期限を生成します。 期間が長いトークンを作成することもできます。 詳細については、 az iot hub generate-sas-token に関するページを参照してください。

Important

この記事では、Shared Access Signature (対称キー認証とも呼ばれます) を使用してデバイスを接続する手順について説明します。 この認証方法はテストと評価には便利ですが、X.509 証明書を使用してデバイスを認証する方が安全なアプローチです。 詳細については、 接続セキュリティ > IoT ソリューションのセキュリティのベスト プラクティスに関するページを参照してください。

サンプル リポジトリを複製する

次のコマンドを使用して、サンプル リポジトリをローカル コンピューター上の適切な場所に複製します。

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

リポジトリには次も含まれます。

  • paho-mqtt ライブラリを使用する Python サンプル。
  • mosquitto_pub CLI を使用して IoT ハブを操作する手順。

C サンプルをビルドする

サンプルをビルドする前に、IoT ハブとデバイスの詳細を追加する必要があります。 複製された IoTMQTTSample リポジトリで、 mosquitto/src/config.h ファイルを開きます。 次のように、IoT ハブ名、デバイス ID、SAS トークンを追加します。 必ず 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"

IoTHubRootCA.crt.pem ファイルには、TLS 接続用の CA ルート証明書が含まれています。

変更を mosquitto/src/config.h ファイルに保存します。

サンプルをビルドするには、シェルで次のコマンドを実行します。

cd mosquitto
cmake -Bbuild
cmake --build build

Linux では、バイナリは mosquitto フォルダーの下の ./build フォルダーにあります。

Windows では、バイナリは mosquitto フォルダーの下の .\build\Debug フォルダーにあります。

テレメトリを送信する

mosquitto_telemetryサンプルは、MQTT ライブラリを使用して、デバイスからクラウドへのテレメトリ メッセージを IoT ハブに送信する方法を示しています。

サンプル アプリケーションを実行する前に、次のコマンドを実行して、IoT ハブのイベント モニターを開始します。 必ず IoT ハブの名前を使用してください。

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

mosquitto_telemetry サンプルを実行します。 たとえば、Linux では次のようになります。

./build/mosquitto_telemetry

az iot hub monitor-eventsは、デバイスによって送信されたペイロードを示す次の出力を生成します。

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

これで、イベント モニターを停止できます。

コードの確認

次のスニペットは 、mosquitto/src/mosquitto_telemetry.cpp ファイルから取得されます。

次のステートメントでは、接続情報と、テレメトリ メッセージの送信に使用する MQTT トピックの名前を定義します。

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

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

main関数は、IoT ハブで認証するユーザー名とパスワードを設定します。 パスワードは、デバイス用に作成した SAS トークンです。

mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);

このサンプルでは、MQTT トピックを使用して、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");

詳細については、「 デバイスからクラウドへのメッセージの送信」を参照してください。

クラウドからデバイスへのメッセージを受信する

mosquitto_subscribeサンプルは、MQTT トピックをサブスクライブし、MQTT ライブラリを使用して IoT ハブからクラウドからデバイスへのメッセージを受信する方法を示しています。

mosquitto_subscribe サンプルを実行します。 たとえば、Linux では次のようになります。

./build/mosquitto_subscribe

次のコマンドを実行して、IoT ハブからクラウドからデバイスへのメッセージを送信します。 必ず IoT ハブの名前を使用してください。

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

mosquitto_subscribeからの出力は次の例のようになります。

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

コードの確認

次のスニペットは 、mosquitto/src/mosquitto_subscribe.cpp ファイルから取得されます。

次のステートメントでは、クラウドからデバイスへのメッセージを受信するためにデバイスが使用するトピック フィルターを定義します。 #は複数レベルのワイルドカードです。

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

main関数は、mosquitto_message_callback_set関数を使用して、IoT ハブから送信されたメッセージを処理するコールバックを設定し、mosquitto_subscribe関数を使用してすべてのメッセージをサブスクライブします。 次のスニペットは、コールバック関数を示しています。

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

詳細については、「MQTT を 使用してクラウドからデバイスへのメッセージを受信する」を参照してください。

デバイス ツインを更新する

mosquitto_device_twinサンプルは、デバイス ツインで報告されたプロパティを設定し、プロパティを読み取り戻す方法を示しています。

mosquitto_device_twin サンプルを実行します。 たとえば、Linux では次のようになります。

./build/mosquitto_device_twin

mosquitto_device_twinからの出力は次の例のようになります。

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.

コードの確認

次のスニペットは 、mosquitto/src/mosquitto_device_twin.cpp ファイルから取得されます。

次のステートメントでは、デバイス ツインの更新のサブスクライブ、デバイス ツインの読み取り、デバイス ツインの更新にデバイスが使用するトピックを定義します。

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

main関数は、mosquitto_connect_callback_set関数を使用して、IoT ハブから送信されたメッセージを処理するコールバックを設定し、mosquitto_subscribe関数を使用して $iothub/twin/res/# トピックをサブスクライブします。

次のスニペットは、connect_callbackを使用してデバイス ツインで報告されるプロパティを設定するmosquitto_publish関数を示しています。 デバイスは、メッセージを $iothub/twin/PATCH/properties/reported/?$rid=%d トピックに発行します。 %d値は、デバイスがトピックにメッセージを発行するたびにインクリメントされます。

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

デバイスは $iothub/twin/res/# トピックをサブスクライブし、IoT ハブからメッセージを受信すると、 message_callback 関数によって処理されます。 サンプルを実行すると、 message_callback 関数が 2 回呼び出されます。 最初に、デバイスは IoT ハブから報告されたプロパティの更新に対する応答を受信します。 その後、デバイスによってデバイス ツインが要求されます。 2 回目に、デバイスは要求されたデバイス ツインを受信します。 次のスニペットは、 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
    }
}

詳細については、「 MQTT を使用してデバイス ツインの報告されたプロパティを更新する 」および 「MQTT を使用してデバイス ツインのプロパティを取得する」を参照してください。

リソースをクリーンアップする

さらに多くのデバイス開発者向け記事を続行する場合は、この記事で使用したリソースを保持して再利用できます。 それ以外の場合は、この記事で作成したリソースを削除して、より多くの料金を回避できます。

次の Azure CLI コマンドを使用してリソース グループ全体を削除することで、ハブと登録済みデバイスの両方を一度に削除できます。 これらのリソースが、保持する他のリソースとリソース グループを共有している場合は、このコマンドを使用しないでください。

az group delete --name <YourResourceGroupName>

IoT ハブのみを削除するには、Azure CLI を使用して次のコマンドを実行します。

az iot hub delete --name <YourIoTHubName>

IoT ハブに登録したデバイス ID のみを削除するには、Azure CLI を使用して次のコマンドを実行します。

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

また、複製したサンプル ファイルを開発用コンピューターから削除することもできます。

次のステップ

これで、Mosquitto MQTT ライブラリを使用して IoT Hub と通信する方法を学習しました。推奨される次の手順は、GitHub で MQTT アプリケーションのサンプル を確認することです。