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 Lambda (Python なら
update_thing_shadow(**kwargs)
です)
- AWS Lambda (Python なら
- デバイス上から
- 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-model
で model.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
-
情報処理技術者試験とかでお世話になりましたね。 ↩