Amazon Web Services ブログ

AWS IoT Core が新たに対応した、柔軟なアーキテクチャ構築に役立つ MQTTv5 機能のご紹介

この記事は Introducing new MQTTv5 features for AWS IoT Core to help build flexible architecture patterns の日本語訳です。

イントロダクション

AWS IoT Core が、大規模に展開されたデバイスの通信を強化し、デバイスのメッセージングパターンを革新する MQTTv5 の機能をサポートしたことを発表でき嬉しく思っています。AWS IoT Core が新旧両方のバージョンをシームレスに統合し、移行中の異なるデプロイをサポートしますので、既に MQTTv3.1.1 を導入しているお客様は新しい MQTTv5 機能を利用することが可能です。このブログ記事では、より柔軟で効率的な IoT アーキテクチャパターンを設計する方法を示すために、実際の IoT シナリオにおけるちょっとした実装例とともに MQTTv5 の機能の一部を要約しています。また、AWS IoT Core を実行している既存のデバイス群に、 MQTTv5 がどのように新しい可能性をもたらすかも併せてご紹介します。

MQTTv3.1.1 の成功の後、 OASIS ( Organization for the Advancement of Structured Information Standards )は、スケーラビリティと大規模システム向けの強化を主な目標として仕様を改善してきました。これらの機能強化により、 2019 年 3 月に新規格として MQTT バージョン 5 ( MQTTv5 )がリリースされました。詳細については、 MQTT 5 の対応機能ドキュメントページをご参照ください。

前提条件

  • AWS アカウント
  • 開発環境、または AWS CLI と Python 3 がインストールされたコンピューター

はじめに

  1. サンプルスクリプトにアクセス: このブログ記事のサンプルスクリプトは、 git リポジトリ aws-samples/aws-iot-mqttv5-examples に格納されています。 git リポジトリのリンクに移動して、開発環境にダウンロードしてください。
  2.  MQTT クライアントライブラリをダウンロード:このブログ記事では、オープンソースの Eclipse Paho™ MQTT Python クライアントライブラリを使用します。
    1.  pip がインストールされていない場合は、以下のコマンドを実行してインストールします。
      python -m ensurepip --upgrade
    2. 以下のコマンドを実行して、 paho-mqtt ライブラリをインストールします。
      pip install paho-mqtt
      paho-mqtt source code repository から、 paho-mqtt のソースコードリポジトリや、他のクライアントのインストールオプションも確認できます。
  3.  AWS IoT Core のデバイスデータエンドポイントを取得: AWS IoT Core デバイスデータエンドポイントは、あなたの AWS アカウントのリージョン固有の AWS IoT Core エンドポイントです。あなたのデバイスはこのエンドポイントに接続します。
    1. AWS IoT Core コンソールに移動します。
    2. 左側のナビゲーションメニューで、[設定]を選択します。
    3. デバイスデータエンドポイントの下で、[エンドポイント] をコピーします。
      後のセクションで、サンプルのスクリプトのパラメータとしてこのエンドポイントが必要になります。
  4. AWS IoT モノのリソースを作成し、証明書を取得、配置します:
    1.  AWS IoT の「モノ」を作成し、デバイス証明書をダウンロードします。
      1. AWS IoT リソースの作成ページの指示に従って、 Amazon Root certificate authority ( CA ) 署名付きクライアント証明書を使用します。
      2. ルートまたは中間認証局 ( CA ) を選択して AWS IoT Core を使用する場合、独自のクライアント証明書を作成するページの手順に従ってください。
    2.  AWS 本ブログのスクリプト例では、デフォルトで「 certificates 」フォルダに証明書が格納されていますが、 --certificates-path パラメータで上書きすることも可能です。
      1. 証明書ファイルの名前を ” client-cert.pem ” に変更します。
      2. ダウンロードしたルート証明書のファイル名を ” AmazonRootCA1.pem ” に変更します。
      3. ダウンロードした秘密鍵の名前を ” private-key.pem ” に変更します。

      これで、 AWS IoT Core がサポートする MQTTv5 新機能のテストを開始する準備が整いました。

