AWS IoT Device SDK for Pythonを使ってAWS IoTのジョブ機能を試してみる

ファームウェアの更新などで複数台のデバイスまとめて同じ命令を実行したいことがあると思います。それを実現するためのジョブという機能がAWS IoTにはサポートされています。AWS IoT Device SDK for Pythonにジョブのサンプルプログラムが提供されているので、それを使ってAWS IoTのジョブ機能を試してみたいと思います。
2018.09.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

ファームウェアの更新などで複数台のデバイスまとめて同じ命令をしたい事があると思います。

それを実現するためのジョブという機能がAWS IoTにはサポートされています。

AWS IoT Device SDK for Pythonにはジョブのサンプルプログラムが提供されているので、それを使ってAWS IoTのジョブ機能を試してみたいと思います。

機能検証を行うにあたりデバイスとして今回、1台のラズパイを利用します。

ジョブ機能とは

AWS IoTに接続された、1つ以上のデバイスに一連のリモート操作を定義できます。たとえば、あるグループに属するデバイスに対して、アプリケーションやファームウェア更新のダウンロードとインストール、再起動、証明書のローテーション、またはリモートトラブルシューティングオペレーションの実行を指示するジョブを定義できます。

https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-jobs.html

環境

  • RaspberryPi 3 Model B
  • Linux raspberrypi 4.9.30-v7+ #1001 SMP Fri May 26 16:09:18 BST 2017 armv7l GNU/Linux
  • aws-iot-device-sdk-python:v1.4.0
  • python2.7

事前準備

下記ブログを参考に、RaspberryPiからAWS IoTへと通信できるようにしておいてください。

AWS IoT Device SDK for Pythonを使ってRaspberryPiとAWS IoTをつないでみる

ラズパイ側に配置した証明書類は下記のように構造にしています。

├── cert <= ディレクトリ作成
│   ├── cert.crt <= 接続時に利用する証明書を設置
│   ├── private.key <= 接続時に利用する証明書を設置
│   ├── public.key <= 接続時に利用する証明書を設置
│   └── rootCA.pem <= 接続時に利用する証明書を設置
├── samples
│   ├── ThingShadowEcho
│   │   └── ThingShadowEcho.py
│   ├── basicPubSub
│   │   ├── basicPubSub.py
│   │   ├── basicPubSubAsync.py
│   │   ├── basicPubSub_APICallInCallback.py
│   │   └── basicPubSub_CognitoSTS.py
│   ├── basicShadow
│   │   ├── basicShadowDeltaListener.py
│   │   └── basicShadowUpdater.py
│   ├── greengrass
│   │   └── basicDiscovery.py
│   └── jobs
│       └── jobsSample.py

ジョブドキュメントを作成

デバイス側で実行したい命令を記載したJSON形式のドキュメントを作成します。

今回はテストということで、シンプルな形にしています。

job.json

{
    "job-key": "job"
}

S3にジョブドキュメントを配置

上記で作成した、ジョブドキュメントをS3バケットに配置しておきます。

AWS IoTでジョブを作成

▼ジョブから作成を選択します。

▼カスタムジョブの作成を選択します。

▼ジョブID、ジョブを適用するデバイス、ジョブドキュメントを指定します。

今回はテストということで、ジョブを適用するのは1台のラズパイとしています。

▼ジョブタイプをスナップショットに設定して、ジョブを作成します。

▼作成されたジョブを確認してみます。

ジョブの進行状況がわかります。

ラズパイ側でサンプルプログラムを実行してみる

注意点として、通常とエンドポイントが異なります。ジョブ用のエンドポイントを確認しておき、それを指定する必要があります。

$ aws iot describe-endpoint --endpoint-type iot:Data { "endpointAddress": "xxxxxxxxx.iot.ap-northeast-1.amazonaws.com" }

では、サンプルプログラムを実行してみます。

$ ls
jobsSample.py


$ python jobsSample.py \
-e xxxx.iot.ap-northeast-1.amazonaws.com \
-r ../../cert/rootCA.pem \
-c ../../cert/cert.crt \
-k ../../cert/private.key \
-n <thing name>

.
.
.

2018-09-24 23:08:19,341 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
Starting to process jobs...
2018-09-24 23:08:19,353 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
2018-09-24 23:08:19,355 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
2018-09-24 23:08:19,402 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
2018-09-24 23:08:19,404 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event
2018-09-24 23:08:19,405 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
2018-09-24 23:08:19,405 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-09-24 23:08:19,406 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
2018-09-24 23:08:19,407 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] event
Executing job ID, version, number: test-job, 2, 1
With jobDocument: {"job-key": "job"}
2018-09-24 23:08:19,410 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
2018-09-24 23:08:19,411 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-09-24 23:08:19,413 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
2018-09-24 23:08:19,445 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
2018-09-24 23:08:19,447 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event
2018-09-24 23:08:19,448 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
2018-09-24 23:08:19,449 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-09-24 23:08:19,450 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
2018-09-24 23:08:19,451 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] event
2018-09-24 23:08:19,452 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-09-24 23:08:19,759 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event
2018-09-24 23:08:19,760 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] event
Notify next saw no execution
2018-09-24 23:08:19,763 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
Done processing jobs
Stats: {"jobsSucceeded": 1, "jobsStarted": 1, "jobsRejected": 0}
2018-09-24 23:08:21,356 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync disconnect...
2018-09-24 23:08:21,357 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing async disconnect...
.
.
.

26行目のjob ID, version, number: test-job, 2, 1は「test-job」がジョブID、「2」がバージョン、「1」が実行番号となります。

27行目で{"job-key": "job"}が出力されており、設定したジョブドキュメントをデバイス側(ラズパイ側)で取得できていることがわかります。実際はここのところで、アプリケーションやファームウェア更新のダウンロードとインストール、再起動、証明書のローテーションなどの処理を実装していくことになると思います。

▼AWS IoTのマネージメントコンソールからジョブのステータスを確認してみると、こちらも「成功」となっています。

さいごに

いかがだったでしょうか。

とりあえず動かしてみたという感じですが、ラズパイとAWS IoT Device SDK for Pythonを使ってAWS IoTのジョブ機能を試してみました。次回はもっと実践的な内容を想定して試してみたいと思います。

誰かの参考になれば幸いです。