Zenn
🍅

AWS IoT EventsでGreengrassを監視する

に公開

はじめに

AWSを使ってIoTのシステムを作るときに、エッジPCにGreengrassをインストールすることはよくあると思います。実際に運用をはじめてみるとエッジPCというものは大抵手元を離れるので、何かあったときに「そもそも起動しているのこいつ?」というのが判断できない事が多いです。

AWSのGreengrassのコンソール上だと以下の画面キャプチャのようにGreengrassデバイスが報告するステータスとその時間が表示されます。しかし、この情報は基本的にデバイスが起動したときの情報が表示されるので、正常起動後にデバイスが終了した場合は状況の判断ができません。

エッジPCを監視する機能を実装するが一番なのは確かなのですが、開発する為のコストやモチベーションが無いときに一旦コンソールからポチポチするだけである程度の見れるものを作ろうというのが今回の趣旨です。

AWS IoT Events とは

AWS IoT Eventsは、AWS上でステートマシンを実現するサービスです。


AWSのドキュメントからパクってきたキャプチャ

AWSでステートマシンというと、もしかしたらStep Functionsを思い浮かべる人もいるかも知れません。しかし、Step Functionsがステートレスであるのに対して、IoT Eventsはステートフルという大きな違いがあります。つまりIoT Eventsであれば状態を保持することができます。つまりStep Functionsより有能です(?)
ということでAWS IoT Eventsを利用することで、各エッジPCに対してGreengrassが起動した際のイベントを検知して「起動中」に、Greengrassが終了した際のイベントを検知したら「停止中」に、ステートを変更することで、全てのエッジPCの起動状態を一覧化出来るということになります。

Greengrassが自動で通知する起動時と終了時のイベントについて

では、どうやってエッジPCの起動と終了を検知するかですが、これはGreengrassがAWS IoTにMQTTで通知するライフサイクルイベントを検知することで実現可能です。

https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/life-cycle-events.html

上記のドキュメントにあるように

  • 接続時(=起動時) : $aws/events/presence/connected/clientId
  • 切断時(=終了時) : $aws/events/presence/disconnected/clientId

に通知が飛びますので、まずは確認のためにAWSコンソールからMQTTテストクライアントで、$aws/events/presence/disconnected/+$aws/events/presence/disconnected/+をサブスクライブします。
そして、エッジPCの電源を入れてGreengrassが起動されると、、、

connectedの通知を受け取れました。

その後エッジPCの電源を落としてGreengrassを終了させると、、、

disconnectedの通知を受け取れました。

ということで、これらの通知によってステートが変化するステートマシンをAWS IoT Eventsで作成します。

AWS IoT Eventで探知機モデルを作ろう

AWS IoT Eventのコンソールから探知モデルのページを開き、「探知モデルの作成」->「新しく作成する」を押下します。すると以下のような画面になります。

初期値だとステートを2つに増やして、ステート名をそれぞれdisconnectedconnectedにします。

ステートを変化させる為のイベントを作りたいのですが、その前にインプットを定義する必要があります。右上の「アクション」から「入力を追加」します。

先ほどMQTTテストクライアントで受け取ったjsonデータをファイルに保存してJSONファイルをアップロードすることで、connectedの入力を作成できます。なぜ一度ファイルを経由しないといけないのか理解し難いですがそういう仕様です。
JSONファイルは構造しか見ていないので、以下の内容をコピペしてもOKです。

connected.json
{
    "clientId": "186b5",
    "thingName": "exampleThing",
    "timestamp": 1573002230757,
    "eventType": "connected",
    "sessionIdentifier": "00000000-0000-0000-0000-000000000000",
    "principalIdentifier": "12345678901234567890123456789012",
    "ipAddress": "192.0.2.0",
    "versionNumber": 0
}

同様に以下のjsonからdisconnectedの入力を作ります。

disconnected.json
{
    "clientId": "186b5",
    "thingName": "exampleThing",
    "timestamp": 1573002340451,
    "eventType": "disconnected",
    "sessionIdentifier": "00000000-0000-0000-0000-000000000000",
    "principalIdentifier": "12345678901234567890123456789012",
    "clientInitiatedDisconnect": true,
    "disconnectReason": "CLIENT_INITIATED_DISCONNECT",
    "versionNumber": 0
}