1. リクエスト/レスポンスパターンによる透明性の高いメッセージング

リクエスト/レスポンス メッセージパターンは、クライアントの要求に対する応答を非同期的に追跡する方法の一つです。これは MQTTv5 から新たに実装された仕組みで、パブリッシャーが特定のメッセージに対するレスポンスのトピックの指定を可能にします。そのため、サブスクライバーはリクエストを受け取ると同時に、レスポンス送信先のトピックも受信します。また、リクエストやデバイス識別パラメータなどのパケットの追跡を可能にするような相関データフィールドもサポートしています。

例えばリクエスト/レスポンスパターンが役に立つユースケースとして、スマートロックとそのアプリケーションが挙げられます。ユーザーがモバイルアプリを介してドアロックを操作し、 MQTT メッセージを送信してロックを開閉するとします。アプリとドアロックの間でやり取りされるメッセージはすべて承認を要し、パケットが配信されたかどうか追跡可能である必要があります。また、ドアロックコマンドは、リクエスト元のユーザー ID などのコンテキストとともに渡す必要があります。

この機能を試すには、「はじめに」のステップでダウンロードした git リポジトリにあるスクリプトファイル./aws-iot-mqttv5-examples/01_request_response_example.pyを使用します。また「はじめに」の手順で取得したデバイスデータエンドポイントを--endpointパラメーターで指定して下さい。(下記のサンプルコマンドの<AWS-IoT-Device-Data-Endpoint>を、ご自身の環境のエンドポイント、例えば abcd123456z-ats.iot.region.amazonaws.com に置き換えて実行して下さい。)

$ python3 01_request_response_example.py --endpoint <AWS-IoT-Device-Data-Endpoint>
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'TestThing01' properties=None
DEBUG:__main__:Received SUBACK: 4, "request_id": "eb1bd30a-c7e6-42a4-9e00-d5baee89f65c"}'], ... (4 bytes)
DEBUG:root:Received a message on topic: 'home07/main_door/lock', payload: 'LOCK'
DEBUG:root:Main door LOCK request with parameters: 'b'{"user_profile_id": 4, "request_id": "eb1bd30a-c7e6-42a4-9e00-d5baee89f65c"}''
DEBUG:__main__:Sending PUBLISH (d0, q0, r0, m3), 'b'home07/main_door/status'', properties=[CorrelationData : b'{"user_profile_id": 4, "request_id": "eb1bd30a-c7e6-42a4-9e00-d5baee89f65c"}'], ... (25 bytes)
DEBUG:__main__:Received PUBLISH (d0, q0, r0, m0), 'home07/main_door/status', properties=[CorrelationData : b'{"user_profile_id": 4, "request_id": "eb1bd30a-c7e6-42a4-9e00-d5baee89f65c"}'], ... (25 bytes)
DEBUG:root:Received a message on topic: 'home07/main_door/status', payload: 'USER_IS_NOT_AUTHENTICATED'
DEBUG:root:Main door status: 'USER_IS_NOT_AUTHENTICATED'' with parameters: 'b'{"user_profile_id": 4, "request_id": "eb1bd30a-c7e6-42a4-9e00-d5baee89f65c"}''


図:ドアロックモバイルアプリにおけるリクエスト/レスポンスメッセージングパターン

  1. モバイルアプリである MQTT クライアントはレスポンストピックをサブスクライブします。次に、施錠リクエストパッケージがhome07/main_door/lock トピックに公開されます。期待されるレスポンストピックは home07/main_door/status で、相関データオブジェクトにはリクエスターとして user_profile_idrequest_id が含まれます。
  2. ドアロックが home07/main_door/lock で施錠要求を受け取ると、レスポンストピックと相関データを含む MQTT パケットを処理します。
  3. ドアロックが施錠決定を行い、相関データのトピックにパブリッシュすることでレスポンスを返却します。
  4. サブスクライバー関数は home07/main_door/status でレスポンスを受け取り、その決定を相関データとともにログに記録します。user_profile_idrequest_id を使用したリクエスターにより、さらなるアクションの実行につなげることも可能です。

