AWS IoT Core検証メモ④：IoT shadow について

公式ドキュメント
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-device-shadows.html

## IoT shadowとは(引用に)
IoT shadowはデバイスの状態をAWS IoT Core上に記録してデバイス状態などを監視するための機能。状態には主に”reported”、”desired”の2つの要素がある。公式ドキュメントでは以下のような説明がされています。


>”desired”： アプリは、desired オブジェクトを更新することによって、デバイスプロパティの desired 状態を指定します。
アプリケーションとして期待する状態を示すのに使用します。アプリケーションで状態の変更要求を出す場合は、この状態を更新します。

>“reported”： デバイスは、reported オブジェクト内の現在の状態を報告します。デバイス自身がどういった状態なのかを示すのに使用します。この状態を変更するのは基本的にはデバイス自身です。


って言われてもなんかぱっとしないと思うので、まずは簡単な使い方をユースケースを交えながら説明していきたいと思います。

## IoT shadowの使いどころ

### ユースケース
例えば、工場で動いてる機械の稼働状況を監視するデバイスがあったとします。
そのデバイスから機械の稼働状況を受け取る管理用プログラムがあるとします。

こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/965758c6-8a94-86ca-9cdf-36235ba9607f.png)

10分毎にデバイスから機械の動作情報データをネットワーク越しで管理用プログラムに送り、送られてきたデータの筐体内温度が70℃を超えていた場合は、稼働状況を詳細に確認したいのでデータの送信頻度を１分毎に送信させるように変更を指示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/0fb49f21-6114-ec12-7539-c8f5a5d6b112.png)

今回はAWS IoTを使わない場合とAWSIoTとIoT shadowを使った場合の構成を考えて比較していきたいと思います。
#### AWSIoTを使わない構成
デバイスと管理プログラムが直接やり取りする場合、
デバイスと管理プログラム間は直接セッションをつないで接続を保つ必要があると思います。

この例の場合、デバイスに対してポーリング間隔の変更を指示したいときに、デバイス側のネットワークが不安定だった場合は管理プログラム側からデバイスへセッションが復帰するまで
常にセッションが回復するのを監視する必要が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/08df62f1-9820-5937-3e12-6656de64fa2e.png)

そのため、ネットワーク越しにデバイスの状況などを管理するにはデバイスと管理用プログラムが密結合な構成になると思います。

#### AWSIoTとIoT shadowを使う場合
ここにAWSIoTのIoT shadowの機能があると何ができるか、この構成を踏まえてお話していきたいとおもいます。

とりあえず先ほどのの構成にIoT shadowを入れてみるとこんなイメージ  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/09f80d64-32e9-143d-b8a3-cd425727e1b1.png)


デバイスと管理プログラムがIoT shadowを仲介して通信をする構成になります。
デバイス側からの報告と管理プログラム側がからの要求がIoT shadowに記録されるようになります。

これだけだとよくわかんないですよね。
とりあえずIoT shadowの中で定義されている内容を見てみましょう。

~~~JSON
{
  "state": {
　　//管理プログラム側からの指示内容
    "desired": {
      "PollingInterval": "60"
    },
　　//デバイスからの報告内容
    "reported": {
      "PollingInterval": "600"
    },
　　//それぞれの内容の差分
    "delta": {
      "PollingInterval": "60"
    }
  },
  "metadata": {
　　//各データの最終タイムスタンプ
    "desired": {
      "PollingInterval": {
        "timestamp": 1444490744
      }
    },
    "reported": {
      "PollingInterval": {
        "timestamp": 1444490470
      }
    }
  },
  "version": 2,
  "timestamp": 1444490781
}
~~~
これがIoT shadowに記録されている内容の中身で、デバイスの現状の設定と管理プログラムからの指示内容が記載されています。

デバイス側はIoT shadowにreportedとして現状の報告をします。

~~~
"reported": {
      "PollingInterval": "600"
    },
~~~

この例で行くと"PollingInterval": "600"となっているので、デバイス側からは600秒に一回データをポーリングしてAWSIoTに送信していることを表しています。


管理アプリ側はIoT shadowにdesiredとしてデバイスに行ってもらいたい指示を出します。

~~~
"desired": {
      "PollingInterval": "60"
    },
~~~

この例だと"PollingInterval": "60"になっているので、管理プログラム側からは
デバイスに対して60秒に一回データを送信するよう指示を出しています。

デバイス側からの報告と管理プログラム側からの指示の内容に差分が出てる場合はdeltaにデバイスに適用させるべき管理プログラム側からの指示が抽出されます。

~~~
"delta": {
      "PollingInterval": "60"
    }
~~~

このIoT shadowの内容を見ると現状のデバイスはポーリング間隔が600秒になってるのに対して、管理プログラム側は60秒にポーリング間隔を設定しようとしているのが分かると思います。

デバイス側はこのIoT shadowのdeltaの内容を確認することで、管理プログラム側からの指示と現状の動作に差が出ていないかを容易に判断することができます。

deltaの内容がデバイス側で処理され、管理プログラム側とデバイス側の値(PollingInterval)が一致するようになった時はIoT shadowは以下のような形に変化します。

~~~JSON
{
  "state": {
　　//管理プログラム側からの指示内容
    "desired": {
      "PollingInterval": "60"
    },
　　//デバイスからの報告内容
    "reported": {
      "PollingInterval": "60"
    }
   //desiredとreportedが一致するのでdeltaは無くなる
  },
  "metadata": {
　　//各データの最終タイムスタンプ
    "desired": {
      "PollingInterval": {
        "timestamp": 1444490744
      }
    },
    "reported": {
      "PollingInterval": {
        "timestamp": 1444490470
      }
    }
  },
  "version": 4,
  "timestamp": 1444490781
}
~~~

このIoT shadowがデバイスと管理プログラムの間にあることで何が良いかというと、
IoT shadowが設定されているとデバイスからの情報や管理プログラムからの指示がこのIoT shadowに記録されるため、デバイスの通信が不安定な場合でも管理プログラムはIoT shadowに報告された内容を確認することでデバイスの状況を確認でき、デバイス側も通信が安定したときにIoT shadowを確認すれば管理プログラムからの指示を確認できるので、通信が復活するまで常にデバイスからの疎通が通ってるか監視をする等の処理が不要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/5f1040c8-3b85-f68e-7a9b-21d2e4bc8b51.png)

また、タイムスタンプの更新などをIoTruleを使って監視しておけばデバイスからの通信が復旧しない際に担当者に通知を送る等といったアクションを起こすことも可能となります。


IoT shadowの更新はメッセージと同じくMQTT、RESTで更新が可能です。
MQTTでデバイスAWS IoT Core間をの基本的な通信を行って、デバイス状態の報告はRESTを使ってIoT shadowに書き込むといったことも可能です。

## IoT shadowの利点

デバイスから何かしらデータを受け取るだけでなく、デバイスとの双方向通信を行ってデバイスへの指示を行うような構成をAWSIoTの環境で作成するためにはIoT shadowの機能を活用することが必要になります。

通信が安定しないような環境にデバイスを設置するような場合もあると思います。
この機能を上手く使うことができれば、デバイスと管理プログラム等の間で常に通信が必要な場合でも、疎結合な構成にすることができます。

次回は自動的にデバイスの認証情報を生成することができる[ FleetProvisioning ]について検証を行っていきます。 
[AWSAWS IoT Core検証メモ⑤：FleetProvisioningについて](https://qiita.com/tomzono/private/28de3d68d3bf4bd2e03b)

---
[AWSAWS IoT Core検証内容一覧へ](https://qiita.com/tomzono/private/eaa786b6a1889351c752)