IoT Eventsでデバイス毎に異なるしきい値を超えたらSNSトピックを発行する
デバイスから来たデータについて、とあるしきい値を超えた際にメール送信したい要件があるとします。 すべてのデバイスでしきい値が同じであれば簡単ですが、デバイス毎にしきい値が異なる場合は、一工夫する必要があります。
というわけで、デバイス毎に異なるしきい値の通知をIoT Evnetsを使って実現してみました。 仕組みとしては、デバイス毎のしきい値をディテクター内に変数として保持して参照しています。
おすすめの方
- IoT Eventsの雰囲気を知りたい方
- デバイス毎に異なるしきい値でイベント発行したい方
IoT Eventsとは
下記をご覧ください。
仕様を簡単に決める
デバイス
- 水位情報をクラウドに送信する
- デバイスが送信する水位情報は下記とする
- 水位(メートル):waterLevel
- 時刻(ミリ秒):timestamp
{ "waterLevel": 10, "timestamp": 1601258079088 }
トピック
- デバイスは下記トピックにデータを送信する
sample/<デバイスID>/waterLevel
クラウド
- しきい値を超えた場合、SNSトピックを発行してメール送信する
- しきい値を下回った場合、SNSトピックを発行してメール送信する
- しきい値はデバイス毎に設定可能とする
- しきい値のデフォルト値は「30」とする
- しきい値の更新は、Low状態(しきい値を下回っている状態)のみ可能とする
しきい値の設定方法
MQTTで下記のJSONを送信するだけです。
{ "threshold": 55 }
デバイス側からしきい値を設定する場合は、そのまま送信すればOKです。 もしユーザがWebブラウザ等で設定する場合は、API GatewayのバックにいるLambdaを使って、MQTTトピックにPublishするなどができます。
通知先のSNSトピックを作成する
しきい値を超えた際と下回った際にIoT Eventsが発行するSNSトピックを作成します。
- トピック名: notify-water-level-sensor
続いてEメールのサブスクリプション設定を行います。
IoT Eventsで探知機モデルを作成する
完成図は下記です。
探知機モデルの作成
新しい探知機モデルを作成します。
初期状態の探知機モデルができたので、これを作り込んでいきます。
入力の設定
右上の「入力の作成」を選択して設定します。
- 入力名: TestWaterLevelInputData
{ "deviceId": "d1234", "payload": { "waterLevel": 10, "timestamp": 1595817156346, "threshold": 30 } }
入力属性はすべて選択しておきます(すべて使います)。
Low状態の作成
既存のState_1
を選択し、状態名をLow
に変更します。
OnEnterイベントの設定(しきい値の初期値設定)
OnEnter
のイベント追加を選択し、しきい値の初期値を設定します。
項目 | 値 |
---|---|
イベント名 | InitThreshold |
条件 | isUndefined($variable.threshold) |
アクション | 変数の設定 |
変数オペレーション | 値の割り当て |
変数名 | threshold |
値の割り当て | 30 |
OnInputイベントの設定(しきい値の更新)
OnInput
のイベント追加を選択し、しきい値の更新を設定します。
項目 | 値 |
---|---|
イベント名 | UpdateThreshold |
条件 | $input.TestWaterLevelInputData.payload.threshold > 0 |
アクション | 変数の設定 |
変数オペレーション | 値の割り当て |
変数名 | threshold |
値の割り当て | $input.TestWaterLevelInputData.payload.threshold |
High状態の作成
状態をドラッグして新しい状態を追加し、状態名をHigh
に変更します。
OnEnterイベントの設定
OnEnter
のイベント追加を選択し、SNSトピックを発行してメール送信する設定を追加します。
項目 | 値 |
---|---|
イベント名 | SendMailToHigh |
条件 | true |
アクション | SNSメッセージの送信 |
SNSトピック | 値の割り当て |
ペイロード | カスタムペイロード |
種類 | 文字列 |
カスタムペイロード | '水位の上昇を検知しました。対象デバイスID: ${$input.TestWaterLevelInputData.deviceId}, 水位: ${$input.TestWaterLevelInputData.payload.waterLevel}' |
OnExitイベントの設定
OnExit
のイベント追加を選択し、SNSトピックを発行してメール送信する設定を追加します。
項目 | 値 |
---|---|
イベント名 | SendMailToLow |
条件 | true |
アクション | SNSメッセージの送信 |
SNSトピック | 値の割り当て |
ペイロード | カスタムペイロード |
種類 | 文字列 |
カスタムペイロード | '水位が低下しました。対象デバイスID: ${$input.TestWaterLevelInputData.deviceId}, 水位: ${$input.TestWaterLevelInputData.payload.waterLevel}' |
状態遷移を定義する
LowからHighの繊維
項目 | 値 |
---|---|
イベント名 | over_threshold |
トリガーロジック | $input.TestWaterLevelInputData.payload.waterLevel >= $variable.threshold |
HighからLowの繊維
項目 | 値 |
---|---|
イベント名 | under_threshold |
トリガーロジック | $input.TestWaterLevelInputData.payload.waterLevel < $variable.threshold |
探知機モデルを発行する
右上の「発行」ボタンを選択し、モデル名とIAMロール名を入力します。IAMロールはここで同時に新規作成してもらいます。
項目 | 値 |
---|---|
モデル名 | SampleWaterLevelModel |
IAMロール名 | iot-events-sample-water-level-role |
探知機生成メソッド | 一意のキー値ごとに探知器を作成する |
探知機作成キー | deviceId |
ディテクターの評価方法 | バッチ評価 |
最後に「保存して発行する」ボタンを押せば完了です!
ログの有効化
IoT Eventsのログを有効化して、CloudWatch Logsで見れるようにしておきます。
IoTルールアクションの作成
IoT Coreでルールを作成します。
項目 | 値 |
---|---|
ルールの名前 | sample_iot_events_water_level_rule |
SQLルール | 下記 |
アクション | IoT Events入力にメッセージを送信する |
入力名 | TestWaterLevelInputData |
ロール | sample-iot-events-water-level-rule-role (※新規作成) |
SELECT topic(2) as deviceId * as payload FROM 'sample/+/waterLevel'
動作確認してみる
水位情報を送信する(水位:10)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 10, "timestamp": 1602661307957 }
探知機モデルの様子
ディテクターにデバイス(d0001)が追加されました。現在の状態はLow
です。
しきい値として、デフォルト値の30が設定されています。
水位情報を送信する(水位:40)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 40, "timestamp": 1602661307957 }
探知機モデルの様子
状態がHigh
になりました!
メールも届きました!
水位情報を送信する(水位:20)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 20, "timestamp": 1602661307957 }
探知機モデルの様子
状態がLow
になりました!
メールも届きました!
新しいしきい値を送信する(しきい値:50)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "threshold": 50 }
探知機モデルの様子
しきい値が50になりました。
水位情報を送信する(水位:40)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 40, "timestamp": 1602661307957 }
探知機モデルの様子
期待通り、特に変わりはありません。
水位情報を送信する(水位:60)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 60, "timestamp": 1602661307957 }
探知機モデルの様子
状態がHigh
になりました!
メールも届きました!
新しいしきい値を送信する(しきい値:55)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "threshold": 55 }
探知機モデルの様子
しきい値は50のまま変化ありません。期待通りですね。
水位情報を送信する(水位:40)
- トピック:
sample/d0001/waterLevel
- データ: 下記
{ "waterLevel": 40, "timestamp": 1602661307957 }
探知機モデルの様子
状態がLow
になりました!
メールも届きました!
さいごに
AWS IoT Eventsの各ディテクターの変数内にしきい値を設けることで、デバイス毎に異なるしきい値を設定してみました。 変数を使いこなすことで、もっと様々なモデル定義ができそうですね。