AWS IoT Eventsの特定状態のデバイス一覧について、Lambdaでメール通知してみた
以前にAWS IoT Eventsで作成したハートビート監視は、次のタイミングでデバイス毎にメール送信していました。
- オフライン状態(デバイス切断)になったとき
- オンライン状態(デバイス復帰)になったとき
しかし、ハートビート監視をしていると「1時間毎に現在オフライン状態のデバイス一覧がメールで欲しい」ことがあります。
というわけで、AWS IoT Eventsを使っている場合にどうするのかを試してみました。
おすすめの方
- AWS IoT Eventsでディテクターの一覧を取得したい方
- SNSトピック経由でメール送信したい方
サーバーレスアプリの作成
作成する全体像は下記です。1時間毎に動くLambdaを作成し、AWS IoT Eventsからデバイス(ディテクター)の一覧を取得し、SNSトピック経由でメール送信しています。
AWS SAMの初期化
sam init \ --runtime python3.7 \ --name iot-events-get-sample \ --app-template hello-world
template.yamlの作成
template.yaml
は下記です。Lambdaを定義しています。なお、以前に手動作成したSNSトピックを流用しています。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: iot-events-get-sample Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.7 Timeout: 10 Policies: - arn:aws:iam::aws:policy/AWSIoTEventsReadOnlyAccess - arn:aws:iam::aws:policy/AmazonSNSFullAccess Environment: Variables: # 以前、手動作成しちゃったSNSトピックを使う SNS_TOPIC_ARN: arn:aws:sns:ap-northeast-1:1234567890:heartbeat-send-mail-topic Events: CheckHeartbeat: Type: Schedule Properties: Schedule: cron(0 0/1 * * ? *) # 日本時間で毎日0時から1時間毎 HelloWorldFunctionLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
Lambdaコードの作成
Lambdaコードは下記です。IoT Eventsのディテクターについて、offline状態の一覧を取得し、メッセージを作成してSNSトピックにPublishしています。
import boto3 import json import os iot_events_client = boto3.client('iotevents-data') sns_client = boto3.client('sns') def lambda_handler(event, context): detectors = get_detectors_offline('SampleHeartbeatModel') if len(detectors) != 0: message = create_message(detectors) send_email(message) def get_detectors_offline(model_name, token=None): options ={ 'detectorModelName': model_name, 'stateName': 'offline' } if token is not None: options['nextToken'] = token res = iot_events_client.list_detectors(**options) detectors = res.get('detectorSummaries', []) if 'nextToken' in res: detectors += get_detectors_offline(model_name, res['nextToken']) return detectors def create_message(detectors): devices = [] for item in detectors: device_id = item['keyValue'] devices.append(device_id) return '\n'.join(devices) def send_email(message): sns_client.publish( TopicArn=os.environ['SNS_TOPIC_ARN'], Subject='お知らせ:切断中のデバイス一覧', Message=message )
デプロイ
sam build sam package \ --output-template-file packaged.yaml \ --s3-bucket cm-fujii.genki-deploy sam deploy \ --template-file packaged.yaml \ --stack-name IoT-Events-Get-Sample-Stack \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
動作確認
オフライン状態のデバイスが2個のとき
ディテクターは2つ存在しており、すべてoffline状態です。
この状態でLmabdaを動かすと、メールが来ました!
オフライン状態のデバイスが1個のとき
1つのデバイスをonline状態に変更しました。
この状態でLambdaを動かすと、メールが来ました!
内容もoffline状態のデバイスだけです。
オフライン状態のデバイスが0個のとき
2つのデバイスをonline状態に変更しました。
この状態でLambdaを動かすと、メールが来ませんでした。期待通りです。
さいごに
AWS IoT EventsとLambdaを組み合わせることで、特定状態のデバイス一覧を取得してメール送信することができました。 発想次第でもっとたくさんのことができそうですね。