そしたら、ステートマシンに戻ってdisconnectedからconnectedを線でつなぎます。移行イベントが作られますので、適当に名前をつけた後にイベントトリガーロジックに以下のように入力します。

currentInput("connected")

これでconnectedの入力があれば、ステートがdisconnectedからconnectedに変化します。

同様に、connectedからdisconnectedへの移行イベントも作ります。トリガーロジックは以下です。

currentInput("disconnected")

以上でステートマシンができたので、右上の「発行」ボタンを押下します。

以下のように探知モデルの設定を入力して、「保存して発行」を押下します。

  • ディテクターモデル名
    • 好きな名前を入れてください。
  • ロール
    • 新規のロール名を入力すると自動で作られます。または既存のロールを選択します。
  • 探知機生成メソッド
    • 「一意のキー値ごとに探知器を作成する」
  • 探知器作成キー
    • clientId
  • ディテクターの評価方法
    • シリアル評価

以上でIoT Eventsが作成できました。

ライフサイクルイベントをIoT Eventsに連携

次に、作成したIoT Eventsに対して、AWS IoTが受け取ったGreengrassのライフサイクルイベントが連携されるようにします。

まずは、connectedのイベントが通知されるようにルールを作成します。

  1. ブラウザでAWS IoTのコンソールを開きます。(IoT EventsでなくAWS IoTの方です!)
  2. 左のメニューからメッセージのルーティング->ルールを選び、ルールの作成ボタンを押下します。
  3. ステップ1は、適当なルール名(例えばgreengrass_connect)を決めて次へ
  4. ステップ2で、SQLステートメントに以下のように入れます。
SELECT * FROM '$aws/events/presence/connected/+' WHERE startswith(clientId, "<モノの名前のプレフィックス>") 

ここで、<モノの名前のプレフィックス> 部分は検知したいエッジPCのモノの名前のプレフィックスに変更してください。いい感じのプレフィックスをつけていない場合は、検知したいエッジPCを特定出来るような条件を記載しましょう。

ここでいくつか注意点があります。

1つ目は、WHERE文を入れないで全てのモノを検知する設定にした場合は、コンソールからモノの一覧を開いたときにコンソールが何かのモノと判断されてAWS IoT Eventに検知されてしまいます。邪魔です。それらの邪魔なモノを排除するために検知したいモノを絞り込む為のWHEREが必要です。

2つ目は、SQLと言いながらLIKE句が使えません。他にも色々使えません。細かい条件を指定をしたい時はドキュメントをよく確認しましょう。
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-reference.html

  1. ステップ3では、ルールアクションとしてIoT Eventsを選択して、その後先ほど作った入力名を選択します。また、IAMロールの項目で「新しいロールを作成」ボタンを押下して好きなロール名を入力します。


  1. 内容を確認して、作成します。

以上でconnectedのイベントをIoT Eventsに通知するルールが作成されました。同様の手順でdisconnectedのルールも作成してください。ステップ2で入力するSQLステートメントは以下です。

SELECT * FROM '$aws/events/presence/disconnected/+' WHERE startswith(clientId, "<モノの名前のプレフィックス>")

ステップ3のIAMロールは、新規に追加してもよいですが前回作成したものを流用してもよいです。

以上で全ての構築が完了です。

実際に動かす

では、GeengrassをインストールしたエッジPCに電源を入れてみます。

IoT Eventのコンソールを確認すると、無事にエッジPCを認識して状態がconnectedになりました!

エッジPCの電源を落としてみます。

状態がdisconnectedになりました!

ということで、無事にエッジPCの稼働状態を監視できるようになりました。

最後に

無事にAWSコンソールをポチポチするだけでエッジPCを監視する機能を構築できました。

さて、ここまで読んでいただいた稀有な人の大半は気づいていると思いますが、このAWS IoT Eventsというサービスかなりマイナーです。最近リリースされた機能でもないのにZennで検索しても全然記事が見つかりません。サ終しないか不安なレベルです。
ですが、最初に書いたようにこのステートフルなステートマシンを扱える貴重なサービスでもあります。うまく使えばいろいろと有用なんじゃないかなと思うので、もっとみんな使わないかなぁと思っています。
最後まで読んでしまった貴方、せっかくなので試しに一度AWS IoT Eventsを使ってみましょう。

NCDCエンジニアブログ

Discussion

ログインするとコメントできます