AWS IoT Coreのtopicデザインホワイトペーパを読んでみた Part.1

# はじめに
[AWS IoT CoreのTopicデザインホワイトペーパ:Designing MQTT Topics for AWS IoT Core](https://d1.awsstatic.com/whitepapers/Designing_MQTT_Topics_for_AWS_IoT_Core.pdf)がリリースされていたので、ざっくりと読んだことを残しておきます。2018/October版がもとになります。今後updateされる可能性もあります。正しいのは原本の英語版ということでご理解ください。
特に英語が得意なわけでもないので、疑問がある方や、おやっと思った方は本文も見ていただければと思います。また、一気に全部読むには時間もかかるので何回かに分けて書く予定です。


## Abstract/目的
このホワイトペーパは、AWS IoT Coreでmqtt topicをデザインするためのベストプラクティスに焦点をあてている。mqttのデザインでアーキテクチャの改善に寄与することができる。
このホワイトペーパはクラウドアーキテクト、IoTエンジニアにむけて記述されている。


##Introduction/序章
AWS IoT Coreは制約のあるデバイス向けで広く一般的に利用されているmqttをサポートしている。mqttを利用するものはmqttを管理するtopicを介してメッセージを受け取ることができる。mqtt topicはpublisherとsubscriberの間を取り持つマッチングメカニズムとして機能する。概念的にmqtt topicは一時的なメッセージチャネルとして働く。

AWS IoTでは、mqttを使用する際の最初の考慮事項はmqtt topicの設計戦略になる。 mqttのtopicは、現在のデバイス通信、クラウドからの操作、および将来のデバイス機能のバランスをとる必要がある。

つまり、理想的なmqttのtopic構造を設計することは難しいことになる。
最小特権通信を実施するのに十分なスキーマを作成しますが、将来のデバイス展開をサポートするのが難しい厳しい構造を作成しないようにする。この資料では、mqtt topic設計のベスト・プラクティスとガイダンスを提供する。 さまざまなデバイス・メッセージ・パターンを解決するために実装できる一般的に使用されるmqtt topic構造の概要を説明し、次に異なるAWS IoTサービスを使用していくつかのサンプル設計パターンを適用する。

## MQTT Communication Patterns/mqtt通信パターン
IoTアプリケーションは、
 - デバイスからデバイス
 - デバイスからクラウド
 - クラウドからデバイス
 - デバイスからユーザ
 - デバイスからの複数の通信シナリオ
をサポートします。 パターンの範囲は大きく異なる可能性があるが、mqtt通信モデルの大部分は、ポイント・ツー・ポイント、ブロードキャスト、ファンインの3つのmqttパターンで考えられる。

### Point-to-Point/ポイント・ツー・ポイント接続
ポイント・ツー・ポイント通信パターンは、デバイスがmqttでメッセージを送受信する方法の基本的なビルディング・ブロックの1つ。 通信チャネルとして単一のMQTTトピックを2つ使用する。
イベントを受け取るThingは、mqttトピックにsubscribeする。 
メッセージを送信するものは、先のmqtt topicにpublishする。 
このアプローチは、エンドユーザーが自宅のものについての更新を受け取るスマートホームシナリオでは一般的である。 次の例では、モバイル・アプリケーションがsubscribeするトピックにロボット・アームがメッセージをpublishします。

![スクリーンショット 2018-10-14 12.46.56.png](https://qiita-image-store.s3.amazonaws.com/0/100893/7f23512d-8a1b-a861-5175-45dfe580347a.png)

ポイントツーポイント通信は、デバイス間の1対1通信に限定されない。ポイント・ツー・ポイントは、1つのpublisherがデバイスごとに異なるMQTTトピックを使用して個々のデバイスにパブリッシュできる1対多の通信でも使用される。このアプローチは、管理者が特定のデバイスに個別の更新を送信する通知シナリオでは一般的である。
次の例では、修復サービスは一連のポイントツーポイント通信を使用して、アプライアンスのリストをプログラム的にループしてメッセージをpublishします。

![スクリーンショット 2018-10-14 12.50.09.png](https://qiita-image-store.s3.amazonaws.com/0/100893/8df1894a-09fa-a2fb-5291-ce79a99d6178.png)

### Broadcast/広域通知
ブロードキャスト・パターンは、1対多メッセージングに使用される。 ブロードキャストパターンは、同じメッセージを大規模なデバイスに送信します。ブロードキャストでは、複数のデバイスが同じmqtt topicをsubscribeし、送信者はその共有トピックにメッセージをpublishする。 ブロードキャストパターンの一般的な使用方法は、デバイスのカテゴリまたはグループに基づいてデバイスに通知を送信することになる。 たとえば、気象ステーションは、デバイスの現在のジオロケーションに基づいてブロードキャストメッセージを送信します。デバイスは、ロケーションごとにグループ化される。
次の図は、ブロードキャストパターンが、州のすべてのバスが購読している天気の話題にメッセージを送信する例を示しています。バスの現在の位置に基づいて、メッセージを無視または応答することができます。

![スクリーンショット 2018-10-14 12.53.20.png](https://qiita-image-store.s3.amazonaws.com/0/100893/0c137630-eee0-537f-82c8-15fe64a1db25.png)

### Fan-In/大量メッセージの流入(N:1パターン)

ファンインパターンは、多対1の通信パターンであり、ブロードキャストパターンの逆と考えることができる。 複数のデバイスは、そのtopicに対する単一のsubscriberを持つ共有topicにpublishします。 ファンイン・パターンでは、publisherがすべて似たようなユニークなmqtt topicを使用するため、加入者はワイルドカードを活用できるようになった。 ファンインパターンは、IoTアプリケーションへのテレメトリの集約を容易にするために一般的に使用される。
次の例では、各エンド・デバイスは、既知のグループIDを含むmqtt topicにpublishします。 AWS IoT Rules Engineはワイルドカードサブスクリプションを使用してメッセージを受信し、Amazon Kinesis streams にルーティングします。 具体的には、ロボットアームは、特定の建物（建物1234）に関連付けられたファンイントピックでpubishします。 管理システムは、MQTTワイルドカード（+）を使用して建物のすべての更新を受け取る。

![スクリーンショット 2018-10-14 12.57.19.png](https://qiita-image-store.s3.amazonaws.com/0/100893/d8210049-8e93-366f-df22-dc82cbc6ef9d.png)

デバイスがmqttを使用してクラウド経由で通信する場合、このルーティングは単一のデバイスmqtt接続で調整できない制限に達する可能性があるため、**単一のサブスクライブ側のエンド・デバイスに対してファンイン・パターンを推奨しない。** 代わりに、ファンインパターンを使用して、AWS IoT Rules Engineを使用して、大量のメッセージをIoTアプリケーションにルーティングします。 大規模なファンインシナリオでは、ルールエンジンをワイルドカードsubscribeパターンおよびルールエンジンアクションと組み合わせて、Amazon Kinesis Data Streams、Amazon Kinesis Data Firehose、またはAmazon Simple Queue Service（Amazon SQS）にルーティングする。

##Communication Workflows/通信フロー
一般的な3つの通信ワークフローは、
- デバイス対デバイス
- デバイス対クラウド
- デバイス対クラウド
となる。
デバイスからデバイスの場合、mqtt topicにはメッセージの送信者または受信者の識別子が含まれている必要があります。 デバイスがクラウドになるためには、MQTTメッセージにはターゲット・アプリケーションに関する情報が含まれている必要がある。 ターゲット・アプリケーションは、デバイスに関する内部メタデータを含むmqttメッセージを拡張する役割を担う。 最後に、クラウドからデバイスへの通信の場合、mqttメッセージには、重要なメッセージの正常応答を追跡するためのセッション情報が含まれている必要があります。

##MQTT Design Best Practices/mqttデザインのベストプラクティス
###General Best Practices/一般的なベストプラクティス
一般的なアプローチを共有するIoT通信パターンの組み合わせは数多くあるが、デバイスがメッセージを発行または受信する方法に関係なく、どのメッセージパターンにも適用されるいくつかのベストプラクティスがある。このセクションでは、トピック構造を設計する際に、レビューと実装を行うためのベストプラクティスをいくつか紹介します。
MQTT topicでは小文字、数字、およびダッシュ(ハイフン)のみを使用してください。 mqtt topicでは大文字と小文字が区別されるため、MQTTトピックを設計する際には、標準の命名規則を使用することが重要。このため、各トピックレベルを作成するときは、小文字、数字、およびダッシュのみを使用する。顧客が、キャメルケース、スペースなどの文字をデバッグするのは難しいので避けたほうがよい。

mqtt topic レベル構造が一般的なパターンから特定のパターンに従うようにする。
トピックのスキームが左から右に流れるにつれて、トピックレベルは一般的なものにする。たとえば、HVACシステムは、hv100という名前のIoTプラットフォームに関連付けられており、建物bld1518の下にあり、Thing Nameはhvac719です。トピック構造は、一般的なグループ（この場合はIoTプラットフォームの名前）で始まり、最も固有の識別名である「Thing Name」で終わる。この例では、次のトピックレベル構造を作成している。
![スクリーンショット 2018-10-14 13.12.06.png](https://qiita-image-store.s3.amazonaws.com/0/100893/77a9c208-8333-9c74-2343-22047fb3cef0.png)

MQTTトピックに関連するルーティング情報を含める。 関連するルーティング情報には、IoTアプリケーション識別子、インストールされた場所、IoTデバイスの一意のIDなど、デバイスが含まれる可能性のあるグループが含まれますが、これに限定されない。 前のHVACシステム例を続行するには、MQTTトピックhv100 / bld1518 / basement / hvac719にすべての関連するルーティング情報が含まれています。 このmqtt topicに基づいて、識別子hv100を使用してアプリケーション全体に関連するすべてのデータをキャプチャするシステムを設計できるが、ビルの場所など、メッセージをsubscribeするためのさまざまな関心領域をターゲットにすることもできる。

**MQTTのトピックに接頭辞を付けて、データ・トピックとコマンド・トピックを区別する。** MQTTのトピックがコマンドとデータ・メッセージの間で重複しないようにする。 データとコマンドを示すように最初のトピックレベルを予約することで、IoTポリシーを使用してきめ細かな権限を作成し、受動テレメトリコマンドとは別にコマンドとコマンド応答のステータスを監視することが容易になる。 たとえば、報告された状態と希望の状態を追跡するためにAWS IoT Device Shadowを使用し、受動的なリアルタイムテレメトリデータに別のデータトピックを使用する。

**MQTTのトピック構造を文書化し、運用実践の一環として文書化する。** ドキュメントには、データのpublish、subscirbe、または受信に使用できるすべてのトピックと、データの意図されたプロデューサとコンシューマが含まれている必要がある。 ドキュメントがAWS IoTの制限、内部セキュリティ要件、およびアプリケーションの使用事例に準拠していることを確認。

**MQTTを介してデバイスとして接続する場合は、MQTTクライアントIDとしてAWS IoT Thing Nameを使用する。** MQTTには、AWS IoTに接続する際に固有のクライアントIDが必要。 MQTTクライアントIDとして、デバイスごとに固有の「Thing Name」を使用する。 クライアントIDをThing Nameと照合することで、IoTログなどの情報を関連するAWS IoTデバイスにさらに簡単に関連付けることができる。 さらに、clientIdがThing Nameと一致する場合は、[Thing Policy Variables](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/thing-policy-variables.html)などの追加機能を使用できる。 Thingポリシー変数を使用すると、AWS IoTポリシーに、物件名や物件属性などの物件を含めることができ、IoTデバイス全体にプロビジョニングする必要があるポリシーの総数を減らすことができる。

**デバイスがデータのpublishまたはsubscribeに使用するMQTTトピックに、デバイスのThing名を含める。** 特定のデバイス宛てのメッセージを追跡するには、デバイスによって発行された、または特定のデバイスに送信されたMQTTメッセージの一部としてThing Nameを含めます。 MQTTトピックの終わり近くまたは終わりに、ルーティングトピック情報の後に「Thing Name」が表示される。

**AWS IoT Coreのデフォルトのサービス制限を確認してください。 任意の調整可能なIoTサービス制限に合わせるように通信パターンを設計する。**AWS IoTには、AWS IoT Coreサービスに関連して、いくつかの調整可能な制限と調整不可能な制限があります。 トピックレビューの一環として、[AWS IoTの制限](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_iot)を確認し、MQTTのトピックとデバイスの通信が調整不可能な制限と矛盾しないようにする必要がある。

**MQTTメッセージのペイロードに特定のメッセージに関する追加のコンテキスト情報を追加する。**このコンテキスト情報には、セッション識別子、リクエスタ識別子、ロギング情報、またはデバイスが応答を受信する予定のリターントピックが含まれますが、これに限定されない。 mqtt 3.1.1仕様には特定のペイロード属性は必要ないが、mqttペイロード内に関連するトラッキング情報を含めることをお薦めします。セッション識別子や成功またはエラーコードなどのフィールドを含む標準構造を作成することで、デバイスの動作の傾向をより簡単に分析できる。通信スキーマを標準化することで、IoTチームのデバイスユースケースの共有も強化される。

**MQTT通信パターンを避けることで、単一のデバイスに相当なファンインシナリオをもたらします。**いくつかのAWS IoT制限は、制限の増加の一環として提起することはできません。また、単一のMQTT接続での最大発行など、デバイスの動作ごとに頻繁に相関がある。 1つのデバイスが多数の他のデバイスによってpublishされている共有トピックに登録することを許可してはいけない。このパターンを回避すると、1つの接続デバイスの制限、特に1秒あたりの接続あたりのスループットのスループットが低下することを避けることができる。

**＃を使用してデバイスがすべてのトピックにサブスクライブすることを許可せず、IoTルールでのみマルチレベルのワイルドカードサブスクリプションを使用する。** マルチレベルのワイルドカードを使用すると、誤ってその特定のデバイス用ではない可能性のある新しいトピックを階層に追加すると、意図しない結果が生じることがある。 代わりに、IoTルールエンジンの一部としてマルチレベルワイルドカードの使用を予約し、デバイスサブスクリプションに単一レベルのワイルドカード（+）を使用する。

## Best Practices for Telemetry/テレメトリのベストプラクティス
テレメトリは、デバイスによって送信され、クラウドに集約される読み取り専用のデータである。 リモートモニタリングは、通信のためのファンインパターンと共に、デバイスからクラウドへのパターンに従うものである。 テレメトリーは、オプションでより高品質のサービス（QoS）レベルを設定することを超えて、MQTTブローカーから応答メッセージを戻す必要はない。 テレメトリーは受動的なアクティビティーであるため、テレメトリーのMQTTトピックは、コマンドなどのアクティブなワークフローのMQTTトピックと重複することはできない。 テレメトリトピックは、エッジゲートウェイやメッシュネットワークなどの他のデバイスに代わって単一のコーディネータがテレメトリをpublishする、より複雑なデバイスをサポートします。
AWS IoTでは、異なるAWS IoTサービスを使用してリモートモニタリングの通信パターンをサポートできる。 テレメトリのユースケースをサポートするには、標準のMQTTトピックを使用することをお勧めしている。

テレメトリー用のMQTTトピックの使用
**MQTTテレメトリのトピック構文**
次の例と各項は、遠隔測定のためのMQTTトピック構造を提供します。

```
dt/<application>/<context>/<thing-name>/<dt-type>
```

dt: メッセージタイプがわかるようなプリフィックス
リモートメンテナンスの話題については、dt、データの略語を使用する。 すべてのテレメトリトピックは、このトッププレフィックスをアプリケーションに使用します。 リモートメンテナンスに同じ値を再使用することによって、メッセージの意図を、最初に前置された値を参照することによって識別できます。 この場合、どのdtトピックもテレメトリトピックとなる。

application:：デバイスに関連するIoTアプリケーション全体を識別するもの。
一般的に使用されるアプリケーション属性には、デバイスハードウェアのバージョンや、メッセージの主要な取り込み点であるクラウドアプリケーションの内部識別子などがある。 IoTアプリケーションは、貴重なIoT製品の内部名に関連付けられているか、具体的にはデバイスのハードウェアの種類に関連している。 アプリケーション・トピック部分は、デバイス・メッセージのグループと相関し、不変であるため、遠隔測定MQTTトピックのアプリケーション・プレフィックス部分は、dtメッセージ・タイプの直後に配置される。

context：単一または複数のレベルの追加のコンテキストデータ
デバイスが公開中であることを示すメッセージ。コンテキスト情報は、デバイスのプロビジョニング中に設定される情報に関連している。 例えば、工場出荷時設定の情報は、施設内の装置の現在の物理的位置を含めることができる。 コンテキスト情報のもう1つの例は、MQTTトピックのgroup-idです。 group-idは、複数のデバイスが特定の属性に基づいて固有の関係を持つ場合（スマート電球を購入して部屋の照明を制御するなど）を表します。 group-idは、多数のデバイスがアクティビティを1つのユニットとして調整できるようにする。

thing-name：テレメトリメッセージを送信しているデバイスを識別する。

dt-type（オプション）：メッセージをデバイスの特定のサブコンポーネントまたはエッジゲートウェイ、ダウンストリームデバイスに関連付ける。

複雑なデバイスには、センサ、アクチュエータ、または個別のシステムオンチップ（SOC）など、特定のタスクを持つ複数のサブコンポーネントが存在することがよくある。 dtタイプを使用すると、特定のデバイスの各サブコンポーネントを個々のMQTTトピックに関連付けることができる。 たとえば、車両のジオロケーションと方向を測定するサブコンポーネントがそれにあたる。 そのサブコンポーネントは、ジオロケーションのメッセージを車の他のコンポーネント（加速度計など）と区別するために、geoタイプのdtタイプの値を持つ。

## Best Practices for Commands/コマンド用途のベストプラクティス
IoTアプリケーションでは、コマンドトピックを使用してデバイスをリモートで制御し、コマンドの実行が成功したことを確認することが必要となる。遠隔測定とは異なり、コマンドトピックは読み取り専用ではなくなる。コマンドは、2つのデバイス間またはクラウドとデバイス間で発生する前後のワークフローです。コマンドは実行可能なメッセージなので、リモートメンテナンスのトピックからコマンド・メッセージのMQTTトピックを分離する。

AWS IoTのコマンドおよび制御操作を実装するためのサービスがいくつか用意されています。クラウドに希望の状態と報告された状態を格納する機能を備えたAWS IoT Shadowは、個々のデバイスコマンドを実装するためのAWS IoTサービスとして推奨されます。 AWS IoTデバイスジョブは、ジョブトラッキングのAmazon CloudWatchメトリックや単一のデバイスの複数の転送中ジョブを追跡する機能など、追加の利点を提供するため、フリート全体の操作に使用する必要がある。 AWS IoT Shadow、AWS IoT Jobドキュメント、および標準MQTTトピックの組み合わせを使用して、コマンドの使用例をサポートすることができる。

###Using the AWS IoT Shadow for Commands/AWS IoT shadowのコマンドを使う
デバイスシャドウサービスは状態を仲介する機能を提供し、デバイスとアプリケーションがデバイスのシャドウ状態を取得および更新できるようにできる。 シャドウを使用して、MQTTまたはHTTP経由でデバイスの状態を取得および設定できる。 シャドウには、コマンドとコントロールをサポートする以下の個々の状態プロパティが含まれる。

**desired state/希望する状態** デバイスにコマンドを送信する権限を持つアプリケーションは、要求された状態の変更をシャドウドキュメントの必要な部分に書き込むことができます。 目的の状態を更新されたことにより、AWS IoT ShadowサービスはAWSクラウドに希望の状態変更を保存し、次に予約されたシャドウトピックを使用してデバイスにMQTTメッセージを送信する。 デバイスがシャドウリクエストを受信すると、デバイスは必要な状態から必要な変更を実行できる

**reported state:報告された状態。** reported stateは、デバイスによって最後に公開された現在の属性を格納します。 アプリケーションがシャドウのこの部分を読み込んで特定のデバイスの状態を判断する間に、ドキュメントのこの部分に書き込んで新しい状態を記録する。 コマンドトピックを実装するために、AWS IoT Shadowはデバイスの属性の保存、取得、および変更に推奨される機能である。

デバイスが現在オフラインであっても、後で使用するためにコマンドが持続する状況では、AWS IoT Shadowを使用してください。 例えば、GPSシステムが、shadowのdesiredを介して新しい目的地に送られたが、直ちに到達可能でない場合、新しい座標はGPSのIoTシャドウにとどまる。 GPSシステムが接続を回復すると、積極的に最後のシャドウ状態を要求して新しい座標を取得できます。 シャドーは、デバイスの属性について最後に報告された状態を格納するのにも理想的です。

#####AWS IoT Shadowを使用するためのベストプラクティス
AWS IoT Shadowは、特定のデバイスの報告された状態を保存するとともに、コマンドと制御の優れたメカニズムとなる。 以下のリストは、シャドウによるコマンドの効率を最大化するためのベストプラクティスを示す。

#####IoTデバイスはshadowを共有すべきではない。
各デバイスのコマンドを区切るには、各デバイスがそれ自身のシャドウに対するアクセス権を持ち、そのデバイスが単一のshadowを共有していないことを確認すべき。 エッジゲートウェイや複数のサブコンポーネントを持つ大規模なデバイスアセットのような複雑なシナリオでは、アセットは複数のIoTオブジェクトを使用する必要がある。

#####中〜低トランザクション/秒（TPS）の状態またはコマンドには、shadowを使用します。
shadowは、数分、数時間、または数日で発生する更新頻度が低い場合に最適。 シャドーは、アクションが成功したことを確認するための追加トピックを発行するため、1秒間に1回または複数秒ごとに更新を送信する要求など、高スループットテレメトリー用の標準MQTTコマンド・トピックを使用したほうがよい。

#####shadowを使用して、デバイスのステータスメトリックを保存。 
接続性、デバイスセンサーと制御ユニットのステータス、およびこれらのサブコンポーネントに関するエラー情報など、デバイスの現在の正常性に関する情報を格納する。 デバイスの現在の状態を知っている場合は、コマンド要求中に意思決定を行うことができる。

#####デバイスシャドウを使用して、現在のファームウェアバージョンをカタログする。
shadowは、デバイスがハードウェアにインストールされているファームウェアバージョンを通知するのに理想的な場所です。 ファームウェアは、サービスのmajor.minor.patchバージョンを強調するフィールドなどの単純な属性である必要があります。

#####シャドウメッセージの送信者を追跡するには、オプションのclientTokenフィールドをdevice shadow更新とともに使用する。
 clientTokenは、shadow内のフィールドで、サブスクライバはレスポンスをMQTTアプリケーション内のリクエストに関連付けることができます。 デバイスがshadow更新要求中にclientTokenを設定すると、AWS IoT Shadowサービスは、関連付けられたshadow イベントに同じclientTokenを含めます。

#### Using the AWS IoT Jobs for Commands /AWS IoT Jobをコマンドとして使う
AWS IoT Jobsは、AWS IoTに接続された1つ以上のものに送信され実行される一連のリモート操作を定義するためのサービスである。 コマンドの使用例では、ジョブによって、アプリケーションは複数のステップを実行する必要があるタスクを実行できる。 AWS IoT Jobには、トランザクションを完了するために実行する必要のある指示が含まれています。 AWS IoT Jobは、IoTアプリケーション全体の信頼できる管理者によってのみ実行される、ソフトウェア更新などのfleetwide操作タスクに推奨される機能である。

#### Best Practices for Using the AWS IoT Jobs/AWS IoT Jobsのベストプラクティス

#####AWS IoT Jobs用のデバイスを整理するには、Thingグループを使用する。
 現在のファームウェアバージョン、ハードウェアバージョン、またはデプロイメント環境（ステージングやプロダクションなど）など、共通のデバイス属性で編成された複数のものを作成できる。 また、グループにはビジネスユニットや場所などの共通の階層構造も必要となる。 デプロイメント中に、特定のIoTジョブのデプロイメントターゲットとして、Thingグループを使用できる。

#####ステージングされたロールアウトを使用して、デバイスジョブを使用してコマンドを展開する。
 デバイスジョブは、フリート全体の操作をデバイスに配信するための理想的なソリューションです。 複数の小規模な展開を最初にフリートのサブセットに作成し、デバイスに変更を適用させてから、時間の経過とともにより多くのデバイスにコマンドを展開します。 数週間から数ヵ月にわたり変更を進めることで、予期しない問題が少ないことをより自信を持って認識させることができます。

####Using the MQTT Topics for Commands /コマンドとしてMQTTを使う
**MQTTコマンドのトピック構文**
いくつかのシナリオでは、標準のMQTT publishおよびsubscribeのモデルを使用してコマンド通信を設計することができる。この状況は、デバイスが一時的なコマンド（この現在のタイプでしか処理できず、デバイスが使用できない場合には失敗するコマンド）を実行しなければならない場合や、複数のデバイスで同時に1つのコマンドを実行する場合に発生する可能性がある。また、デバイスが高レベルのAWS IoTサービスを利用できないような環境でも可能となる。また、MQTTトピックの独自のセットを選択して、デバイスへのコマンドとデバイスからの応答を定義する柔軟性が必要な場合もある。

コマンド・トピックの別のセットを使用している場合は、テレメトリーで説明したMQTTコマンド・トピックの同様のベスト・プラクティスに従うとよい。コマンドトピックは、他のデバイスにコマンドを公開または中継する複雑なデバイスに柔軟性を持たせるべきである。コマンドトピックは、必須属性の可視性も提供する必要があります。 MQTTコマンド・トピックは、MQTTトピックおよびペイロードに基づいて操作上の問い合わせに応答する必要がある。
• コマンドの実行者は誰か？
• コマンドの受信者は誰か？
• コマンドは正常に処理されたか？
• コマンドの現在の状態は？
• コマンドが正常に処理されなかった場合、エラーは何か？

これらの質問に加えて、コマンドがいつ要求されたか、デバイスが応答したかを判断したり、クラウド内のフリート間の単一の要求の状態を監視することもできる。
コマンド要求のためのMQTTトピックを設計するときは、次のような構造にしてください。

```
cmd / <application> / <context> / <destination-id> / <req-type>
```

コマンドは双方向通信パターンなので、次のようなコマンドに応答するための同様のMQTTトピック構造を設計する。

```
cmd/<application>/<context>/<destination-id>/<res-type>
```

遠隔測定のトピック設計はコマンドトピックの設計と似ているため、このセクションではIoTトピックのうちコマンドの要求と応答が異なる部分についてのみ説明する。

cmd：メッセージのタイプを参照する接頭詞。
コマンドトピックは、コマンドの略語であるcmdを使用する。 すべてのコマンドにcmdとすべてのテレメトリの接頭辞を付けることで、遠隔測定とコマンドは別々のMQTTトピックで分離される。

req-type：コマンドを分類します。 
単純な要求と応答パターンの場合、req-type属性はreqのような単一の静的なコマンド値であるべき。 制限されたコマンドタイプの場合、MQTTメッセージには追加データがペイロードに含まれる。

デバイスが複数のデバイス、アクチュエータ、またはサブコンポーネントを編成するより複雑なシステムでは、req-type属性はコマンドを受け取るために使用できる各サブコンポーネントに関連する。 たとえば、デバイスがモバイルの場合、デバイスを遠隔操作するか、デバイスの周囲に関するナビゲーション情報を受け取ることができる。 このタイプのサブコンポーネントは、コマンドが単一または複数のプレーンで操縦されるreqタイプのnavを持ったほうが良い場合もある。

destination-id：このメッセージの宛先デバイスまたはアプリケーションを識別する。
destination-idを含めることによって、ターゲットデバイスは、独自のコマンドトピックセットにサブスクライブし、任意のコマンド要求を受け取ることができる。

res-type：コマンド応答を示し、以前に送信されたコマンドに関連する応答を識別する。
res-typeを使用すると、1つのデバイスですべての着信コマンドの確認応答に1つのシングルレベルワイルドカードサブスクリプションを使用できる。 デバイスに制限されたコマンドがある場合、レスポンストピックはresなどの静的フィールドを使用できる。

**MQTTコマンドのペイロード構文**
コマンド用の明確なMQTTトピック構造を作成することに加えて、メッセージ・ペイロード用のスキーマを生成するか確認をする。 MQTTペイロード情報は、受信デバイスまたはIoTアプリケーションによって解析され、オペレーションを完了するために必要な追加ロジックを通知する。 MQTTコマンドの場合、message payloadコマンドで次のフィールドを組み込む。

session-id：一意のセッションを識別します。
リクエスタは、コマンドのセッションIDを生成し、それを要求ペイロードに含める。 応答トピックは、コマンド完了時にsession-idを使用する。 セッションIDを使用することにより、AWS IoT Rules Engineはコマンドのステータスを保存および追跡し、依頼が依然として転送中、正常終了中、またはエラー中であるかどうかを判断できる。 デバイスは、複数のデバイスと通信するときに、輸送中の要求を追跡することもできる。

response-topic：コマンドには、アクションが発生する要求と、コマンドのステータス（成功またはエラー）を示す応答がある。
レスポンス・トピックをハードコードするのを避けるために、どのMQTTコマンドでも、コマンド要求ペイロードには、応答トピックを持つフィールドが含まれていることを推奨する。 デバイスは、応答トピックを使用して応答ペイロードをpublishする。 たとえば、次のコマンドのトピックを考えてみましょう。

```
cmd/security/device-1/cert-rotation
```

この要求のペイロードでは、IoTアプリケーションは、デバイス（デバイス-1）がその応答を送信すべき場所および追跡のためのセッション識別子を示すフィールドを含む。 このコマンドのペイロード構造については、次の例を参照してください。

```
{
 "sessionId":"session-820923084792",
 "resTopic":"cmd/security/app1/res"
}
```

[part2へつづく。](https://qiita.com/TakashiKOYANAGAWA/items/f0823179b7e955e517b9)

##免責
本投稿は、個人の意見/取り組みで、所属する企業や団体は関係ありません。
また意訳等などもあるために、参考程度にしてください。