MQTT プロトコルを使用した IoT ハブとの通信

この記事では、デバイスがサポートされている MQTT 動作を使用して Azure IoT Hub との通信を行う方法について説明します。 IoT Hub により、デバイスは、以下を使用して IoT Hub デバイス エンドポイントと通信できます。

  • TCP ポート 8883 上の MQTT v3.1.1
  • TCP ポート 443 上の MQTT v3.1.1 over WebSocket。

Note

この記事で言及されている一部の機能 (cloud-to-device メッセージング、デバイス ツイン、デバイス管理など) は、IoT Hub の Standard レベルだけで使用することができます。 Basic および Standard または Free レベルの IoT Hub の詳細については、「ソリューションに適した IoT Hub のレベルを選択する」を参照してください。

IoT Hub でのすべてのデバイス通信は、TLS/SSL を使用してセキュリティで保護する必要があります。 そのため、IoT Hub では、TCP ポート 1883 経由のセキュリティで保護されていない接続はサポートしません。

IoT Hub と Event Grid での MQTT サポートの比較

IoT Hub はフル機能の MQTT ブローカーではないため、MQTT v3.1.1 標準で指定されているすべての動作をサポートしているわけではありません。 ソリューションに MQTT が必要な場合は、Azure Event Grid での MQTT サポートをお勧めします。 Event Grid では、pub-sub メッセージング モデルを使用して、柔軟な階層構造トピック上の MQTT クライアント間での双方向通信が可能になります。 さらに処理を行うために、MQTT メッセージを Azure サービスまたはカスタム エンドポイントにルーティングすることもできます。

次の表では、2 つのサービス間の MQTT サポートの違いについて説明します。

IoT Hub Event Grid
デバイスとクラウド アプリ間の緊密な結合を備えたクライアント サーバー モデル。 パブリッシャーとサブスクライバーを分離するパブリッシュ サブスクライブ モデル。
MQTT v3.1.1 の制限付き機能のサポートと、プレビュー中の MQTT v5 の制限付き機能サポート。 その他の機能のサポートは計画されていません。 MQTT v3.1.1 および v5 プロトコルのサポートと、さらに多くの機能サポートと業界コンプライアンスが計画されています。
静的で定義済みのトピック。 ワイルドカードをサポートするカスタム階層型トピック。
cloud-to-device ブロードキャストと device-to-device の通信はサポートされません。 device-to-cloud、ファンアウトの高い cloud-to-device ブロードキャスト、および device-to-device 通信パターンをサポートします。
最大メッセージ サイズは 256 KB。 最大メッセージ サイズは 512 KB。

IoT Hub への接続

デバイスでは、MQTT プロトコルを使用し、次のいずれかのオプションを利用して IoT ハブに接続できます。

MQTT ポート (TCP ポート 8883) は、多くの企業や教育用のネットワーク環境ではブロックされています。 ファイアウォールでポート 8883 を開けない場合は、MQTT over WebSocket を使用することをお勧めします。 MQTT over WebSocket は、ほとんどの場合はネットワーク環境で開放されているポート 443 を介して通信します。 Azure IoT SDK を使用しているときに MQTT プロトコルと MQTT over WebSocket プロトコルを指定する方法については、「デバイス SDK の使用」を参照してください。

デバイス SDK の使用

MQTT プロトコルをサポートするデバイス SDK は、Java、Node.js、C、C#、および Python に対応しています。 デバイス SDK は、選択した認証メカニズムを使用して、IoT ハブへの接続を確立します。 MQTT プロトコルを使用するには、クライアント プロトコル パラメーターを MQTTに設定する必要があります。 また、クライアント プロトコル パラメーターで MQTT over Web Sockets を指定することもできます。 デバイス SDK は既定では、CleanSession フラグを 0 に設定して IoT ハブに接続し、IoT ハブとのメッセージ交換には QoS 1 を使用します。 メッセージ交換を高速にすために QoS 0 を構成することはできますが、配信が保証されず、確認応答がないことに注意する必要があります。 このため、QoS 0 は "ファイア アンド フォーゲット" と呼ばれることがよくあります。

デバイスは、IoT ハブに接続されると、デバイス SDK によって、IoT ハブとのメッセージの交換を可能にするメソッドが提供されます。

