そもそもJetsonという製品群はエッジでモデルのトレーニングもできてしまうようなデバイスなので簡単なことであればクラウドは必要ないかもしれません。
Jetsonの強みはエッジで機械学習できることなので、クラウドへセンサーデータを送り推論みたいなことは必要はないし、低いレイテンシが求められるときはNGいかもと思います。ただデバイスやセンサーの数が多くなると管理はやっぱりクラウドでしたいですよね。
AWS IoTにはDevice Shadowという機能があります。これは簡単に言うとデバイスの状態保存&取得できる機能です。デバイスの状態というのはライトのon/offなどです。
このDevice ShadowもGreengrassを使うことでエッジへもっていくことができます。
というわけで今回はDevice Shadowの検証なので、Jetson Nanoとほとんど関係ありあません。
ドキュメントのモジュール5: Device Shadowの操作を参考に検証していきます。
1. 構成
今回の構成はこんな感じ。
今回はDevice Shadowの検証なので実際にセンサーや機械学習のモデルなどは用意しませんでしたが、ドアの開閉を実行するデバイスと開閉を制御するアプリケーションの乗ったデバイスがある想定です。
アプリケーションがDevice Shadowで管理されるドアの開閉状態を更新するという想定です。
ドキュメントにもありますがIoT Greengrass Coreはゲートウェイとなるデバイスにデプロイし、それ以外のデバイスはデバイス間の通信でIoT Greengrass Coreを利用するといった構成が想定されているようです。わかりませんが。
この構成では真ん中のデバイスにIoT Greengrass Coreがデプロイされています。各デバイスはこのデバイスを通じて通信します。
構成図通りにやろうとするとデバイスが3つ必要ですが、、、今回は1つのJetson Nano上でそれぞれのプログラムを動かすことにします。。。
2. 準備
2-1. 「デバイス」の作成
まずはAWS IoTのコンソールから「デバイス」を作成します。今回は「door01」「door_controller01」という名前でデバイスを作成します。
対象のGreengrassグループの「デバイス」一覧から作成開始。
「新しいデバイスの作成」をクリック。
デバイス名を入力。
「デフォルトを使用」します。Coreデバイス上でプログラムを実行するのでルートCAはCoreデバイスでしようしているものを流用します。後述しますがローカルシャドウでのやり取りになるので、GreengrassグループのCAを別途取得して利用することとなります。
証明書等のtar.gzをダウンロードして完了。
2つとも作成できたらこんな感じで一覧に表示されます。
2-2. サブスクリプションの作成
次にサブスクリプションを作成します。
Device ShadowはMQTTトピックを使用してデバイスの状態を取得・更新します。
Device Shadowで使用するトピックはAWSによりあらかじめ予約されています。
必要なサブスクリプションはドキュメントに記載があります。
今回の構成で簡記すると以下になります。
ソース | ターゲット | トピック名 |
---|---|---|
door_controller01 | Local Shadow Service | ~door01/update |
Local Shadow Service | door_controller01 | ~door01/update/accept |
Local Shadow Service | door_controller01 | ~door01/update/reject |
door01 | Local Shadow Service | ~door01/update |
Local Shadow Service | door01 | ~door01/update/delta |
Local Shadow Service | door01 | ~door01/update/accept |
Local Shadow Service | door01 | ~door01/update/reject |
対象のGreengrassグループの「サブスクリプション」一覧から作成開始。
ソースとターゲットを選択。
トピックフィルターにトピック名を入力。
完了。
全部作るとこんな感じ。
デバイスとサブスクリプションの設定をデプロイします。Jetson Nano上でコアソフトウェアが起動していることが前提となります。
2-3. AWS IoT Device SDK for Pythonのインストール
今回はPythonを使用します。
PythonからDevice Shadowを利用するのにSDKが必要なので、Jetson Nanoへpipでインストールします。
pip install AWSIoTPythonSDK
2-4. プログラムの用意
さてデバイス上で動かすプログラムを用意します。今回はシャドウのドアの状態更新するプログラムとシャドウから更新されたドアの状態を受け取るプログラムを用意します。前者がドアの開閉を支持するデバイスで、後者がドアを開閉するデバイスにあたるわけです。
作成したプログラム、 door.py
と door_controller.py
はGitHubに置いておきました。参考にしてみてください。といっても、ほとんどドキュメントで使ってるサンプルをコピペしただけですが。。。Greengrassでは初心者向けにサンプルが用意されてるので、それを使って手軽に開発できるのがよいです。
ファイル名 | 説明 |
---|---|
door.py | シャドウにてドアの状態の更新があったらそれを受け取り表示します。 |
door_controller.py | 30秒ごとにドアの状態を更新します。ドアの状態は「open」と「close」の2種類でこれを交互にトピックへ送信します。 |
以下、注意点です。
- Greengrassコアのトピックと通信するためにはグループCAが必要になります。サンプルと同様にそれぞれのプログラムが最初に走った時にグループCAをAWS IoTから取得する処理を入れています。AWS IoTとの通信はインターネットを経由するため、インターネットと通信できない環境で稼働させるときはあらかじめデバイスにグループCAを置いておく必要があります。もちろんAWS IoT Device SDK for Pythonも。
- 今回、Greengrassコアのエンドポイントは
127.0.0.1
としました。コアが同じデバイスで実行されているためです。別々のデバイスの場合はコアデバイスのIPアドレスを代入するなり取得する処理などいれないといけません。ドメイン名でもいける?
上記のプログラム内のルートCAのパスや証明書のハッシュは各環境に合わせて書き換えてください。
プログラムと証明書をデバイスの同じディレクトリに配置します。
$ ls
xxxxxxxxxx.cert.pem xxxxxxxxxx.cert.pem door_controller.py
xxxxxxxxxx.private.key xxxxxxxxxx.private.key door.py
xxxxxxxxxx.public.key xxxxxxxxxx.public.key
3. 実行
さてターミナルを2つ開いて、1つは door.py
を実行します。もう一方は door_controller.py
を実行します。
まずは door.py
を実行します。シャドウの更新がないため何も表示されません。
次に door_controller.py
を実行します。シャドウへ送信されたドアの状態が表示されます。
そして door.py
を実行中のターミナルを確認すると、状態が更新されていることがわかります。
もう少し、このDevice Shadowについて説明しておくと、、、
今回の場合以下のような流れの繰り返しになっています。 Divice Shadowは以下の desired
delta
reported
でデバイスの状態を保持しているというわけです。
- door_controller01がdoor01のあるべき状態
desired
を更新。 - 実際のdoor01の状態
reported
とdesired
が異なるためdelta
が更新。 delta
の更新をdoor01が受け取り、reported
を更新。
まとめ
いかがでしたでしょうか。デバイスの状態を管理できるDevice Shadowという機能のご紹介でしたが、Greengrassを利用することでこの機能もエッジで利用することができます。つまりインターネットにつながりにくい場所でもこの機能が利用できるということです。
Yusuke Mine(書いた記事を見る)
I get drunk but it's not enough 'Cause the morning comes and you're not my baby.