翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
coreMQTT 接続共有デモ
重要
これは、FreeRTOS リリース 202012.00 で使用する FreeRTOS ユーザーガイドのアーカイブ版です。このドキュメントの最新バージョンについては、FreeRTOS ユーザーガイドを参照してください。
序章
coreMQTT 接続共有デモプロジェクトでは、マルチスレッドアプリケーションを使用して、クライアントとサーバー間の相互認証で TLS を使用して AWS MQTT ブローカーへの接続を確立する方法を示します。このデモでは、mbedTLS ベースのトランスポートインターフェイスの実装を使用して、サーバーとクライアントの認証 TLS 接続を確立し、QoS 1
注記
FreeRTOS デモをセットアップして実行するには、FreeRTOS の開始方法 の手順に従います。
このデモでは、スレッドセーフなキューを使用して MQTT API を操作するためのコマンドを保持します。このデモでは、注意すべきタスクが 4 つあります。
-
コマンド (メイン) タスクはコマンドキューからコマンドを受け取り、それらを処理します。他のタスクでは、処理対象のコマンドをこのキューに配置します。このタスクはループに入り、その間にコマンドを処理します。終了コマンドを受信すると、このタスクはループから抜け出します。
-
同期パブリッシャータスクは、一連の公開オペレーションを作成し、コマンドキューにプッシュします。これらのオペレーションは、コマンドタスクによって実行されます。このタスクでは同期パブリッシングを使用します。つまり、このタスクは各公開オペレーションが完了するまで待機してから、次の公開をスケジュールします。
-
非同期パブリッシャータスクは、一連の公開オペレーションを作成し、コマンドキューにプッシュします。これらのオペレーションは、コマンドタスクによって実行されます。このタスクは前のタスクと異なり、公開オペレーションが完了するのを待つことなく次のタスクをスケジュールします。すべての公開オペレーションがキューに追加されてから、各公開オペレーションのステータスをチェックします。同期パブリッシングと非同期パブリッシングの違いは、これらのタスクの動作のみであることに注意してください。実際の公開コマンドに違いはありません。
-
サブスクライバータスクは、2 つのパブリッシャータスクが発行するすべてのメッセージのトピックに一致するトピックフィルターへの MQTT サブスクリプションを作成します。このタスクはループに入り、他のタスクによって発行されたメッセージの受信を待ちます。
タスクは、受信したメッセージを保持するキューを持つことができます。コマンドタスクは、受信トピックにサブスクライブされているタスクのキューに受信メッセージをプッシュします。
このデモでは、相互認証を使用した TLS 接続を使用して AWSに接続します。デモ中にネットワークが予期せず切断された場合、クライアントはエクスポネンシャルバックオフロジックを使用して再接続を試みます。クライアントが正常に再接続してもブローカーが前回のセッションを再開できない場合、クライアントは前回のセッションと同じトピックに再度サブスクライブします。
シングルスレッドとマルチスレッド
coreMQTT の使用モデルは、シングルスレッドとマルチスレッド (マルチタスク) の 2 つがあります。このデモでは、独自のマルチスレッドスキームを作成する方法を説明します。エージェント (またはデーモン) タスク内で MQTT プロトコルをバックグラウンドで実行するマルチスレッドの例もあります。詳細については、MWTT エージェントと coreMQTT を使用したデモMQTT_ProcessLoop
関数を呼び出す必要はありません。また、エージェントタスクを使用する場合、ミューテックスなどの同期プリミティブを必要とせずに、複数のアプリケーションタスクが単一の MQTT 接続を共有できます。
ソースコード
デモのソースファイルの名前は mqtt_demo_connection_sharing.c
で、
ディレクトリと GitHubfreertos
/demos/coreMQTT/
機能
このデモでは、合計 4 つのタスクを作成します。そのうち 3 つは MQTT API コールを要求するもの、残り 1 つはそれらのリクエストを処理するプライマリタスクです。このデモでは、3 つのサブタスクを作成し、処理ループを呼び出し、その後クリーンアップするループにプライマリタスクが入ります。プライマリタスクは、サブタスク間で共有されるブローカーへの MQTT 接続を 1 つ作成します。2 つのサブタスクはメッセージをブローカーに発行し、3 つ目のサブタスクは発行されたメッセージのすべてのトピックに一致するトピックフィルターへの MQTT サブスクリプションを使用してメッセージを受信します。
Typedefs
デモでは、次の構造、列挙型、関数ポインタを定義しています。
- コマンド
-
タスクは MQTT API コールを直接行うのではなく、
Command_t
構造を使って、メインタスクに適切な API オペレーションを呼び出すように指示するコマンドを作成します。コマンドには次のタイプがあります。-
PROCESSLOOP
-
PUBLISH
-
SUBSCRIBE
-
UNSUBSCRIBE
-
PING
-
DISCONNECT
-
RECONNECT
-
TERMINATE
TERMINATE
コマンドには対応する MQTT API オペレーションがありません。デモでは、メインタスクにコマンドの処理を停止し、クリーンアップオペレーションを開始するように指示するために使用されます。例えば、公開やサブスクライブ情報などの追加情報が一部の MQTT コマンド (MQTT_Publish
、MQTT_Subscribe
、MQTT_Unsubscribe
など) に必要になるためCommandContext_t
フィールドを使用します。このフィールドはこれら 3 つのコマンドでは必須で、その他のコマンドではオプションです。これらのコマンドにはこのコンテキストが必要であるため、コマンドがキューに配置された後は、コマンドが完了するまでこの値を変更しないでください。コマンドが完了すると、オプションのコールバックを呼び出すことができます。このデモでは、タスク通知を作成するコールバックを使用して、コマンドが完了したことを呼び出し側のタスクに通知します。確認を必要とする MQTT オペレーション (QoS が 0 より大きいサブスクライブ、サブスクライブ解除、公開) の場合、確認が受信されるとコマンドが完了したと見なされます。それ以外の場合は、対応する MQTT API コールが返された時点でコマンド完了です。
mqtt_demo_connection_sharing.c
ファイルに以下の定義があります。-
Command_t
struct -
CommandContext_t
struct -
CommandType_t
enum -
CommandCallback_t
function pointer
-
- 確認
-
一部の MQTT オペレーションは確認を必要とするため、AckInfo_t
の配列を使用します。これには、完了コールバックを呼び出せるように、期待される確認のパケット識別子、それを待機している元のコマンドが含まれます。 - サブスクリプション
-
このデモでは、各タスクのサブスクリプションを追跡できます。そのためには、サブスクリプションを要求する各タスクは、発行されたメッセージを受信するメッセージキューを提供する必要があります (SubscriptionElement_t
)。複数のタスクが同じトピックフィルターにサブスクライブできます。これは、別々のレスポンスキューを使用することが想定されるためです。 - 発行済みメッセージの受信
-
タスクはメインタスクと並行して実行されるため、サブスクライブされた各タスクが受信した公開メッセージを読み取るのを待たなければならないのは、メインタスクにとって難しく時間がかかります。したがって、受信した各メッセージは、発行されたメッセージのトピック (PublishElement_t
) にサブスクライブされているタスクのレスポンスキューにコピーされます。MQTT クライアントから受信した公開パケットにはクライアントのネットワークバッファへのポインタが含まれているため、受信メッセージのペイロードとトピック名は応答キューに挿入される前に別のバッファにコピーされます。この方法では、MQTT クライアントがネットワークバッファを消去した後も、サブスクライブされたタスクは受信した情報を読み取ることができます。
メインタスク
メインアプリケーションタスク RunCoreMQTTConnectionSharingDemoclean session
フラグを設定して接続し、フラグを未設定にして切断して再接続します。処理ループが終了するとブローカから切断され、ネットワークの再接続が行われた時点から再びループします。
デモが正常に完了すると、次の図のような出力が生成されます。