2. ユーザープロパティ機能による、より柔軟なデバイスメッセージング

ユーザープロパティ機能を使用すると、接続されたデバイスやサブスクライバーとなるアプリケーションが、パブリッシュや接続を含むカスタムのキーと値のペアを MQTT パケットに追加することで、カスタム情報を渡すことができます。この機能は HTTP ヘッダーと同様の機能を提供し、ヘッダーの合計サイズが 8 KB を超えない限り使用できます。

ユーザープロパティ機能のユースケースとして、例えばマルチベンダーのセンサーデプロイにおけるユースケースが挙げられます。異なるベンダーの複数のセンサーが産業用またはスマートホーム用アプリケーションに導入されているケースを考えてみましょう。このような場合、個々のセンサーは、ユーザープロパティで指定されている様々なエンコーディングを使用してデータを送信できます。ユーザープロパティの値に応じて、メッセージのサブスクライバーは特定のアクションを実行してメッセージを処理することができます。

この機能を試すには、「はじめに」のステップでダウンロードした git リポジトリにあるスクリプトファイル /aws-iot-mqttv5-examples/02_user_properties_example.py を使用します。またまた「はじめに」の手順で取得したデバイスデータエンドポイントを --endpoint パラメーターで指定して下さい。(下記のサンプルコマンドの <AWS-IoT-Device-Data-Endpoint> を、ご自身の環境のエンドポイント、例えば abcd123456z-ats.iot.region.amazonaws.com に置き換えて実行して下さい。)

$ python3 02_user_properties_example.py --endpoint <AWS-IoT-Device-Data-Endpoint>
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'TestThing02' properties=NonerandX-rev8.2')]], ... (8 bytes)
DEBUG:__main__:Sending PUBLISH (d0, q0, r0, m4), 'b'sensors/gateway01/sensor03'', properties=None, ... (4 bytes)
DEBUG:__main__:Received PUBLISH (d0, q0, r0, m0), 'sensors/gateway01/sensor01', properties=[UserProperty : [('Content-Type', 'text/plain'), ('Hardware-Revision', 'brandX-rev1.17c')]], ... (4 bytes)
DEBUG:root:Received a message on topic: 'sensors/gateway01/sensor01'
DEBUG:root:Message has user properties: [('Content-Type', 'text/plain'), ('Hardware-Revision', 'brandX-rev1.17c')]
DEBUG:root:Received message with Content-Type: 'text/plain'
DEBUG:root:Plain text payload: '23.4'
DEBUG:__main__:Received PUBLISH (d0, q0, r0, m0), 'sensors/gateway01/sensor02', properties=[UserProperty : [('Content-Type', 'base64'), ('Hardware-Manufacturer', 'brandX-rev8.2')]], ... (8 bytes)
DEBUG:root:Received a message on topic: 'sensors/gateway01/sensor02'
DEBUG:root:Message has user properties: [('Content-Type', 'base64'), ('Hardware-Manufacturer', 'brandX-rev8.2')]
DEBUG:root:Received message with Content-Type: 'base64'
DEBUG:root:Raw payload: 'MjMuNw==', Decoded base64 payload: '23.7'
DEBUG:__main__:Received PUBLISH (d0, q0, r0, m0), 'sensors/gateway01/sensor03', properties=[], ... (4 bytes)
DEBUG:root:Received a message on topic: 'sensors/gateway01/sensor03'
DEBUG:root:No User Property specified, raw payload: '24.4'