次の表は、サポートされている各言語のコード サンプルへのリンクを提供すると共に、MQTT プロトコルまたは MQTT over WebSocket プロトコルを使用して IoT Hub への接続を確立するために使用するパラメーターを示しています。

Language MQTT プロトコルのパラメーター MQTT over WebSocket プロトコルのパラメーター
Node.js azure-iot-device-mqtt.Mqtt azure-iot-device-mqtt.MqttWs
Java IotHubClientProtocol.MQTT IotHubClientProtocol.MQTT_WS
C MQTT_Protocol MQTT_WebSocket_Protocol
C# TransportType.Mqtt MQTT が失敗した場合、TransportType.Mqtt は MQTT over WebSocket にフォールバックします。 MQTT over WebSocket のみを指定するには、TransportType.Mqtt_WebSocket_Only を使用します
Python 既定で MQTT をサポートします 呼び出しに websockets=True を追加してクライアントを作成します

次のフラグメントは、Azure IoT Node.js SDK を使用しているときに MQTT over WebSocket プロトコルを指定する方法を示しています。

var Client = require('azure-iot-device').Client;
var Protocol = require('azure-iot-device-mqtt').MqttWs;
var client = Client.fromConnectionString(deviceConnectionString, Protocol);

次のフラグメントは、Azure IoT Python.js SDK を使用しているときに MQTT over WebSocket プロトコルを指定する方法を示しています。

from azure.iot.device.aio import IoTHubDeviceClient
device_client = IoTHubDeviceClient.create_from_connection_string(deviceConnectionString, websockets=True)

既定のキープアライブ タイムアウト

クライアント/IoT Hub 接続を確実に存続させるために、サービスとクライアントは、どちらもキープアライブ ping を定期的に相手に送信します。 IoT SDK を使用しているクライアントは、次の表に定義されている間隔でキープアライブを送信します。

Language 既定のキープアライブ間隔 構成可能
Node.js 180 秒 いいえ
Java 230 秒 はい
C 240 秒 はい
C# 300 秒* はい
Python 60 秒 はい

*C# SDK では、MQTT KeepAliveInSeconds プロパティのデフォルト値は 300 秒と定義されています。 実際には、SDK はキープアライブ期間セットごとに 4 回 ping 要求を送信します。 つまり、SDK では 75 秒ごとにキープアライブ ping が 1 回送信されます。

MQTT v3.1.1 の仕様に基づき、IoT Hub のキープアライブ ping 間隔はクライアントのキープアライブ値の 1.5 倍になります。ただし、IoT Hub では、サーバー側の最大タイムアウトは 29.45 分 (1,767 秒) に制限されています。 この制限が存在するのは、すべての Azure サービスが Azure ロード バランサーの TCP アイドル タイムアウト (29.45 分) にバインドされているためです。

たとえば、Java SDK を使用しているデバイスでは、キープアライブ ping が送信された後、ネットワーク接続が失われます。 230 秒後、デバイスはオフラインになっているため、キープアライブ ping は失敗します。 ただし、IoT Hub では、接続はすぐに閉じられるわけではありません。さらに (230 * 1.5) - 230 = 115 秒間待機した後、エラー 404104 DeviceConnectionClosedRemotely でデバイスが切断されます。

設定できるクライアントのキープアライブの最大値は、1767 / 1.5 = 1177 秒です。 すべてのトラフィックで、キープアライブがリセットされます。 たとえば、共有アクセス署名 (SAS) トークンの更新が成功すると、キープアライブがリセットされます。

デバイス アプリの AMQP から MQTT への移行

デバイス SDK を使用している場合、AMQP から MQTT に使用を切り替えるには、前述のようにクライアントの初期化時にプロトコル パラメーターを変更する必要があります。

これを行う際は、次の項目をご確認ください。

  • AMQP では、MQTT 接続を終了するときに、多くの条件のエラーが返されます。 そのため、例外処理のロジックを一部変更する必要が生じることがあります。

  • MQTT は、クラウドからデバイスへのメッセージを受信するときの "拒否" 操作をサポートしていません。 バックエンド アプリではデバイス アプリから応答を受信する必要がある場合、ダイレクト メソッドの使用を検討してください。

  • Python SDK では AMQP はサポートされていません。

MQTT プロトコルの直接使用 (デバイスとして)

デバイスでデバイス SDK を使用できない場合でも、MQTT プロトコルをポート 8883 で使用して、デバイスをパブリックのデバイス エンドポイントに接続できます。