- コマンドループ
-
コマンドループ prvCommandLoop
は、コマンドがコマンドキューに配置されるまで待機してから、適切な MQTT API を呼び出します。 DISCONNECT
とTERMINATE
以外のすべてのコマンドで、MQTT_ProcessLoop
も呼び出されます。このデモでは、ソケットウェイクアップコールバックを設定し、データがソケットで利用可能になったときにPROCESSLOOP
コマンドをキューに送信します。ただし、その時点でキュー内に先行するコマンドが多数存在する可能性があります。他のコマンドが処理されている間に受信データを無視しないようにするには、各コマンドの後にMQTT_ProcessLoop
が 1 回のイテレーションに対して呼び出されます。 - コマンドの処理
-
詳しくは、prvProcessCommand
関数を参照してください。
同期パブリッシャータスク
同期パブリッシャータスク prvSyncPublishTaskPUBLISH
オペレーションを同期的に作成し、各オペレーションが完了するのを待ってから次のオペレーションをスケジュールします。このデモでは QoS 1 を使用してメッセージを公開します。つまり、公開確認パケットが受信されるまで、これらのオペレーションは完了したと見なされません。
非同期パブリッシャータスク
非同期パブリッシャータスク prvAsyncPublishTask
サブスクライバータスク
サブスクライバータスク、prvSubscribeTaskTERMINATE
オペレーションの作成も担当します。