このサンプルスクリプトでは、異なるメーカーの 3 つのセンサーが、異なるデータエンコーディングを使用してトピックにパブリッシュする様子を示しています。サブスクライバーは、 Content-Type ユーザープロパティ値を評価することにより、センサーの生値と base64 でエンコードされたセンサー値を処理します。

AWS IoT Core のトピックルールでユーザープロパティを含む MQTT パケットを処理する

AWS IoT Core のトピックルール機能を使用すると、 AWS IoT Core から各種 AWS サービスに MQTT メッセージを転送する為のルールを設定することができます。また、AWS IoTルールのSQL文を使って処理ロジックを定義することができます。これにより、各データスキーマに対応した処理を実装することで、複数のベンダーにまたがるデータを AWS IoTトピックルールに基づいて標準化されたベンダーに依存しない形に変換し、任意の AWS サービスに転送することができます。

SELECT CASE get_user_property("Content-Type")
WHEN "base64" THEN decode(decode(encode(*, 'base64'), 'base64'), 'base64')
ELSE decode(encode(*, 'base64'), 'base64') END as sensor_value,
FROM sensors/#'

AWS IoT Core トピックルール機能には、ルール定義内の MQTT パケットのユーザープロパティ値にアクセスできる get_user_property() 関数が用意されています。上記のルール SQL は、base64 でエンコードされている場合、base64 デコードを適用します。トピックルールの作成方法は AWS IoT ルールの作成ドキュメントページをご参照ください。また、AWS IoT SQL リファレンスバイナリペイロードの使用のドキュメントページもご確認ください。

3. トピックエイリアス機能でデバイスの帯域をより効率的に利用する

セルラー IoT デバイスとセンサーは、モバイルネットワークを使用してバックエンドサービスと通信します。これらのデバイスは、従量制のデータサービスのため、ほとんどの場合、可能な限り低い帯域幅で動作するように設計されています。セルラー接続センサーデバイスが農地で動作するように設計されていると仮定すると、それらは少ないデータ量で通信し、かつ長いバッテリー寿命で動作することが期待されます。また、データパケットが大きいほど、消費電力も大きくなる傾向があります。これらのセンサーは数バイトのセンシング値しかパブリッシュしないことを考えると、長い MQTT トピックはデバイスメッセージングの際のオーバーヘッドになり得ます。

トピックエイリアス機能により、MQTT クライアントはトピックに数値エイリアスを割り当て、さらにメッセージを公開するときにそのエイリアスの参照を可能にします。これにより、トピック自体ではなく単一の番号でトピックを参照することで、送信する MQTT パケットサイズを削減することができます。

例)センサー値: 23.2
例) MQTT topic (83 bytes):
sensors/field/field001/equipments/a804e598-ee90-4f89-9cde-458f8fe9b980/temperature

この機能を試すには、「はじめに」のステップでダウンロードした git リポジトリにあるスクリプトファイル./aws-iot-mqttv5-examples/03_topic_alias_example.pyを使用します。また「はじめに」の手順で取得したデバイスデータエンドポイントを --endpoint パラメーターで指定して下さい。(下記のサンプルコマンドの <AWS-IoT-Device-Data-Endpoint> を、ご自身の環境のエンドポイント、例えば、abcd123456z-ats.iot.region.amazonaws.comに置き換えて実行して下さい。)

$ python3 03_topic_alias_example.py --endpoint <AWS-IoT-Device-Data-Endpoint>
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'TestThing03' properties=None
DEBUG:__main__:Sending PUBLISH (d0, q0, r0, m1), 'b'sensors/field/field001/equipments/a804e598-ee90-4f89-9cde-458f8fe9b980/temperature'', properties=[TopicAlias : 1], ... (4 bytes)
DEBUG:__main__:Sending PUBLISH (d0, q0, r0, m2), 'b''', properties=[TopicAlias : 1], ... (4 bytes)
DEBUG:__main__:Sending PUBLISH (d0, q0, r0, m3), 'b''', properties=[TopicAlias : 1], ... (4 bytes)

