

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

# AWS IoT Device Shadow デモアプリケーション
<a name="shadow-demo"></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="shadow-demo-introduction"></a>

このデモでは、 AWS IoT Device Shadow ライブラリを使用して [AWS Device Shadow サービス](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html)に接続する方法を示します。を使用して MQTT ブローカーへの TLS (相互認証) による AWS IoT MQTT 接続[coreMQTT ライブラリ](coremqtt.md)を確立し、coreJSON AWS ライブラリパーサーを使用して Shadow サービスから受信したシャドウドキュメントを解析します。デモでは、シャドウドキュメントの更新方法やシャドウドキュメントの削除方法など、基本的なシャドウオペレーションについて説明します。また、 AWS IoT Device Shadow サービスから送信されるメッセージ (シャドウ `/update` や `/update/delta` メッセージなど) を処理するために coreMQTT ライブラリを使ってコールバック関数を登録する方法も示します。

このデモは、シャドウドキュメント (状態) の更新要求と更新レスポンスが同じアプリケーションによって行われるため、学習演習としてのみ意図されています。現実的な本番シナリオでは、デバイスが現在接続されていない場合でも、外部アプリケーションによってデバイスの状態の更新がリモートで要求されます。デバイスは、接続時に更新要求を承認します。

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

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

デモでは、シャドウ `/update` と `/update/delta` コールバックを示す一連の例をループする 1 つのアプリケーションタスクを作成して、リモートデバイスの状態を切り替えます。新しい `desired` 状態のシャドウアップデートを送信し、デバイスが新しい `desired` 状態に応答して `reported` を変更するまで待ちます。さらに、シャドウ `/update` コールバックは、変化するシャドウの状態を出力するために使用されます。このデモでは、MQTT ブローカーへの安全な AWS IoT MQTT 接続も使用し、デバイスシャドウに `powerOn`状態があることを前提としています。

このデモでは以下のオペレーションを実行します。

1. `shadow_demo_helpers.c` のヘルパー関数を使用して MQTT 接続を確立します。

1.  AWS IoT Device Shadow ライブラリで定義されたマクロを使用して、デバイスシャドウオペレーションの MQTT トピック文字列を組み立てます。

1. デバイスシャドウの削除用に使用する MQTT トピックに公開して、既存のデバイスシャドウを削除します。

1. `shadow_demo_helpers.c` のヘルパー関数を使って、`/update/delta`、`/update/accepted`、`/update/rejected` の MQTT トピックをサブスクライブします。

1. `shadow_demo_helpers.c` のヘルパー関数を使って `powerOn` の望ましい状態を公開します。これにより、デバイスに `/update/delta` メッセージが送信されます。

1. で受信 MQTT メッセージを処理し`prvEventCallback`、Device Shadow ライブラリ () で定義された関数を使用して、メッセージが AWS IoT デバイスシャドウに関連しているかどうかを判断します`Shadow_MatchTopic`。メッセージがデバイスシャドウ `/update/delta` メッセージの場合、メインのデモ関数が 2 つ目のメッセージを発行して、報告された状態を `powerOn` に更新します。`/update/accepted` メッセージを受信した場合、以前更新メッセージで発行されたものと `clientToken` が同じか確認します。これでデモは終了です。

