

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# coreMQTT エージェント接続共有デモ
<a name="mqtt-demo-cs"></a>

**重要**  <a name="deprecation-message-demo"></a>
このデモは、非推奨の Amazon-FreeRTOS リポジトリでホストされています。新しいプロジェクトを作成するときは、[ここから始める](freertos-getting-started-modular.md)ことをお勧めします。現在非推奨の Amazon-FreeRTOS リポジトリをベースにした既存の FreeRTOS プロジェクトが既にある場合は、「[Amazon FreeRTOS Github リポジトリ移行ガイド](github-repo-migration.md)」を参照してください。

## 序章
<a name="mqtt-demo-cs-introduction"></a>

coreMQTT 接続共有デモプロジェクトでは、マルチスレッドアプリケーションを使用して、クライアントとサーバー間の相互認証で TLS を使用して AWS MQTT ブローカーへの接続を確立する方法を示します。このデモでは、mbedTLS ベースのトランスポートインターフェイスの実装を使用して、サーバーとクライアントの認証 TLS 接続を確立し、[QoS 1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180914) レベルでの MQTT のサブスクライブおよび公開ワークフローについて説明します。デモでは、トピックフィルターをサブスクライブし、フィルターに一致するトピックに公開し、QoS 1 レベルでサーバからそれらのメッセージを受信するまで待機します。ブローカーに発行し、ブローカーから同じメッセージを受信するというこのサイクルは、作成されたタスクごとに何度も繰り返されます。このデモのメッセージは QoS 1 で送信され、MQTT 仕様に従って少なくとも 1 つの配信が保証されます。

**注記**  
FreeRTOS デモをセットアップして実行するには、[FreeRTOS の開始方法](freertos-getting-started.md) の手順に従います。

このデモでは、スレッドセーフなキューを使用して MQTT API を操作するためのコマンドを保持します。このデモでは、注意すべきタスクが 2 つあります。
+ MQTT エージェント (メイン) タスクは、コマンドキューからのコマンドを処理し、他のタスクがそれらをキューに追加します。このタスクはループに入り、その間にコマンドキューからのコマンドを処理します。終了コマンドを受信すると、このタスクはループから抜け出します。
+ demo subpub タスクは MQTT トピックへのサブスクリプションを作成後に、発行オペレーションを作成してコマンドキューにプッシュします。その後、これらの発行オペレーションが MQTT エージェントタスクによって実行されます。demo subpub タスクは、コマンド完了コールバックの実行に伴い通知される発行の完了まで待機してから、次の発行を開始する前に短い遅延に入ります。このタスクでは、アプリケーションタスクが coreMQTT エージェント API を使用する方法の例を示します。

発行メッセージを着信した場合、coreMQTT エージェントは単一のコールバック関数を呼び出します。このデモには、サブスクライブしているトピックで着信した発行メッセージを呼び出すコールバックをタスクで指定できるサブスクリプションマネージャも含まれています。このデモでエージェントが着信した発行コールバックは、サブスクリプションマネージャを呼び出し、サブスクリプションを登録したタスクに発行をファンアウトします。

このデモでは、相互認証を使用した TLS 接続を使用して AWSに接続します。デモ中にネットワークが予期せず切断された場合、クライアントはエクスポネンシャルバックオフロジックを使用して再接続を試みます。クライアントが正常に再接続してもブローカーが前回のセッションを再開できない場合、クライアントは前回のセッションと同じトピックに再度サブスクライブします。

### シングルスレッドとマルチスレッド
<a name="mqtt-demo-cs-single-vs-multi"></a>

coreMQTT の使用モデルは、シングルスレッドとマルチスレッド (マルチタスク) の 2 つがあります。シングルスレッドモデルでは、coreMQTT ライブラリを 1 つのスレッドからだけ使用するため、MQTT ライブラリで明示的に繰り返し呼び出す必要があります。マルチスレッドユースケースでは、ここで説明しているデモに示すように、エージェント (またはデーモン) タスク内で MQTT プロトコルをバックグラウンドで実行できます。エージェントタスクで MQTT プロトコルを実行する場合、MQTT 状態を明示的に管理したり、`MQTT_ProcessLoop` API 関数を呼び出したりする必要はありません。また、エージェントタスクを使用すると、ミューテックスなどの同期プリミティブを必要とせずに、複数のアプリケーションタスクで単一の MQTT 接続を共有できます。

## ソースコード
<a name="mqtt-demo-cs-source-code"></a>