このサンプルスクリプトは、トピックエイリアスを「1」に設定してトピックに最初の温度値をパブリッシュします。この値は、現在の接続が終了するまで有効です。次のパブリッシュ操作では、実際のトピックを指定せずにトピックエイリアスのみが参照されます。全てのメッセージは、ブローカー上の同じトピックに受信されます。制限事項については、リンク先ドキュメントのAWS IoT Core メッセージブローカーとプロトコルの制限とクォータの項目を参照してください。

4. メッセージの有効期限、セッションの有効期限、クリーンスタート機能によるデバイスの制御性向上

MQTTv5 では、デバイスをより適切に制御できるように、セッションとメッセージの有効期限に関するパラメータが用意されています。新しいセッションおよびメッセージの有効期限パラメータにより、ブローカーはクライアントの実装に依存することなく、より優れたセッション制御を提供します。

  • セッションの有効期限機能:一定の間隔を定義できます。この間隔が過ぎると、ブローカーは特定のクライアントのセッション情報を削除します。
  • メッセージ有効期限機能:現在接続されていないサブスクライバーに対してブローカーがパブリッシュしたメッセージを保存する間隔を定義します。セッションの有効期限は、メッセージの有効期限と同時に使用された場合、メッセージの有効期限を上書きします。また、メッセージの有効期限は、AWS IoT Coreメッセージの保持間隔を上書きします。制限事項についてはリンク先ドキュメントの、AWS IoT Core メッセージブローカーおよびプロトコルの制限とクォータの項目を確認してください。
  • クリーンスタート:セッションの有効期限間隔と同時に設定することができるフラグです。パケットにこのフラグを設定することは、既存のセッションを使用せずにセッションを開始することを示します。

コネクテッドカーは、接続パターンが不規則で、接続が回復したときのレジリエンスが求められるデバイスの良い例です。モバイルアプリでエアコンやドアロックなどの車のシステムと連動させるコネクテッドカーのユースケースを考えると、これらの機能をよく理解できると思います。例えば、宅配サービスやカーシェアリングで、遠隔操作でドアのロックを解除したりロックしたりするようなケースです。モバイルアプリが発行するこれらのリモートコマンドは、特定の時間内に処理される必要があります。メッセージの有効期限を指定することで、短い時間内(送信から 10 秒以内等)に車がコマンドを受信しない場合、そのメッセージは失効しなければならない、と指定することができます。エアコンの制御など、あまり時間的制約の少ないユースケースでは、リモートコマンドに 2 つ目のタイプのメッセージを指定することができます。例えば、有効期限を 2 分に設定した AC 電源をオンにするリモートコマンドを設定することができます。

この機能を試すために、リモートコマンドを送信するモバイルアプリクライアントとして動作するパブリッシャースクリプトを 1 つと、アクションを実行するコネクテッドカークライアントとして動作するサブスクライバースクリプトを 1 つ使用します。以下のサンプルスクリプトを確認してください。
./aws-iot-mqttv5-examples/04_message_session_expiry_clean_start_publisher_example.py
そして
./aws-iot-mqttv5-examples/04_message_session_expiry_clean_start_subscriber_example.py
このテストでは、この 2 つのスクリプトを異なる間隔で実行し、コネクテッドカーのオンラインとオフラインの状態を再現します。また「はじめに」の手順で取得したデバイスデータエンドポイントを--endpointパラメーターで指定して下さい。(下記のサンプルコマンドの<AWS-IoT-Device-Data-Endpoint>を、ご自身の環境のエンドポイント、例えば、abcd123456z-ats.iot.region.amazonaws.comに置き換えて実行して下さい。)