![シャドウデモ端末の出力](http://docs.aws.amazon.com/ja_jp/freertos/latest/userguide/images/shadow-demo-output.png)


デモはファイル `{{freertos}}/demos/device_shadow_for_aws/shadow_demo_main.c` または [GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c) で手に入ります。

次のスクリーンショットは、デモが成功したときに予想される出力です。

![成功した場合のシャドウデモ端末の出力](http://docs.aws.amazon.com/ja_jp/freertos/latest/userguide/images/shadow-demo-screenshot.png)


## AWS IoT MQTT ブローカーに接続する
<a name="shadow-demo-connect-mqtt"></a>

 AWS IoT MQTT ブローカーに接続するには、 `MQTT_Connect()`と同じ方法を使用します[coreMQTT Mutual Authentication デモ](mqtt-demo-ma.md)。

## シャドウキュメントを削除する
<a name="shadow-demo-delete-document"></a>

シャドウドキュメントを削除するには、 AWS IoT Device Shadow ライブラリで定義されたマクロを使用して、空のメッセージ`xPublishToTopic`で を呼び出します。これは `MQTT_Publish` を使用して `/delete` トピックに公開します。次のコードセクションでは、これを `prvShadowDemoTask` 関数で実行する方法を示します。

```
/* First of all, try to delete any Shadow document in the cloud. */
returnStatus = PublishToTopic( SHADOW_TOPIC_STRING_DELETE( THING_NAME ),
                               SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
                               pcUpdateDocument,
                               0U );
```

## シャドウトピックをサブスクライブする
<a name="shadow-demo-subscribe"></a>

Device Shadow トピックをサブスクライブして、シャドウの変更に関する通知を AWS IoT ブローカーから受信します。Device Shadow のトピックは、Device Shadow ライブラリで定義されているマクロによって組み立てられます。次のコードセクションでは、これを `prvShadowDemoTask` 関数で実行する方法を示します。

```
/* Then try to subscribe shadow topics. */
if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
}

if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
}

if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
}
```

## シャドウの更新を送信する
<a name="shadow-demo-send-updates"></a>

シャドウアップデートを送信するために、Device Shadow ライブラリで定義されるマクロを使用して、JSON 形式のメッセージ付きの `xPublishToTopic` を呼び出します。これは `MQTT_Publish` を使用して `/delete` トピックに公開します。次のコードセクションでは、これを `prvShadowDemoTask` 関数で実行する方法を示します。

```
#define SHADOW_REPORTED_JSON    \
    "{"                         \
    "\"state\":{"               \
    "\"reported\":{"            \
    "\"powerOn\":%01d"          \
    "}"                         \
    "},"                        \
    "\"clientToken\":\"%06lu\"" \
    "}"
snprintf( pcUpdateDocument,
          SHADOW_REPORTED_JSON_LENGTH + 1,
          SHADOW_REPORTED_JSON,
           ( int ) ulCurrentPowerOnState,
           ( long unsigned ) ulClientToken );

xPublishToTopic( SHADOW_TOPIC_STRING_UPDATE( THING_NAME ),
                 SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
                 pcUpdateDocument,
                 ( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
```

## シャドウデルタメッセージとシャドウ更新メッセージを処理する
<a name="shadow-demo-delta-and-update"></a>

ユーザーコールバック関数は `MQTT_Init` 関数を使って [coreMQTT クライアントライブラリ](https://www.freertos.org/iot-device-shadow/device-shadow-demo.html#handle-shadow-messages) に登録され、受信パケットイベントを通知します。コールバック関数については、GitHub の「[prvEventCallback](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L671-L753)」を参照してください。

コールバック関数は受信パケットが `MQTT_PACKET_TYPE_PUBLISH` のタイプであることを確認し、Device Shadow ライブラリ API `Shadow_MatchTopic` を使用して、受信メッセージがシャドウメッセージであることを確認します。

受信メッセージが `ShadowMessageTypeUpdateDelta` タイプのシャドウメッセージである場合、[prvUpdateDeltaHandler](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L464-L580) を呼び出してこのメッセージを処理します。ハンドラ `prvUpdateDeltaHandler` が coreJSON ライブラリを使用してメッセージを解析し、`powerOn` 状態のデルタ値を取得し、これをローカルで保持されているデバイスの現在の状態と比較します。これらが異なる場合、シャドウドキュメントの `powerOn` 状態の新しい値を反映するようにローカルデバイスの状態が更新されます。

受信メッセージが `ShadowMessageTypeUpdateAccepted` タイプのシャドウメッセージである場合、[prvUpdateAcceptedHandler](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L584-L667) を呼び出してこのメッセージを処理します。ハンドラ `prvUpdateAcceptedHandler` は coreJSON ライブラリを使用してメッセージを解析し、メッセージから `clientToken` を取得します。このハンドラ関数は、JSON メッセージのクライアントトークンが、アプリケーションで使用されるクライアントトークンと一致するかチェックします。一致しない場合、関数は警告メッセージをログに記録します。