CONNECT パケットの場合、デバイスでは次の値を使用する必要があります。

  • ClientId フィールドには、deviceId を使用します。

  • [ユーザー名] フィールドには、{iotHub-hostname}/{device-id}/?api-version=2021-04-12 を使用します。{iotHub-hostname} は IoT Hub の完全な CName です。

    たとえば、IoT Hub の名前が contoso.azure-devices.net であり、デバイスの名前が MyDevice01 であるとすると、Username フィールドの内容は 次のようになります。

    contoso.azure-devices.net/MyDevice01/?api-version=2021-04-12

    フィールドに api-version を含めることをお勧めします。 そうしないと、予期しない動作が発生するおそれがあります。

  • [Password] フィールドには、SAS トークンを使用します。 SAS トークンの形式は、HTTPS プロトコルや AMQP プロトコルの場合と同じです。

    SharedAccessSignature sig={signature-string}&se={expiry}&sr={URL-encoded-resourceURI}

    Note

    X.509 証明書の認証を使用する場合は、SAS トークン パスワードは不要です。 詳細については、「チュートリアル: テスト用の証明書の作成とアップロード」を参照し、「TLS/SSL 構成セクション」のコード手順に従います。

    SAS トークンを生成する方法の詳細については、「Shared Access Signature を使用して IoT Hub へのアクセスを制御する」の「デバイスとして SAS トークンを使用する」セクションを参照してください。

    クロスプラットフォームの Visual Studio Code 用 Azure IoT Hub 拡張機能または CLI 拡張機能コマンド az iot hub generate-sas-token を使用して、SAS トークンを簡単に生成することができます。 その後、テスト目的で SAS トークンをコピーして独自のコードに貼り付けることができます。

MQTT を直接使用するチュートリアルについては、「MQTT を使用してデバイス SDK を使用せずに IoT デバイス クライアントを開発する」を参照してください。

Visual Studio Code 用の Azure IoT Hub 拡張機能を使用する

  1. サイド バーで、[Azure IoT Hub] セクションの下にある [デバイス] ノードを展開します。

  2. IoT デバイスを右クリックし、コンテキスト メニューから [デバイスの SAS トークンの生成] を選択します。

  3. 入力ボックスに SAS トークンの有効期限を時間単位で入力し、Enter キーを選択します。

  4. SAS トークンが作成され、クリップボードにコピーされます。

    生成される SAS トークンは、次のような構成になります。

    HostName={iotHub-hostname};DeviceId=javadevice;SharedAccessSignature=SharedAccessSignature sr={iotHub-hostname}%2Fdevices%2FMyDevice01%2Fapi-version%3D2016-11-14&sig=vSgHBMUG.....Ntg%3d&se=1456481802

    MQTT を使用して接続するための [Password] フィールドとして使用されるこのトークンの一部は次のようになります。

    SharedAccessSignature sr={iotHub-hostname}%2Fdevices%2FMyDevice01%2Fapi-version%3D2016-11-14&sig=vSgHBMUG.....Ntg%3d&se=1456481802

デバイス アプリは、CONNECT パケットに Will メッセージを指定できます。 また、デバイス アプリは、devices/{device-id}/messages/events/ または devices/{device-id}/messages/events/{property-bag}Will トピック名として使用することで、テレメトリ メッセージとして転送される Will メッセージ を定義する必要があります。 この場合、ネットワーク接続が閉じている一方で、DISCONNECT パケットがデバイスからまだ受信されていない場合、IoT Hub は、CONNECT パケットで提供される Will メッセージをテレメトリ チャネルに送信します。 テレメトリ チャネルは、既定のイベント エンドポイントにすることも、IoT Hub ルーティングで定義されるカスタム エンドポイントにすることもできます。 メッセージには iothub-MessageType プロパティが含まれており、その値には Will が割り当てられています。

MQTT プロトコルの直接使用 (モジュールとして)

