AWS IoTルールでMQTTメッセージ受信時にLambda関数を実行する
この記事では、AWS IoTルールを使用して、MQTTメッセージ受信時にLambda関数を実行する方法を確認します。
Lambda (lambda) AWS Lambda アクションは関数を呼び出し、MQTT メッセージを渡します。 AWS IoT Lambda 関数を非同期的に呼び出します。
Lambda
この記事では、AWS IoTルールとLambda関数、SNSを組み合わせて、特定の条件下でSMS通知を行うシステムを構築します。これにより、MQTTメッセージの内容に応じて動的に処理を行い、結果をリアルタイムに通知できます。
構成
- AWS IoTルールを作成し、特定のトピックに発行されたメッセージをLambda関数に渡します。
- AWS IoTルール用のIAMロールを作成します。
- Lambda関数はSNSトピックにメッセージを送信するパブリッシャーとして動作します。
- 関数のランタイム環境はPython 3.12です。
- SNSの通知先にSMSを指定し、携帯電話の電話番号を設定します。
リソース
AWS IoTリソース
AWS IoTルールの基本的な事項については、以下のページをご確認ください。
SQL
SQLで具体的なルールを定義します。4つのデータで構成されるメッセージを作成します。
- device_id:castおよびtopic関数を使用して、トピック名をスラッシュで分割した際の2番目の文字列を数値に変換します。
- reported_temperature:元のメッセージのtemperatureという名前のデータをリネームして使用します。
- max_temperature:値は固定で「30」を設定します。
- notify_topic_arn:SNSトピックのARNを指定します。
FROM句では、トピック名device/+/dataを対象とします。WHERE句を用いて、temperatureの値が30より大きい場合のみSNSに通知します。
Action
アクションとしてLambda関数を指定します。
Lambda
関数
SNSトピックにメッセージを発行するLambda関数です。関数に渡された引数を使用して、メッセージの本文を作成します。特に、メッセージの通知先のSNSトピックも引数で渡されます。
関数で実行するコードは、以下のページのものを参考にしました。
IAMロール
メッセージを発行するための必要な権限を付与します。通知先のSNSトピックが引数として渡されるため、ワイルドカード(*)を使用して不特定のSNSトピックへのメッセージ発行を許可します。
SNS
SNSトピックの通知先に携帯電話の電話番号を指定し、通知プロトコルにSMSを設定します。
詳細につきましては、以下のページをご確認ください。
CloudFormationテンプレート
AWS IoTルール
Resources:
TopicRule:
Type: AWS::IoT::TopicRule
Properties:
RuleName: wx_friendly_text
TopicRulePayload:
Actions:
- Lambda:
FunctionArn: !Ref FunctionArn
AwsIotSqlVersion: 2016-03-23
RuleDisabled: false
Sql: !Sub |
SELECT
cast(topic(2) AS DECIMAL) as device_id,
temperature as reported_temperature,
30 as max_temperature,
'${SnsTopicArn}' as notify_topic_arn
FROM '${TopicName}' WHERE temperature > 30
Code language: YAML (yaml)
Lambdaパーミッション
Resources:
Permission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref FunctionArn
Principal: iot.amazonaws.com
SourceAccount: !Ref AWS::AccountId
SourceArn: !GetAtt TopicRule.Arn
Code language: YAML (yaml)
Lambda 関数を呼び出すには、lambda:InvokeFunctionにアクセス権限を付与するポリシーを設定する必要があります。 AWS IoT AWS IoT Lambda AWS リージョン ポリシーが存在するのと同じ場所で定義された Lambda 関数のみを呼び出すことができます。Lambda 関数はリソースベースのポリシーを使用するため、ポリシーを Lambda 関数自体にアタッチする必要があります。
Lambda
Lambda
関数
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Code:
ZipFile: |
import boto3
def lambda_handler(event, context):
sns = boto3.client('sns')
message_text = "Device {0} reports a temperature of {1}, which exceeds the limit of {2}.".format(
str(event['device_id']),
str(event['reported_temperature']),
str(event['max_temperature'])
)
response = sns.publish(
TopicArn = event['notify_topic_arn'],
Message = message_text
)
return response
FunctionName: !Sub "${Prefix}-function"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)
IAMロール
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: SNSPublishPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sns:Publish
Resource:
- !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:*"
Code language: YAML (yaml)
SNS
Resources:
Topic:
Type: AWS::SNS::Topic
Properties:
FifoTopic: false
Subscription:
- Endpoint: !Ref PhoneNumber
Protocol: sms
TopicName: !Sub "${Prefix}-sns-topic"
Code language: YAML (yaml)
テンプレート全体
動作確認
MQTT test clientページにアクセスして、動作を確認します。
トピックdevice/+/dataをサブスクライブします。
トピックdevice/32/dataにメッセージを発行します。
device/+/dataでメッセージを受信できます。temperatureの値が38であり、30より大きいです。AWS IoTルールの条件を満たしているため、SNSトピックにメッセージが送信されます。
携帯電話のSMSアプリを確認すると、メッセージが届いています。
メッセージ内容は、Lambda関数でフォーマットされたものです。
次に、トピックdevice/33/dataにtemperatureの値を28としてメッセージを発行します。
メッセージの発行は成功しますが、SMSは届きません。temperatureの値が30以下のため、AWS IoTルールの条件を満たしていません。
まとめ
AWS IoTルールを使用して、MQTTメッセージ受信時にLambda関数を実行し、条件に応じてSNSでSMS通知を行う方法を確認しました。これにより、デバイスからのデータをリアルタイムで監視し、異常値が検出された際に即時通知する仕組みを構築できます。