この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
いままで手動ポチポチでIoT Eventsを作っていました。 動作を試す実験だったので十分でしたが、案件で採用する可能性が高くなったため、IoT EventsをCloudFormationで作ってみました。
おすすめの方
- AWS IoT EventsをCloudFormationで作成したい方
仕様を決める
デバイス
- 水位情報をクラウドに送信する
- デバイスが送信する水位情報は下記とする
- 水位(メートル): waterLevel
- 時刻(ミリ秒): timestamp
{
"waterLevel": 10,
"timestamp": 1601258079088
}
トピック
- デバイスは下記トピックにデータを送信する
sample/<デバイスID>/waterLevel
クラウド(IoT Events)
- しきい値は30とする
- しきい値以上になった場合、SNSトピックを発行してメール送信する(水位が異常です)
- しきい値を下回った場合、SNSトピックを発行してメール送信する(復旧しました)
IoT EventsをCloudFormationで作成する
CloudFormationテンプレート
下記を定義しています。
- メール通知用のSNSトピック
- IoTルール
- IoTルール用のIAMロール
- IoT Eventsの入力情報
- IoT Eventsの探知器モデル
- IoT Eventsの探知器モデル用のIAMロール
iot_events.yml
AWSTemplateFormatVersion: 2010-09-09
Description: IoT Events Sample
Resources:
WaterLevelNotifyTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: sample@example.com
Protocol: email
waterLevelTopicRule:
Type: AWS::IoT::TopicRule
Properties:
RuleName: water_level_topic_rule
TopicRulePayload:
AwsIotSqlVersion: "2016-03-23"
RuleDisabled: false
Sql: >-
SELECT
topic(2) as deviceId, * as payload
FROM
'sample/+/waterLevel'
Actions:
- IotEvents:
InputName: !Ref WaterLevelEventsInput
RoleArn: !GetAtt WaterLevelTopicRuleRole.Arn
WaterLevelTopicRuleRole:
Type: AWS::IAM::Role
Properties:
RoleName: water-level-topic-rule-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: iot.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSIoTEventsFullAccess
WaterLevelEventsInput:
Type: AWS::IoTEvents::Input
Properties:
InputName: WaterLevelInputData
InputDefinition:
Attributes:
- JsonPath: deviceId
- JsonPath: payload.waterLevel
- JsonPath: payload.timestamp
WaterLevelDetectorModel:
Type: AWS::IoTEvents::DetectorModel
Properties:
DetectorModelName: water-level-model
Key: deviceId
EvaluationMethod: BATCH
RoleArn: !GetAtt WaterLevelEventsDetectorModelRole.Arn
DetectorModelDefinition:
InitialStateName: Normal
States:
- StateName: Normal
OnInput:
TransitionEvents:
- EventName: to_warning
NextState: Warning
Condition: $input.WaterLevelInputData.payload.waterLevel >= 30
- StateName: Warning
OnEnter:
Events:
- EventName: send-mail-to-warning
Actions:
- Sns:
TargetArn: !Ref WaterLevelNotifyTopic
Payload:
Type: STRING
ContentExpression: "'水位の上昇を検知しました。対象デバイスID: ${$input.WaterLevelInputData.deviceId}, 水位: ${$input.WaterLevelInputData.payload.waterLevel}'"
OnInput:
TransitionEvents:
- EventName: to_normal
NextState: Normal
Condition: $input.WaterLevelInputData.payload.waterLevel < 30
OnExit:
Events:
- EventName: send-mail-to-normal
Actions:
- Sns:
TargetArn: !Ref WaterLevelNotifyTopic
Payload:
Type: STRING
ContentExpression: "'水位が復旧しました。対象デバイスID: ${$input.WaterLevelInputData.deviceId}, 水位: ${$input.WaterLevelInputData.payload.waterLevel}'"
WaterLevelEventsDetectorModelRole:
Type: AWS::IAM::Role
Properties:
RoleName: water-level-detector-model-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: iotevents.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSIoTEventsFullAccess
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
デプロイ
aws cloudformation deploy \
--template-file iot_events.yml \
--stack-name IoT-Events-Sample-Stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
デプロイされた探知器モデルを確認する
予定通りにできました。
動作確認
waterLevel=10を送信すると、Normal状態になる
- トピック: sample/d0001/waterLevel
{
"waterLevel": 10,
"timestamp": 1601258079088
}
Normal状態になりました。
waterLevel=30を送信すると、Warning状態になってメールが来る
- トピック: sample/d0001/waterLevel
{
"waterLevel": 30,
"timestamp": 1601258079088
}
Warning状態になりました。
水位の上昇を知らせるメールも来ています。
waterLevel=29を送信すると、Normal状態になって復旧メールが来る
- トピック: sample/d0001/waterLevel
{
"waterLevel": 29,
"timestamp": 1601258079088
}
Normal状態になりました。
復旧メールも来ています。
さいごに
いろんなところでハマりました。最初からCloudFormationで作るのは大変なので、手動で作成してからエクスポートを行い、その内容を参考にすると便利でした。どなたかの参考になれば幸いです。