まず、セッションの有効期限間隔を 300 秒にしてサブスクリプションを実行します。これにより、 AWS IoT Core MQTT ブローカーにサブスクリプションを持つセッションインスタンスが作成され、デバイスがオフラインになったときに 300 秒間メッセージをキューに入れることができるようになります。

$ python3 04_message_session_expiry_clean_start_subscriber_example.py --endpoint <AWS-IoT-Device-Data-Endpoint> --session-expiry-interval 300
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c0, k60) client_id=b'TestThing04-Sub' properties=[SessionExpiryInterval : 300]
DEBUG:__main__:Received CONNACK (0, Success) properties=[SessionExpiryInterval : 0, ServerKeepAlive : 60, ReceiveMaximum : 100, TopicAliasMaximum : 8, MaximumQoS : 1, RetainAvailable : 1, MaximumPacketSize : 149504, WildcardSubscriptionAvailable : 1, SubscriptionIdentifierAvailable : 0, SharedSubscriptionAvailable : 1]
DEBUG:__main__:Sending SUBSCRIBE (d0, m1) [(b'vehicle/#', {QoS=1, noLocal=False, retainAsPublished=False, retainHandling=0})]
DEBUG:__main__:Received SUBACK

次に、クライアントを停止します。停止すると、セッションの有効期限である 300 秒のタイマーがスタートします。コネクテッドカーはオフラインになりますが、メッセージの有効期限( 300 秒)が切れる前にオンラインに戻れば、再度メッセージを受信できるようになります。次にパブリッシャーを実行して、コネクテッドカーがオフラインの間に 以下の 2 つのリモートコマンドを発行してみましょう。

$ python3 04_message_session_expiry_clean_start_publisher_example.py --endpoint &lt;AWS-IoT-Device-Data-Endpoint&gt;

2つのメッセージの Received PUBACK ログを確認したら、サブスクライバー側のスクリプトを実行してください。

$ python3 04_message_session_expiry_clean_start_subscriber_example.py --endpoint <AWS-IoT-Device-Data-Endpoint> --session-expiry-interval 300
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c0, k60) client_id=b'TestThing04-Sub' properties=[SessionExpiryInterval : 300]
DEBUG:__main__:Received CONNACK (1, Success) properties=[SessionExpiryInterval : 0, ServerKeepAlive : 60, ReceiveMaximum : 100, TopicAliasMaximum : 8, MaximumQoS : 1, RetainAvailable : 1, MaximumPacketSize : 149504, WildcardSubscriptionAvailable : 1, SubscriptionIdentifierAvailable : 0, SharedSubscriptionAvailable : 1]
DEBUG:__main__:Sending SUBSCRIBE (d0, m1) [(b'vehicle/#', {QoS=1, noLocal=False, retainAsPublished=False, retainHandling=0})]
DEBUG:__main__:Received PUBLISH (d0, q1, r0, m1), 'vehicle/air_conditioner/set', properties=[MessageExpiryInterval : 116], ...  (8 bytes)
DEBUG:root:Received a message on topic: 'vehicle/air_conditioner/set', payload: 'PRE_HEAT'
DEBUG:__main__:Sending PUBACK (Mid: 1)
DEBUG:__main__:Received PUBLISH (d0, q1, r0, m2), 'vehicle/driver_door/lock', properties=[MessageExpiryInterval : 6], ...  (6 bytes)
DEBUG:root:Received a message on topic: 'vehicle/driver_door/lock', payload: 'UNLOCK'
DEBUG:__main__:Sending PUBACK (Mid: 2)
DEBUG:__main__:Received SUBACK