デモソースファイルは、`mqtt_agent_task.c` と `simple_sub_pub_demo.c` という名前で、[GitHub](https://github.com/aws/amazon-freertos/tree/main/demos/coreMQTT_Agent/) ウェブサイトの `freertos/demos/coreMQTT_Agent/` ディレクトリに用意されています。

## 機能
<a name="mqtt-demo-cs-functionality"></a>

このデモでは、少なくとも 2 つのタスクを作成します。それは MQTT API コールのリクエストを処理するプライマリタスクと、それらのリクエストを作成する設定可能な数のサブタスクです。このデモでは、プライマリタスクがサブタスクを作成し、処理ループを呼び出し、後でクリーンアップします。プライマリタスクは、サブタスク間で共有されるブローカーへの MQTT 接続を 1 つ作成します。サブタスクはブローカーに対する MQTT サブスクリプションを作成し、それに宛ててメッセージを発行します。各サブタスクでは、発行に固有のトピックが使用されます。

## メインタスク
<a name="mqtt-demo-cs-main-task"></a>

主なアプリケーションタスクである [RuncoreMqtTagentDemo](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/mqtt_agent_task.c#L435-L480) は、MQTT セッションを確立し、サブタスクを作成し、終了コマンドを受信するまで処理ループ [mqtTagent\$1commandLoop](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/mqtt_agent_task.c#L856) を実行します。ネットワークが予期せず切断された場合、デモはバックグラウンドでブローカーに再接続し、ブローカーに対するサブスクリプションを再確立します。処理ループが終了すると、デモはブローカーから切断されます。

### コマンド
<a name="mqtt-demo-cs-main-task-commands"></a>

coreMQTT エージェント API を呼び出すと、エージェントタスクのキューに送信されるコマンドが作成され、`MQTTAgent_CommandLoop()` で処理されます。コマンドの作成時に、オプションの完了コールバックおよびコンテキストパラメータを渡すこともできます。対応するコマンドが完了すると、渡されたコンテキストと、コマンドの結果として作成された戻り値を使用して、完了コールバックが呼び出されます。完了コールバックの署名は次のとおりです。

```
typedef void (* MQTTAgentCommandCallback_t )( void * pCmdCallbackContext,
                                              MQTTAgentReturnInfo_t * pReturnInfo );
```

コマンド完了コンテキストはユーザー定義であり、このデモでは、[struct MQTTAgentCommandContext](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/simple_sub_pub_demo.c#L105-L115) となります。

コマンドは次の時点で完了したと見なされます。
+ QoS > 0 でのサブスクライブ、サブスクライブ解除、発行: 対応する確認応答パケットを受信した時点。
+ その他すべてのオペレーション: 対応する coreMQTT API が呼び出された時点。

発行情報、サブスクリプション情報、完了コンテキストなど、コマンドで使用されるすべての構成要素は、コマンドが完了するまでスコープ内に留めておく必要があります。呼び出し元のタスクは、完了コールバックを呼び出す前に、コマンドの構成要素を再利用してはいけません。完了コールバックは MQTT エージェントによって呼び出されるため、コマンドを作成したタスクではなく、エージェントタスクのスレッドコンテキストを使用して実行されます。タスク通知やキューなどのプロセス間通信メカニズムを使用すると、呼び出し元のタスクにコマンドの完了を通知できます。

### コマンドループの実行
<a name="mqtt-demo-cs-command-loop"></a>

コマンドは `MQTTAgent_CommandLoop()` で継続的に処理されます。処理するコマンドがない場合、ループはコマンドがキューに追加されるまで最大で `MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME` 待機します。コマンドが追加されない場合は、`MQTT_ProcessLoop()` の反復が 1 回実行されます。これにより、MQTT キープアライブが管理され、キューにコマンドがない場合でも着信する発行を受け入れられます。

コマンドループ関数は、次の理由で値を返します。
+ コマンドは `MQTTSuccess` 以外のすべてのステータスコードを返します。エラーステータスはコマンドループによって返されるため、エラーステータスについては処理方法を決定できます。このデモでは、TCP 接続が再確立され、再接続が試行されます。エラーが発生した場合、MQTT を使用している他のタスクの介入なしに、バックグラウンドで再接続することができます。
+ 切断コマンド (`MQTTAgent_Disconnect` から) が処理されます。TCP を切断できるように、コマンドループが終了します。
+ 終了コマンド (`MQTTAgent_Terminate` から) が処理されます。このコマンドは、キュー内に残っているコマンドや、確認応答パケットを待っているコマンドをエラーとしてマークし、コード `MQTTRecvFailed` を返します。

### サブスクリプションマネージャ
<a name="mqtt-demo-cs-subscription-manager"></a>

デモでは複数のトピックを使用するため、サブスクリプションマネージャは、サブスクライブされたトピックを一意のコールバックまたはタスクに関連付けるのに役立ちます。このデモのサブスクリプションマネージャはシングルスレッドであるため、複数のタスクで同時に使用しないでください。このデモのサブスクリプションマネージャ関数は MQTT エージェントに渡されるコールバック関数からのみ呼び出され、エージェントタスクのスレッドコンテキストでのみ実行されます。

## シンプルなサブスクライブ発行タスク
<a name="mqtt-demo-cs-sub-pub"></a>

[prvSimpleSubscribePublishTask](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/simple_sub_pub_demo.c#L447-L569) の各インスタンスは、MQTT トピックへのサブスクリプションを作成し、そのトピックに対する発行オペレーションを作成します。複数の発行タイプを示すために、偶数番のタスクでは QoS 0 (発行パケットの送信時に完了) が使用され、奇数番のタスクでは QoS 1 (PUBACK パケットの受信時に完了) が使用されます。