デバイスとして IoT Hub に接続する場合と同様に、モジュール ID を使用して MQTT 経由で IoT Hub に接続できます。 デバイスとして MQTT 経由で IoT Hub に接続する方法の詳細については、「MQTT プロトコルの直接使用 (デバイスとして)」を参照してください。 ただし、次の値を使用する必要があります。

  • クライアント ID を {device-id}/{module-id} に設定します。

  • ユーザー名とパスワードを使用して認証する場合、ユーザー名を <hubname>.azure-devices.net/{device_id}/{module_id}/?api-version=2021-04-12 に設定し、パスワードとしてモジュール ID に関連付けられている SAS トークンを使用します。

  • 利用統計情報を公開するためのトピックとして devices/{device-id}/modules/{module-id}/messages/events/ を使用します。

  • WILL トピックとして devices/{device-id}/modules/{module-id}/messages/events/ を使用します。

  • メッセージを受信するためのトピックとして devices/{device-id}/modules/{module-id}/# を使用します。

  • ツインの GET トピックと PATCH トピックは、モジュールとデバイスと同じです。

  • ツインの状態トピックは、モジュールとデバイスと同じです。

モジュールでの MQTT の使用について詳しくは、「IoT Edge を使用した発行とサブスクライブ」を参照してください。また、IoT Edge ハブ MQTT エンドポイントの詳細を確認してください。

Azure IoT SDK を使用しない MQTT を使用したサンプル

IoT MQTT サンプル リポジトリには、Azure デバイス SDK を使用せずに、テレメトリ メッセージを送信、cloud-to-device メッセージを受信、デバイス ツインを使用する方法を示す C/C++、Python、CLI のサンプルが含まれています。

C/C++ サンプルでは Eclipse Mosquitto ライブラリを使用し、Python サンプルでは Eclipse Paho を使用、CLI サンプルでは mosquitto_pub を使用します。

詳細については、MQTT を使用して IoT デバイス クライアントを開発するチュートリアルに関するページを参照してください。

TLS または SSL の構成

MQTT プロトコルを直接使用するには、クライアントは TLS または SSL 経由で接続する "必要があります"。 この手順をスキップすると、接続エラーで失敗します。

TLS 接続を確立するには、Azure が使用する DigiCert ルート証明書をダウンロードして参照する必要がある場合があります。 2023 年 2 月 15 日から 10 月 15 日の間に、Azure IoT Hub は、その TLS ルート証明書を DigiCert Baltimore ルート証明書から DigiCert グローバル ルート G2 に移行します。 移行期間中は、接続を確保するために、デバイスに両方の証明書が必要です。 移行の詳細については、「IoT リソースを新しい TLS 証明書ルートに移行する」を参照してください。これらの証明書の詳細については、Digicert の Web サイトを参照してください。

次の例は、Eclipse Foundation による Python バージョンの Paho MQTT ライブラリを使用して、この構成を実装する方法を示しています。

最初に、コマンドライン環境から Paho ライブラリをインストールします。

pip install paho-mqtt

次に、Python スクリプトでクライアントを実装します。 次のコード スニペットで、これらのプレースホルダーを置き換えます。

  • <local path to digicert.cer> は、DigiCert ルート証明書を含むローカル ファイルのパスです。 このファイルは、証明書情報を Azure IoT SDK for C のcerts.c からコピーすることで作成できます。-----BEGIN CERTIFICATE----- 行と -----END CERTIFICATE----- 行を含め、すべての行の先頭と末尾の " 印を削除し、すべての行の末尾の \r\n 文字を削除します。

  • <device id from device registry> は、IoT ハブに追加したデバイスの ID です。

  • <generated SAS token> は、この記事で前述のように作成されたデバイスの SAS トークンです。

  • <iot hub name> は、IoT ハブの名前です。

from paho.mqtt import client as mqtt
import ssl

path_to_root_cert = "<local path to digicert.cer file>"
device_id = "<device id from device registry>"
sas_token = "<generated SAS token>"
iot_hub_name = "<iot hub name>"


def on_connect(client, userdata, flags, rc):
    print("Device connected with result code: " + str(rc))


def on_disconnect(client, userdata, rc):
    print("Device disconnected with result code: " + str(rc))


def on_publish(client, userdata, mid):
    print("Device sent message")


client = mqtt.Client(client_id=device_id, protocol=mqtt.MQTTv311)

client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_publish = on_publish

client.username_pw_set(username=iot_hub_name+".azure-devices.net/" +
                       device_id + "/?api-version=2021-04-12", password=sas_token)