スクリプトのログを見て、コネクテッドカーがオフラインの時に 2 つのリモートコマンドがパブリッシュされており、また、オンラインに戻った際に受信されていることを確認してください。vehicle/driver_door/lockメッセージは残り 6 秒、vehicle/air_conditioner/setメッセージは残り 116 秒であることに注目してください。このことから、コネクテッドカーはこの期間内にオンラインに戻り、期限切れになる前に両方のリモートコマンドを受信したことがわかります。
ここで、両方のスクリプトを停止して、同じパブリッシュ・サブスクライブのテストをもう一度実行します。この場合は、パブリッシュ後 15 秒待ってからメッセージをサブスクライブして下さい。期待通り、vehicle/air_conditioner/setメッセージのみが受信されていることが確認できます。このことから、コネクテッドカーがオフラインのときに、vehicle/driver_door/lockメッセージの有効期限が切れとなっていることがわかります。

この機能に関する最後の実験として、セッションの有効期限を 10 秒にしてサブスクライバを実行してみましょう。そうすると、 AWS IoT Core MQTT ブローカーにおけるコネクテッドカーのセッションは、キューイングされたメッセージとともに削除されます。メッセージの有効期限間隔がメッセージのキューイングを許可していても、 10 秒後にセッションが削除されるため、コネクテッドカーがメッセージを受信することはありません。

サブスクライバーをセッションの有効期限を 10 秒に設定してから実行し、Received SUBACK のログを見てから停止してください。次に、リモートコマンドを送るためにパブリッシャーを実行し、 15 秒間待ちます。その後、サブスクライバをもう一度実行してください。

$ python3 04_message_session_expiry_clean_start_subscriber_example.py --endpoint <AWS-IoT-Device-Data-Endpoint> --session-expiry-interval 10
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c0, k60) client_id=b'TestThing04-Sub' properties=[SessionExpiryInterval : 10]
DEBUG:__main__:Received CONNACK (0, Success) properties=[SessionExpiryInterval : 0, ServerKeepAlive : 60, ReceiveMaximum : 100, TopicAliasMaximum : 8, MaximumQoS : 1, RetainAvailable : 1, MaximumPacketSize : 149504, WildcardSubscriptionAvailable : 1, SubscriptionIdentifierAvailable : 0, SharedSubscriptionAvailable : 1]
DEBUG:__main__:Sending SUBSCRIBE (d0, m1) [(b'vehicle/#', {QoS=1, noLocal=False, retainAsPublished=False, retainHandling=0})]
DEBUG:__main__:Received SUBACK

ログからもわかるように、セッションが既に削除されているため、コネクテッドカーは何も受信していません。

5. Reason Code とサーバー切断機能を使用した拡張デバイス接続フロー

Reason Code により、送信者はパブリッシャーとサブスクライバーの間のトランザクションで発生したエラーのタイプ(存在する場合)を判断することができます。MQTT バージョン 5.0 の OASIS 仕様の全リストをご覧ください。

サーバー切断機能は、コネクションが閉じられた理由に関する Reason Code を含む、サーバーからの応答です。この機能は、切断/拒否が発生した理由を分析するときに役立ち、さまざまなデバッグに使用できます。

ユースケースの一例としては、クラウドで実行されているさまざまなサービスと統合するエッジセンサーゲートウェイが挙げられます。MQTT クライアントが切断されると、多くの場合、自動的に再接続を試みるように設定されています。MQTTV3.1.1 では、接続解除の Reason Code がない状態でデバイスが不正な MQTT アクションを実行しようとすると、ゲートウェイのサブスクリプショントピックと IoT デバイスポリシーの間の設定ミスによって接続/切断ループが発生していました。MQTTv5 では、デバイスは接続が切断された理由を把握し、サーバーからの接続解除の理由が認証にあると指定されている場合、そのトピックへのサブスクライブを試みません。デバイスは問題を報告し、 Reason Code を使用して適切な修復処置を試みることができます。

この機能を試すには、「はじめに」のステップでダウンロードした git リポジトリにあるスクリプトファイル ./aws-iot-mqttv5-examples/05_reason_codes_example.pyを使用します。また「はじめに」の手順で取得したデバイスデータエンドポイントを--endpointパラメーターで指定して下さい。(下記のサンプルコマンドの<AWS-IoT-Device-Data-Endpoint>を、ご自身の環境のエンドポイント、例えば、abcd123456z-ats.iot.region.amazonaws.comに置き換えて実行して下さい。)

