AWS IoT Events は IoT デバイスの「ステートマシン」 ― IoTデバイスの状態管理に使えるサービス


AWS IoT Hero になったので、やっぱ AWS IoT 関連のアウトプットは必要でしょう、ということでお送りしております。

AWS IoT Events は「ステートマシン」

AWS では目的に応じた IoT 向けサービスが数多く存在しています。
その中でも今回取り上げる AWS IoT Events説明で損をしている12素晴らしいサービスですので、皆さんに知ってもらいたいと思い、紹介しています。

以下は AWS IoT Events の実装画面です。見たことありませんか?そうです、「ステートマシン」です。AWS IoT Events はIoTデバイスの状態管理(ステート管理)を行うことができます。

ステートマシンって?

いわゆる「状態遷移(図)」です。
例として挙げられるのが、 OS 内のプロセス遷移です。3 プロセスが New されてから Terminated されるまでの流れが描かれています。

たとえば "Ready" からは決して "Waiting" や "Terminated" に遷移しないとなっているわけです。(もちろん、そうやってコードの実装をする必要があります)

IoT では「状態」が常に発生している

現在はステートレス、システム内部に「状態」を持たずにシステムを作る考え方が、特にサーバレス界隈では常識(要出典)となっています。理由は「スケールしやすい」からです。
ステートレスとステートフルの解説や、ステートレスだとなぜスケールしやすいのかは ステートレスとは何か がわかりやすいのでご覧ください。

話を戻すと、IoT は必ず物理世界に「モノ」があり、モノは常に「状態」を持っています。例えば扉は「開いてる(Open)」と「閉まっている(Close)」のステートがあります。
ここで困るのが、ステートってどこに保存しておこうか? という問題です。

AWS IoT Core の「デバイスシャドウ」をにステートを保存するアプローチ

AWS IoT Core にはデバイスシャドウという、デジタルツイン2の実装ができる機能があり、これをステートの保存先として利用するアプローチが考えられます。

シャドウステータスを更新する方法はクラウド側、デバイス側、それぞれあります。

  • クラウド上から
  • デバイス上から
    • AWS Greengrass (の中の AWS Lambda)

結局 AWS Lambda ってことですね。

「状態」の実装で面倒な事

「状態」をコードで実現しようとすると、面倒なことが 3つ出てきます。

  • コード側
    • どのようなステートが存在するのか?
    • ステートの遷移条件は?
  • ストレージ側
    • ステートをどこにどうやって保存するのか?

このうち、「コード」については、実は GoF の State パターンがあるのですが、ダンプカーでコンビニに行く感覚くらいの実装量になります。
かといって、たとえば "open" から "close" へは遷移できるけど "open" から "open" は遷移できない(無視する)という実装を考えると、必殺 if 文の登場となりますが、ステートが増えた時や遷移条件が変更された時の保守が「うっ」ってなるのは、ちょっと考えれば想像できる話です。

前回どこまで遷移したか(=次回はどの「状態」からスタートするか)を保存しておく「ストレージ」もコードが必要となります。
デバイスシャドウであれば update_thing_shadow() を使いますし、Amazon DynamoDB や Amazon ElastiCache ... まあ色々と考えられますけど、結局コード内に「読みだして、保存する」実装しなければいけませんし、「キーをどうする」とか「データ構造どうしよう」とか、、、もう面倒!!

要するに、面倒なんです。

そこで AWS IoT Events

以下のように「状態 (ステート)」と「遷移条件」を指定することができます。
また、「今回はどの状態まで進んだか = 次回はどこからスタートするか」を保存してくれるうえ、次回のスタート場所を自動的に設定してくれます。

どの様に動作するかは、アニメーションをご覧ください。

遷移時に「アクション」を呼び出すことができる

状態と遷移条件の実装だけでなく、遷移時の「アクション」も指定できます。例えば "open から close に遷移したときに Amazon SNS 経由で通知を送る" といった事もできます。

イベントは onEnter , onInput , onExit の3つです。(ドキュメントはここ)

  • onEnter : その状態になった時に発火
  • onExit : その状態じゃなくなった時に発火
  • onInput : データ入力を受け取ったら発火

基本的には「データを受け取って(onInput)」→「その状態じゃなくなった(onExit)」→「次の状態になった(次の状態の onEnter)」という形で発火していきます。(たぶん)
ますは onEnter を使えばわかりやすく実装できるでしょう。

指定できるアクションは ドキュメント を見てください。

結局 AWS Lambda じゃねぇか!!

そ、そうですね。
とはいえ、Lambda 関数には状態の移行条件の if/switch 文を排除できるので、Lambda 関数自体をステートレスに実装できます。

まさに「Lambda が Lambda であるために!」

AWS IoT Core と AWS IoT Events はどうやって連携する?

AWS IoT Core のルールに "IoT Events 入力にメッセージを送信する" で OK。

ほかにはどんな使い方が?

AWS IoT Events は内部でタイマーを持っており、これをイベントとして発火させることもできるので AWS IoT Events入門 一定期間通信途絶時にイベント発火してみた こんな使い方もできます。

これも状態管理ですね。

検知器(= 要するにステートマシン) のバックアップは CLI が使える

GUI 特有の「バックアップとかどうするんじゃい」問題は AWS CLI を使うことで解決はできます。

$ aws iotevents list-detector-models
{
    "detectorModelSummaries": [
        {
            "detectorModelName": "DoorState",
            "creationTime": 1568089449.837
        }
    ]
}
$ aws iotevents describe-detector-model --detector-model-name "DoorState" > model.json

あとは aws iotevents create-detector-modelmodel.json から復元する形となります。(ごめん、ここは未検証)

まとめ

AWS IoT Events はステートマシーンです。

ステート管理は AWS IoT Events に任せ、その他のロジックは別で(っていうか、実質 AWS Lambda)と役割を分離しよう。

AWS IoT Events は検知器(要するにステートマシン)の実行回数で課金される、完全従量課金モデルなので、いつデータが発生するかわからないような IoT デバイスと相性が抜群に良いかと思います。

あとがき

じつはこれ、JAWS-UG 広島 14回目@酒まつりの時に、ピンチヒッターとして登壇したときのネタなんです。。。使いまわしでスマセンスマセン。
今回あらたにアニメーション作ったから許してください。

当時のスライドはこちらです。悪天候で本当に大変でしたよね。。。でも楽しかった!!

Speaker Desk / AWS IoT Events はステートマシンですから。

これからも AWS IoT Hero の名に恥じぬような情報(使いまわしはいいのか?)を皆さんにお届けできたらいいなと思いますし、また、いろいろ教えていただきたく思いますので、お気軽に絡んでいただければと思います!

IoT 芸人として "Still Day One" をいつも心に、 Max 松下でしたー。

バックアップのくだりは


さすが。あざます!

EoT


  1. "IoT センサーやアプリケーションで発生したイベントを容易に検出し対応する" 🤔🤔🤔 

  2. 前はもっとアレでした "変更についてデバイスフリートをモニタリングし、アラートをトリガーして応答します" 

  3. 情報処理技術者試験とかでお世話になりましたね。