client.tls_set(ca_certs=path_to_root_cert, certfile=None, keyfile=None,
               cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
client.tls_insecure_set(False)

client.connect(iot_hub_name+".azure-devices.net", port=8883)

client.publish("devices/" + device_id + "/messages/events/", '{"id":123}', qos=1)
client.loop_forever()

デバイス証明書を使用して認証するには、前のコード スニペットを次のコード スニペットで指定されている変更内容で更新します。 証明書ベースの認証を準備する方法の詳細については、「X.509 CA 証明書を使用してデバイスを認証する」の「X.509 CA 証明書を入手する」セクションを参照してください。

# Create the client as before
# ...

# Set the username but not the password on your client
client.username_pw_set(username=iot_hub_name+".azure-devices.net/" +
                       device_id + "/?api-version=2021-04-12", password=None)

# Set the certificate and key paths on your client
cert_file = "<local path to your certificate file>"
key_file = "<local path to your device key file>"
client.tls_set(ca_certs=path_to_root_cert, certfile=cert_file, keyfile=key_file,
               cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

# Connect as before
client.connect(iot_hub_name+".azure-devices.net", port=8883)

デバイスからクラウドへのメッセージの送信

デバイスは、接続後も、トピック名として devices/{device-id}/messages/events/ または devices/{device-id}/messages/events/{property-bag} を使用して IoT Hub にメッセージを送信できます。 {property-bag} 要素を使用すると、デバイスは他のプロパティを含むメッセージを URL エンコード形式で送信できるようになります。 次に例を示します。

RFC 2396-encoded(<PropertyName1>)=RFC 2396-encoded(<PropertyValue1>)&RFC 2396-encoded(<PropertyName2>)=RFC 2396-encoded(<PropertyValue2>)…

注意

この {property_bag} 要素では、HTTPS プロトコルでのクエリ文字列と同じエンコードを使用します。

Note

D2C メッセージを Azure Storage アカウントにルーティングし、JSON エンコードを利用する場合は、前の注意で言及した {property_bag} の一部として $.ct=application%2Fjson&$.ce=utf-8 を含め、コンテンツ タイプとコンテンツ エンコード情報を指定する必要があります。

これらの属性の形式はプロトコル固有です。 IoT Hub は、これらの属性を対応するシステム プロパティに変換します。 詳細については、「IoT Hub メッセージ ルーティングのクエリ構文」の「システム プロパティ」セクションを参照してください。

次のリストは、IoT Hub 実装固有のビヘイビアーについて説明しています。

  • IoT Hub では、QoS 2 メッセージはサポートされていません。 デバイス アプリから QoS 2 を使用したメッセージが発行されると、IoT Hub はネットワーク接続を閉じます。

  • IoT Hub では、Retain メッセージは保持されません。 デバイスで RETAIN フラグを 1 に設定してメッセージが送信されると、IoT Hub によってそのメッセージに mqtt-retain アプリケーション プロパティが追加されます。 この場合、IoT Hub は、Retain メッセージを保持するのではなく、バックエンド アプリにそのメッセージを渡します。

  • IoT Hub は、デバイスごとにアクティブな MQTT 接続を 1 つだけサポートします。 同じデバイス ID の代わりに新しい MQTT 接続を実行すると、IoT Hub によって既存の接続が削除され、400027 ConnectionForcefullyClosedOnNewConnection が IoT Hub ログに記録されます

  • メッセージ本文に基づいてメッセージをルーティングするには、まずプロパティ 'contentType' (ct) を MQTT トピックの末尾に追加し、その値を次の例に示すように application/json;charset=utf-8 に設定する必要があります。 メッセージのプロパティまたはメッセージ本文に基づいてメッセージをルーティングする方法の詳細については、IoT Hub メッセージ ルーティングのクエリ構文に関するドキュメントを参照してください。

    devices/{device-id}/messages/events/$.ct=application%2Fjson%3Bcharset%3Dutf-8

詳細については、「IoT Hub で device-to-cloud および cloud-to-device メッセージを送信する」を参照してください。

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

IoT Hub からメッセージを受信するには、デバイスで、devices/{device-id}/messages/devicebound/#トピック フィルターとして使用してサブスクライブする必要があります。 トピック フィルター内の複数レベルのワイルドカード # は、デバイスがトピック名のその他のプロパティを受信できるようにするためにのみ使用されます。 IoT Hub では、# または ? ワイルドカードを使用してサブトピックをフィルター処理できません。 IoT Hub はパブリッシャーとサブスクライバー間の汎用メッセージング ブローカーではないため、ドキュメント化されたトピック名とトピック フィルターのみをサポートします。 デバイスは、一度に 5 つのトピックのみをサブスクライブできます。

デバイスは、devices/{device-id}/messages/devicebound/# トピック フィルターで表されるデバイス固有のエンドポイントへのサブスクライブが成功するまで、IoT Hub からメッセージを受信することはありません。 サブスクリプションが確立した後、デバイスは、サブスクリプション後に送信された cloud-to-device メッセージのみを受信します。 デバイスが CleanSession フラグを 0 に設定した状態で接続している場合、サブスクリプションは複数のセッションで保持されます。 この場合、次回 CleanSession 0 の状態で接続したときに、デバイスは、切断中にデバイスに対して送信された未処理メッセージを受信します。 ただし、デバイスが CleanSession フラグを 1 に設定して使用している場合は、デバイス エンドポイントにサブスクライブするまで、デバイスが IoT Hub からメッセージを受信することはありません。

IoT Hub では、メッセージはトピック名devices/{device-id}/messages/devicebound/ で配信されます。メッセージの プロパティがある場合は、devices/{device-id}/messages/devicebound/{property-bag} で配信されます。 {property-bag} には、メッセージ プロパティの URL でエンコードされた値/キーのペアが含まれています。 プロパティ バッグに含められるのは、アプリケーション プロパティとユーザーが設定可能なシステム プロパティ (messageIdcorrelationId など) のみです。 システム プロパティの名前にはプレフィックス $ が付きます。アプリケーション プロパティでは、プレフィックスのない元々のプロパティ名が使用されます。 プロパティ バッグの形式の詳細については、「デバイスからクラウドへのメッセージの送信」を参照してください。

クラウドからデバイスへのメッセージでは、プロパティ バッグの値は次の表に示されるように表記します。

プロパティ値 [表記] 説明
null key プロパティ バッグにキーのみが含まれる
空の文字列 key= キーの後に等号が続き、値はない
null 以外の空でない値 key=value キーの後に等号と値が続く

以下の例では、次の 3 つのアプリケーション プロパティを含むプロパティ バッグを示します。値が nullprop1、空の文字列 ("") の prop2、"a string" という値の prop3

/?prop1&prop2=&prop3=a%20string

デバイス アプリが QoS 2 を使用してトピックをサブスクライブしている場合、IoT Hub は SUBACK パケットに最大の QoS レベル 1 を許可します。 その後、IoT Hub は QoS 1 を使用してデバイスにメッセージを配信します。

デバイス ツインのプロパティの取得

まずデバイスが、操作の応答を受信するために、$iothub/twin/res/# にサブスクライブします。 次に、デバイスは、空のメッセージをトピック $iothub/twin/GET/?$rid={request id} に送信します (要求 ID に値を指定します)。 その後サービスが、要求と同じ 要求 ID を使用して、トピック $iothub/twin/res/{status}/?$rid={request-id} のデバイス ツイン データを含む応答メッセージを送信します。

要求 ID にはメッセージ プロパティ値として有効な任意の値を指定できます。ステータスは、整数として検証されます。 詳細については、「IoT Hub で device-to-cloud および cloud-to-device メッセージを送信する」を参照してください。

次の応答の例で示されているように、応答本文にはデバイス ツインのプロパティ セクションが含まれます。

{
    "desired": {
        "telemetrySendFrequency": "5m",
        "$version": 12
    },
    "reported": {
        "telemetrySendFrequency": "5m",
        "batteryLevel": 55,
        "$version": 123
    }
}

使用できる状態コードは次のとおりです。

Status 説明
200 Success
429 要求が多すぎます (スロットルされました)。 詳細については、IoT Hub のスロットリングに関する記事を参照してください。
5** サーバー エラー

詳細については、「IoT Hub のデバイス ツインの理解と使用」を参照してください。

デバイス ツインの報告されるプロパティの更新

報告されたプロパティを更新するために、デバイスでは、指定した MQTT トピック経由の公開を介して IoT Hub に要求が発行されます。 IoT Hub は、要求を処理した後、別のトピックへの公開を介して、更新操作の成功または失敗の状態を応答します。 デバイスでは、そのツイン更新要求の結果を通知するために、このトピックをサブスクライブできます。 この種類の要求/応答のやり取りを MQTT で実装するために、その更新要求内でデバイスによって最初に提供される要求 ID ($rid) の概念を使用します。 この要求 ID はIoT Hub からの応答にも含まれ、デバイスが以前の特定の要求に応答を関連付けることができるようにします。

IoT Hub のデバイス ツインで報告されるプロパティをデバイスが更新する手順を次に示します。

  1. デバイスはまず、$iothub/twin/res/# トピックをサブスクライブして、IoT Hub から操作の応答を受信する必要があります。

  2. デバイスは、デバイス ツインの更新を含むメッセージを、$iothub/twin/PATCH/properties/reported/?$rid={request-id} トピックに送信します。 このメッセージには、要求 ID の値が含まれます。

  3. サービスは、トピック $iothub/twin/res/{status}/?$rid={request-id} で報告されたプロパティ コレクションの新しい ETag 値を含む応答メッセージを送信します。 この応答メッセージでは、要求と同じ要求 ID が使われます。

要求メッセージの本文には、報告されるプロパティの新しい値を含む JSON ドキュメントが含まれています。 JSON ドキュメントの各メンバーは、デバイス ツインのドキュメントの対応するメンバーを更新または追加します。 メンバーを null に設定した場合、メンバーは包含オブジェクトから削除されます。 次に例を示します。

{
    "telemetrySendFrequency": "35m",
    "batteryLevel": 60
}

使用できる状態コードは次のとおりです。

Status 説明
204 成功 (コンテンツは返されません)
400 正しくない要求。 無効な形式の JSON
429 要求が多すぎます (スロットル)。IoT Hub スロットルに関するページを参照してください。
5** サーバー エラー

次の Python のコード スニペットは、Paho MQTT クライアントを使用した MQTT 経由でのツインの報告されたプロパティの更新プロセスを示しています。

from paho.mqtt import client as mqtt

# authenticate the client with IoT Hub (not shown here)

client.subscribe("$iothub/twin/res/#")
rid = "1"
twin_reported_property_patch = "{\"firmware_version\": \"v1.1\"}"
client.publish("$iothub/twin/PATCH/properties/reported/?$rid=" +
               rid, twin_reported_property_patch, qos=0)

前のコード スニペット内のツインの報告されたプロパティの更新プロセスが成功すると、IoT Hub からの発行メッセージには次のトピックが含まれます: $iothub/twin/res/204/?$rid=1&$version=6。ここで、204 は成功を示す状態コードで、$rid=1 はコード内のデバイスによって提供された要求 ID に対応します。$version は、更新後のデバイス ツインの報告されたプロパティ セクションのバージョンに対応します。

詳細については、「IoT Hub のデバイス ツインの理解と使用」を参照してください。

必要なプロパティの更新通知の受信

デバイスが接続されると、IoT Hub は、ソリューション バックエンドによって実行された更新の内容を含むトピック $iothub/twin/PATCH/properties/desired/?$version={new-version} に通知を送信します。 次に例を示します。

{
    "telemetrySendFrequency": "5m",
    "route": null,
    "$version": 8
}

プロパティの更新の場合、値 null は、JSON オブジェクト メンバーが削除されることを意味します。 また、$version は、ツインの目的のプロパティ セクションの新しいバージョンを示します。

重要

IoT Hub は、デバイスが接続されている場合にのみ変更通知を生成します。 IoT Hub とデバイス アプリ間で目的のプロパティが同期された状態を保つには、デバイス再接続フローを必ず実装してください。

詳細については、「IoT Hub のデバイス ツインの理解と使用」を参照してください。

ダイレクト メソッドへの応答

最初に、デバイスは $iothub/methods/POST/# にサブスクライブする必要があります。 IoT Hub は、有効な JSON または空の本文と共にメソッド要求をトピック $iothub/methods/POST/{method-name}/?$rid={request-id} に送信します。

応答するために、デバイスは、有効な JSON を含むメッセージまたは 空の本文をトピック $iothub/methods/res/{status}/?$rid={request-id} に送信します。 このメッセージでは、要求 IDは、要求メッセージ内のものと一致する必要があり、ステータスは整数である必要があります。

詳細については、「IoT Hub からのダイレクト メソッドの呼び出しについて」を参照してください。

次のステップ

MQTT の使用の詳細については、以下を参照してください。

IoT デバイス SDKS の使用の詳細については、以下を参照してください。

IoT Hub のデプロイの計画に関する詳細については、以下をご覧ください。