$ python3 05_reason_codes_example.py --endpoint <AWS-IoT-Device-Data-Endpoint>
DEBUG:__main__:Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'TestThing05' properties=None
DEBUG:__main__:Received CONNACK (0, Success) properties=[SessionExpiryInterval : 0, ServerKeepAlive : 60, ReceiveMaximum : 100, TopicAliasMaximum : 8, MaximumQoS : 1, RetainAvailable : 1, MaximumPacketSize : 149504, WildcardSubscriptionAvailable : 1, SubscriptionIdentifierAvailable : 0, SharedSubscriptionAvailable : 1]
DEBUG:root:Connected {'session present': 0}
DEBUG:__main__:Sending PUBLISH (d0, q1, r0, m1), 'b'sensors/field/field001/equipments/9e6282ff-c8f0-49cd-b3a0-fa17ad6b84a7/temperature'', properties=None, ... (4 bytes)
DEBUG:__main__:Sending PUBLISH (d0, q1, r0, m2), 'b'sensors/field/field001/equipments/46be210d-8a83-4e92-a3fe-4f989704d21e/temperature'', properties=[TopicAlias : 14], ... (4 bytes)
DEBUG:__main__:Received DISCONNECT Topic alias invalid [ReasonString : DISCONNECT:Topic alias is out of range.:e3392cff-a031-4887-5b87-59eae249b6c4]
DEBUG:root:Received Disconnect with reason: Topic alias invalid
DEBUG:root:The disconnect is caused by the topic alias. Logging the issue for further analysis and exiting.

スクリプトを起動すると、最初にトピックエイリアス無しのメッセージを正常にパブリッシュします。次に、スクリプトはトピックエイリアスを 14 に設定して 2 番目のメッセージをパブリッシュします。トピックエイリアスの現在の制限は 8 なので、ブローカーは接続解除の理由も含めてパケットを拒否します。クライアントは、MQTT バージョン 5.0 の OASIS 仕様で指定されているように、DISCONNECT パケットの「トピックエイリアスが無効です」という Reason Code 148 を受け取ります。 Reason Code 148 の後、クライアントは正常に停止します。

まとめ

AWS IoT Core は、新たに発表された MQTTv5 の各種機能により、より包括的な IoT メッセージング機能を提供します。これらの機能により、お客様はより適応性の高い IoT アーキテクチャを構築し、より帯域幅効率、費用対効果、信頼性の高い導入が可能になります。このブログでは、これらの機能がさまざまな IoT ユースケースにおけるビジネス上の課題を解決するために、どのように機能するかを学んで頂きました。AWS IoT Core MQTTv5 機能の詳細を確認して使い始めるには、ドキュメントページをご覧ください。また、repost.aws Internet of Things channel にアクセスして、AWS IoT コミュニティと新機能について話し合ったり、アイデアを共有して下さい。

著者について

Emir Ayar は、AWS プロトタイピングチームのテックリードソリューションアーキテクトです。IoT 、ML at the Edge 、 Industry 4.0 に関するソリューションの構築とアーキテクチャのベストプラクティスの実装を支援することを専門としています。ルクセンブルグ在住で、趣味はシンセサイザーの演奏です。
Ashok Rao は、AWS の IoT スペシャリスト ソリューションアーキテクトです。 MCU やエッジゲートウェイなどの IoT ハードウェアとクラウド技術の両方に精通しています。 IoT ソリューションの設計と導入において、複数のドメインにまたがるコンセプトからプロダクションまで、さまざまなお客様を支援してきました。イギリス在住で、趣味は写真とスマートホームプロジェクト。

この記事はソリューションアーキテクトの新澤が翻訳しました。