この記事では、デバイスが MQTT プロトコルを使用して Azure IoT Hub と通信する方法について説明します。 IoT Hub デバイス エンドポイントは、次を使用したデバイス接続をサポートします。
- ポート 8883 上の MQTT v3.1.1
- ポート 443 の WebSocket 経由の MQTT v3.1.1
注
この記事で言及されている一部の機能 (cloud-to-device メッセージング、デバイス ツイン、デバイス管理など) は、IoT Hub の Standard レベルだけで使用することができます。 Basic および Standard/Free IoT Hub レベルの詳細については、「ソリューションに適した IoT Hub レベルとサイズを選択する」を参照してください。
IoT Hub とのデバイス通信はすべて、TLS を使用してセキュリティで保護する必要があります。 そのため、IoT Hub では、ポート 1883 経由の安全でない MQTT 接続はサポートされていません。
IoT Hub と Event Grid での MQTT サポートの比較
IoT Hub はフル機能の MQTT ブローカーではないため、MQTT v3.1.1 標準で指定されているすべての動作をサポートしているわけではありません。 ソリューションでクラウドホスト型 MQTT ブローカーが必要な場合は、代わりに Azure Event Grid を使用します。 Event Grid では、パブリッシュ/サブスクライブ メッセージング モデルを使用して、柔軟な階層構造のトピックで MQTT クライアント間の双方向通信を可能にします。 さらに処理するために、MQTT メッセージを他の Azure サービスまたはカスタム エンドポイントにルーティングすることもできます。
次の表は、2 つのサービス間の MQTT サポートにおける現在の違いをまとめたものです。
IoT ハブ | イベントグリッド |
---|---|
デバイスとクラウド アプリ間の緊密な結合を備えたクライアント サーバー モデル。 | パブリッシャーとサブスクライバーを分離するパブリッシュ サブスクライブ モデル。 |
MQTT v3.1.1 の制限付き機能のサポート。 | MQTT v3.1.1 および v5 プロトコルのサポート。 |
静的で定義済みのトピック。 | ワイルドカードをサポートするカスタム階層型トピック。 |
クラウドからデバイスへのブロードキャストやデバイス間通信はサポートされません。 | device-to-cloud の、ファンアウトの高い cloud-to-device ブロードキャスト、および device-to-device 通信パターンをサポートします。 |
最大メッセージ サイズは 256 KB です。 | 最大メッセージ サイズは 512 KB です。 |
IoT Hub に接続する
デバイスでは、MQTT プロトコルを使用し、次のいずれかのオプションを利用して IoT ハブに接続できます。
- Azure IoT デバイス SDK。
- 直接的な MQTT プロトコル。
多くの企業および教育用ファイアウォールは、MQTT ポート (TCP ポート 8883) をブロックします。 ファイアウォールでポート 8883 を開くことができない場合は、WebSocket 経由で MQTT を使用します。 Mqtt over WebSocket はポート 443 を介して通信します。これは、ほぼ常に開いています。 Azure IoT SDK を使用しているときに MQTT プロトコルと MQTT over WebSocket プロトコルを指定する方法については、「デバイス SDK の使用」を参照してください。
デバイス SDK を使用する
MQTT プロトコルをサポートする Azure IoT デバイス 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 への接続を確立するために使用するパラメーターを示しています。
言語 | MQTT プロトコルのパラメーター | MQTT over WebSockets プロトコルのパラメーター |
---|---|---|
Node.js | azure-iot-device-mqtt.Mqtt | azure-iot-device-mqtt.MqttWs |
ジャワ | 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 を使用するときに、WebSocket プロトコル経由で MQTT を指定する方法を示しています。
var Client = require('azure-iot-device').Client;
var Protocol = require('azure-iot-device-mqtt').MqttWs;
var client = Client.fromConnectionString(deviceConnectionString, Protocol);
次のフラグメントは、Azure IoT Python SDK を使用するときに、WebSockets プロトコル経由で MQTT を指定する方法を示しています。
from azure.iot.device.aio import IoTHubDeviceClient
device_client = IoTHubDeviceClient.create_from_connection_string(deviceConnectionString, websockets=True)
重要
この記事では、Shared Access Signature (対称キー認証とも呼ばれます) を使用してデバイスを接続する手順について説明しています。 この認証方法はテストと評価には便利ですが、X.509 証明書を使用してデバイスを認証する方が安全なアプローチです。 詳細については、 接続セキュリティ > IoT ソリューションのセキュリティのベスト プラクティスに関するページを参照してください。
既定のキープアライブ タイムアウト
IoT ハブ接続へのクライアント接続を確実に有効にするには、サービスとクライアントの両方が定期的に キープアライブ ping を送信します。 いずれかのデバイス SDK を使用する場合、クライアントは次の表に定義されている間隔でキープアライブ メッセージを送信します。
言語 | 既定のキープアライブ間隔 | 構成可能 |
---|---|---|
Node.js | 180 秒 | いいえ |
ジャワ | 230 秒 | いいえ |
C | 240 秒 | Yes (はい) |
C# | 300 秒* | Yes (はい) |
Python(プログラミング言語) | 60 秒 | Yes (はい) |
*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 秒) に制限されます。
たとえば、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 に変更する場合は、次の項目を確認します。
AMQP では、MQTT 接続を終了するときに、多くの条件のエラーが返されます。 その結果、例外処理ロジックの変更が必要になる場合があります。
MQTT では、cloud-to-device メッセージを受信したときの拒否操作はサポートされません。 バックエンド アプリケーションがデバイス アプリケーションから応答を受信する必要がある場合は、 ダイレクト メソッドの使用を検討してください。
Python SDK では AMQP はサポートされていません。
デバイスから MQTT プロトコルを直接使用する
デバイスで IoT デバイス SDK を使用できない場合でも、ポート 8883 の MQTT プロトコルを使用してパブリック デバイス エンドポイントに接続できます。
重要
この記事では、Shared Access Signature (対称キー認証とも呼ばれます) を使用してデバイスを接続する手順について説明しています。 この認証方法はテストと評価には便利ですが、X.509 証明書を使用してデバイスを認証する方が安全なアプローチです。 詳細については、 接続セキュリティ > IoT ソリューションのセキュリティのベスト プラクティスに関するページを参照してください。
CONNECT パケットの場合、デバイスでは次の値を使用する必要があります。
ClientId フィールドには、deviceId を使用します。
[ユーザー名] フィールドには、
{iotHub-hostname}/{device-id}/?api-version=2021-04-12
を使用します。{iotHub-hostname}
は IoT Hub の完全なCName
です。たとえば、IoT ハブの名前が contoso.azure-devices.net され、デバイスの名前が MyDevice01 の場合、[ Username ] フィールドには次のものが含まれます。
contoso.azure-devices.net/MyDevice01/?api-version=2021-04-12
予期しない動作を回避するには、フィールドに api-version を含めます。
[Password] フィールドには、SAS トークンを使用します。 次のスニペットは、SAS トークンの形式を示しています。
SharedAccessSignature sig={signature-string}&se={expiry}&sr={URL-encoded-resourceURI}
注
X.509 証明書認証を使用する場合、SAS トークン パスワードは必要ありません。 詳細については、「 チュートリアル: テスト用の証明書を作成してアップロードする 」を参照し、 TLS 構成セクションのコード手順に従います。
SAS トークンを生成する方法の詳細については、「Shared Access Signature を使用して IoT Hub へのアクセスを制御する」の「デバイスとして SAS トークンを使用する」セクションを参照してください。
Visual Studio Code 用の Azure IoT Hub 拡張機能または CLI 拡張機能コマンド az iot hub generate-sas-token を使用して SAS トークンを生成することもできます。 その後、テスト目的で 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 メッセージを指定できます。 デバイス アプリケーションでは、Will トピック名としてdevices/{device-id}/messages/events/
またはdevices/{device-id}/messages/events/{property-bag}
を使用して、テレメトリ メッセージとして転送される Will メッセージを定義する必要があります。 この場合、ネットワーク接続が閉じている一方で、DISCONNECT パケットがデバイスからまだ受信されていない場合、IoT Hub は、CONNECT パケットで提供される Will メッセージをテレメトリ チャネルに送信します。 テレメトリ チャネルは、既定のイベント エンドポイントにすることも、IoT Hub ルーティングで定義されるカスタム エンドポイントにすることもできます。 メッセージには iothub-MessageType プロパティが含まれており、その値には Will が割り当てられています。
モジュールから MQTT プロトコルを直接使用する
モジュール ID を使用して MQTT 経由で IoT Hub に接続することもできます。 この方法はデバイスとしての接続に似ていますが、次の値を使用する必要があります。
クライアント ID を
{device-id}/{module-id}
に設定します。ユーザー名とパスワードで認証する場合は、ユーザー名を
<hubname>.azure-devices.net/{device_id}/{module_id}/?api-version=2021-04-12
に設定します。 SAS を使用している場合は、モジュール ID に関連付けられている SAS トークンをパスワードとして使用します。利用統計情報を公開するためのトピックとして
devices/{device-id}/modules/{module-id}/messages/events/
を使用します。devices/{device-id}/modules/{module-id}/messages/events/
を Will トピックとして使用します。メッセージを受信するためのトピックとして
devices/{device-id}/modules/{module-id}/#
を使用します。ツイン GET と PATCH のトピックは、モジュールとデバイスで同じです。
ツインの状態に関するトピックは、モジュールとデバイスで同じです。
モジュールでの MQTT の使用の詳細については、 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 を使用して、デバイス SDK を使用せずに IoT デバイス クライアントを開発する」を参照してください。
TLS の構成
MQTT プロトコルを直接使用するには、クライアントが TLS 1.2 経由で接続する必要があります。 この手順をスキップしようとすると、接続エラーで失敗します。
TLS 接続を確立するには、Azure が使用する DigiCert グローバル ルート G2 ルート証明書をダウンロードして参照することが必要になる場合があります。 この証明書の詳細については、DigiCert の Web サイトを参照してください。
次の例では、 Paho MQTT ライブラリの Python バージョンを使用して、この構成を実装する方法を示します。
最初に、コマンドライン環境から 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 証明書を使用した ID の認証」の「X.509CA 証明書の取得」セクションを参照してください。
# 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 プロトコルでのクエリ文字列と同じエンコードを使用します。
D2C メッセージを Azure Storage アカウントにルーティングしていて、JSON エンコードを使用する場合は、前のメモで説明した{property_bag}
の一部として、$.ct=application%2Fjson&$.ce=utf-8
を含むコンテンツ タイプとコンテンツ エンコードの情報を指定する必要があります。
注
これらの属性の形式はプロトコル固有です。 IoT Hub は、これらの属性を対応するシステム プロパティに変換します。 詳細については、「IoT Hub メッセージ ルーティングのクエリ構文」の「システム プロパティ」セクションを参照してください。
次の一覧は、IoT Hub MQTT の実装固有の動作をまとめたものです。
IoT Hub では、QoS 2 メッセージはサポートされていません。 デバイス アプリケーションが QoS 2 でメッセージを発行すると、IoT Hub はネットワーク接続を閉じます。
IoT Hub では、メッセージ
Retain
保持されません。 デバイスで RETAIN フラグを 1 に設定してメッセージが送信されると、IoT Hub によってそのメッセージに mqtt-retain アプリケーション プロパティが追加されます。 この場合、保持されたメッセージを保持する代わりに、IoT Hub によってバックエンド アプリケーションに渡されます。IoT Hub は、デバイスごとにアクティブな MQTT 接続を 1 つだけサポートします。 同じデバイス ID に代わって新しい MQTT 接続を使用すると、IoT Hub は既存の接続を削除し、 ConnectionForcefullyClosedOnNewConnection 400027 IoT Hub ログに書き込みます。
メッセージ本文に基づいてメッセージをルーティングするには、まず MQTT トピックの末尾にプロパティ
ct
を追加し、その値を次の例に示すようにapplication/json;charset=utf-8
に設定します。 メッセージのプロパティまたはメッセージ本文に基づいてメッセージをルーティングする方法の詳細については、IoT Hub メッセージ ルーティングのクエリ構文に関するドキュメントを参照してください。devices/{device-id}/messages/events/$.ct=application%2Fjson%3Bcharset%3Dutf-8
詳細については、「 IoT Hub を使用したメッセージの送受信」を参照してください。
cloud-to-device メッセージを受信する
IoT Hub からメッセージを受信するには、デバイスで、devices/{device-id}/messages/devicebound/#
をトピック フィルターとして使用してサブスクライブする必要があります。 トピック フィルターに含まれる複数レベルのワイルドカード #
を使用すると、デバイスはトピック名にさらに多くのプロパティを受け取ります。 IoT Hub では、サブトピックをフィルター処理するための #
または ?
ワイルドカードの使用は許可されません。 IoT Hub は汎用の発行/サブスクライブ メッセージング ブローカーではなく、文書化されたトピック名とトピック フィルターのみをサポートします。 デバイスは、一度に 5 つのトピックのみをサブスクライブできます。
デバイスは、 devices/{device-id}/messages/devicebound/#
トピック フィルターで表されるデバイス固有のエンドポイントに正常にサブスクライブするまで、IoT Hub からメッセージを受信しません。 サブスクリプションが確立されると、デバイスは、サブスクリプションの終了後に送信されたクラウドからデバイスへのメッセージを受信します。 デバイスが 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 でエンコードされた値/キーのペアが含まれています。 プロパティ バッグに含められるのは、アプリケーション プロパティとユーザーが設定可能なシステム プロパティ (messageId、correlationId など) のみです。 システム プロパティの名前にはプレフィックス $ が付きます。アプリケーション プロパティでは、プレフィックスのない元のプロパティ名が使用されます。 プロパティ バッグの形式の詳細については、「デバイスからクラウドへのメッセージの送信」を参照してください。
クラウドからデバイスへのメッセージでは、プロパティ バッグの値は次の表に示されるように表記します。
プロパティ値 | [表記] | 説明 |
---|---|---|
null |
key |
プロパティ バッグにキーのみが含まれる |
空の文字列 | key= |
キーの後に等号が続き、値はない |
null 以外の空でない値 | key=value |
キーの後に等号と値が続く |
以下の例では、次の 3 つのアプリケーション プロパティを含むプロパティ バッグを示します。値が null
の prop1、空の文字列 ("") の 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 を使用したメッセージの送受信」を参照してください。
次の応答の例で示されているように、応答本文にはデバイス ツインのプロパティ セクションが含まれます。
{
"desired": {
"telemetrySendFrequency": "5m",
"$version": 12
},
"reported": {
"telemetrySendFrequency": "5m",
"batteryLevel": 55,
"$version": 123
}
}
使用できる状態コードは次のとおりです。
ステータス | 説明 |
---|---|
200 | Success |
429 | 要求が多すぎます (スロットルされました)。 詳細については、「IoT Hub のクォータと調整」を参照してください。 |
5** | サーバー エラー |
詳細については、「IoT Hub のデバイス ツインの理解と使用」を参照してください。
デバイス ツインの報告されるプロパティの更新
報告されたプロパティを更新するために、デバイスは指定された MQTT トピックに発行して IoT Hub に要求を発行します。 IoT Hub は要求を処理した後、別のトピックに発行することで、更新操作の成功または失敗の状態で応答します。 デバイスは、ツイン更新要求の結果に関する通知を受信するために、このトピックをサブスクライブできます。 MQTT でこの種類の要求/応答対話を実装するために、デバイスは最初の更新要求で要求 ID ($rid
) を提供します。 その後、この要求 ID は IoT Hub からの応答に含まれるので、デバイスは応答を正しい要求に関連付けることができます。
IoT Hub のデバイス ツインで報告されるプロパティをデバイスが更新する手順を次に示します。
デバイスは、最初に
$iothub/twin/res/#
トピックをサブスクライブして、IoT Hub からの応答を受信できるようにします。デバイスは、デバイス ツインの更新を含むメッセージを、
$iothub/twin/PATCH/properties/reported/?$rid={request-id}
トピックに送信します。 このメッセージには、要求 ID の値が含まれます。サービスは、トピック
$iothub/twin/res/{status}/?$rid={request-id}
で報告されたプロパティ コレクションの新しい ETag 値を含む応答メッセージを送信します。 この応答メッセージでは、要求と同じ要求 ID が使われます。
要求メッセージの本文には、報告されるプロパティの新しい値を含む JSON ドキュメントが含まれています。 JSON ドキュメントの各メンバーは、デバイス ツインのドキュメントの対応するメンバーを更新または追加します。 メンバーを null
に設定した場合、メンバーは包含オブジェクトから削除されます。 次に例を示します。
{
"telemetrySendFrequency": "35m",
"batteryLevel": 60
}
使用できる状態コードは次のとおりです。
ステータス | 説明 |
---|---|
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 の使用の詳細については、以下を参照してください。