AWS
awsIoT

AWS IoT device managementのJob機能の動きをデバイス視点で見てみる

はじめに

公式ページはこちらになります。(2018/1/20時点では英語のマニュアルのみとなっております)
同じく、投稿時点では、javascript IoT Device SDKはjobの処理が入っているようですが、pythonなどはまだSDKに入っていないようですので、本説明にあわせてご自分でシーケンスをコードで表現する必要があるようです。
デバイス側でどういったことを考えてシーケンスを書くかや、request/responseのjsonについての理解が深まるようにまとめようと思います。

デバイスが意識すべきjob用のtopic

以下、topoic中の{}で区切ったものは変数となるものです。 device名やjobIdなど。

job情報取得で使えるtopic

新規job待受用のsubscribe topic

  • $aws/things/{thingName}/jobs/notify
  • $aws/things/{thingName}/jobs/notify-next

新規jobが作成されると下記2つにpublishされます。つまり新規jobを受け取るために、動作中のデバイスがsubscribeしたままにすべきtopicということになります。2つのtopicの情報の差を含めて見ましょう。

$aws/things/{thingName}/jobs/notify
=> job一覧入ってきます。jobDocumentはありません。

{
  "timestamp": unixtime,
  "jobs": {
    "IN_PROGRESS": [
      {
        "jobId": "作成したjob名",
        "queuedAt": unixtime,
        "lastUpdatedAt": unixtime,
        "startedAt": unixtime,
        "executionNumber": 1,
        "versionNumber": 3
      }
    ],
    "QUEUED": [
      {
        "jobId": "作成したjob名",
        "queuedAt": unixtime,
        "lastUpdatedAt": unixtime,
        "startedAt": unixtime,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}

$aws/things/{thingName}/jobs/notify-next
=> 次にやるべきjob情報のみが、通知されます。
jobDocumentにある、test:testは job生成時に指定したS3のjob fileの中身(json)が入っています。

{
  "timestamp": unixtime,
  "execution": {
    "jobId": "job名",
    "status": "QUEUED",
    "queuedAt": unixtime,
    "lastUpdatedAt": unixtime,
    "versionNumber": 1,
    "executionNumber": 1,
    "jobDocument": {
      "test": "test"
    }
  }
}

注意:通知対象のdeviceに"IN_PROGRESS"のstatusがある場合、notify-nextは発行されません。
複数の処理を通知して、デバイス側でupdate処理が重複しないための考慮だと思います。

この場合、デバイスが "testjob-20180120-00" のtaskの終了通知(後述のupdate通知をSUCCEEDEDでpublish)すると、AWS IoTがnotify-nextへ通知します。

能動的にjob statusを確認するためのtopic

起動時などにjobを確認する用途 publishすると、acceptedへ返却される

  • $aws/things/{thingName}/jobs/get (publish)
  • $aws/things/{thingName}/jobs/get/accepted (publish前にsubscribeしておく)

上記の通り、シーケンスとしては acdepted topicを先にsubscribeしてから、get topicへpublishすることとなります。acceptedへのsubscribeへの返却は以下のようなjsonとなります。先に説明したnotifyと少しjsonフォーマットが異なりますが、取得できる内容はほぼ同じです。
こちらはデバイスが起動したばかりなどで前回の終了状態が分からない場合や電源off時などにupdateが来ていないかなど、最初にチェックするような用途になるかと思います。

{
  "timestamp": unixtime,
  "inProgressJobs": [],
  "queuedJobs": [
    {
      "jobId": "Job名",
      "queuedAt": unixtime,
      "lastUpdatedAt": unixtime,
      "executionNumber": 1,
      "versionNumber": 1
    }
  ]
}

deviceがAWS IoTにreportするためのtopic

$aws/things/thingName/jobs/jobId/update
requestのjson format

{
  "status": ["IN_PROGRESS", "FAILED", "SUCCEEDED", "REJECTED"],
  "statusDetails": {
    "progress": "0%"
  },
  "expectedVersion":"",
  "clientToken":""
}

statusは上記の4つの状態のみを指定可能
statusDetailsのjsonについては自由に記載できます。ここでは例として"progress"としています。
管理者視点で見ると、統計などが見れる機能があるので、デバイス側のupdate処理内で定期的に呼び出して置くと良いかと思います。

AWS IoTのテスト画面を使っての動作確認

device想定のsubscribe設定

AWSのマネージメントコンソールから、AWS IoTを選択し左側メニューの "Test" を選択します。
Subscription topicへ"$aws/things/+/jobs/#"を入力し、subscribe to topicを押下して、受信状態のままにしておきます。

意味を説明すると$aws/things/(+ = すべてのthingName)/jobs/(# = ここ以下すべてのレイヤtopic)
を受信することになります。

スクリーンショット 2018-01-21 21.39.56.png

test Jobの作成

事前作業

AWS IoTの作成

今回は、AWS IoTのテスト画面しか使わないので名前だけあれば良いです。(証明書やpolicyなどは使いません)
本投稿では qiita-thing としています。

job通知のjsonドキュメント配置

S3へjsonドキュメントを置きます。このjsonドキュメントがjobのjobDocumentとして通知されます。
ここでは、 {"test":"test"}としておいておきます。

AWS IoTからjob作成

先程の受信状態のコンソールをそのままにして別タブなどでもう一つ AWS IoT画面を開き、Manage => Jobsを選択します。画面右上にあるCreateを押下して、jobの作成をしてみます。

Select a job で、Create custom jobを選択。次の画面で以下を設定
- Job IDに qiita-test
- device updateに、先程作ったthingを一つ選択、
- job fileに 先程おいたS3のjson fileを選択
- job typeに snapshotを選択
createを実行。createを実行するとjob通知が自動で発行されます。

通知の確認とupdateで通知

AWS IoTのtest画面の方に戻ります。
先程のjob作成でsubscribeにnotifyとnotify-nextの通知がきています。
スクリーンショット 2018-01-21 22.09.31.png

本test画面の Publish の topicを以下とします。
$aws/things/qiita-thing/jobs/qiita-test/update

updateのpayloadに以下を設定

{
  "status": "IN_PROGRESS",
  "statusDetails": {
    "progress": "0%"
  },
  "expectedVersion":"",
  "clientToken":""
}

状態を確認

Publishのtopicを以下に変更して、publishを実行します。
$aws/things/qiita-thing/jobs/get
mqttのpayloadは設定しなくともよいです。

test画面のsubscribeの画面に以下が表示されました。想定通り、queueからinProgressへ変化しています。

{
  "timestamp": 1516540819,
  "inProgressJobs": [
    {
      "jobId": "qiita-test",
      "queuedAt": 1516540026,
      "lastUpdatedAt": 1516540699,
      "startedAt": 1516540699,
      "executionNumber": 1,
      "versionNumber": 2
    }
  ],
  "queuedJobs": []
}

AWS IoTコンソールのjob詳細画面もin progressとなっています。
スクリーンショット 2018-01-21 22.28.08.png

複数jobを通知してみる

notifyとnotify-nextの動きを確認するために、再度jobを作成して送信してみます。
jobIdは qiita-test-2としてみます。それ以外は先程同じにしています。

説明済みですが、notifyのみが通知されました。

{
  "timestamp": 1516541383,
  "jobs": {
    "IN_PROGRESS": [
      {
        "jobId": "qiita-test",
        "queuedAt": 1516540026,
        "lastUpdatedAt": 1516540699,
        "startedAt": 1516540699,
        "executionNumber": 1,
        "versionNumber": 2
      }
    ],
    "QUEUED": [
      {
        "jobId": "qiita-test-2",
        "queuedAt": 1516541383,
        "lastUpdatedAt": 1516541383,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}

最初のjobを完了させてみる

updateの通知と同様の手順で以下のtopicに payloadを"SUCCEEDED"として送信してみます。

topic : $aws/things/qiita-thing/jobs/qiita-test/update

{
  "status": "SUCCEEDED",
  "statusDetails": {
    "progress": "100%"
  },
  "expectedVersion":"",
  "clientToken":""
}

完了通知に合わせて自動でnotifyとnotify-nextが送られてきました。
ということで、notify-nextをsubscribeしておけば良いことがわかります。
スクリーンショット 2018-01-21 22.37.56.png

雑にDeviceの想定するシーケンス図

スクリーンショット 2018-02-22 22.46.25.png

まとめ

ということで、AWS IoTのdevice managementのjob機能についてdeviceの観点で簡単に整理してみました。実際にはjob documentのデザイン(プログラムDLのS3 urlをセット)やプログラム更新をする部分というところがdevice updateの本質なので、主にシーケンス/request方法についての説明となりますが、AWS IoT側でこのくらい作られていれば、device updateプログラムの開発に集中出来るのではないでしょうか?

免責

本投稿は、個人の意見で、所属する企業や団体は関係ありません。
ご自身でもドキュメントの確認や、動きを確認してからの利用をおすすめします。