AWS IoTルールでMQTTメッセージ受信時にLambda関数を実行する

目次

AWS IoTルールでMQTTメッセージ受信時にLambda関数を実行する

この記事では、AWS IoTルールを使用して、MQTTメッセージ受信時にLambda関数を実行する方法を確認します。

Lambda (lambda) AWS Lambda アクションは関数を呼び出し、MQTT メッセージを渡します。 AWS IoT Lambda 関数を非同期的に呼び出します。

Lambda

この記事では、AWS IoTルールとLambda関数、SNSを組み合わせて、特定の条件下でSMS通知を行うシステムを構築します。これにより、MQTTメッセージの内容に応じて動的に処理を行い、結果をリアルタイムに通知できます。

構成

Diagram of AWS IoT rules to execute Lambda functions when receiving MQTT messages.
  • AWS IoTルールを作成し、特定のトピックに発行されたメッセージをLambda関数に渡します。
  • AWS IoTルール用のIAMロールを作成します。
  • Lambda関数はSNSトピックにメッセージを送信するパブリッシャーとして動作します。
  • 関数のランタイム環境はPython 3.12です。
  • SNSの通知先にSMSを指定し、携帯電話の電話番号を設定します。

リソース

AWS IoTリソース

Detail of AWS IoT 01.

AWS IoTルールの基本的な事項については、以下のページをご確認ください。

あわせて読みたい
AWS IoTルールでMQTTメッセージを再発行する 【AWS IoTルールでMQTTメッセージを再発行する】 AWS IoTには、AWS IoTルールという機能があります。 AWS IoT ルールは、デバイスから他の AWS のサービスにデータを送...

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

Detail of AWS IoT 02.

アクションとしてLambda関数を指定します。

Lambda

関数

Detail of Lambda 01.

SNSトピックにメッセージを発行するLambda関数です。関数に渡された引数を使用して、メッセージの本文を作成します。特に、メッセージの通知先のSNSトピックも引数で渡されます。

関数で実行するコードは、以下のページのものを参考にしました。

あわせて読みたい
チュートリアル: AWS Lambda 関数を使用して通知をフォーマットする - AWS IoT Core このチュートリアルでは、MQTTメッセージデータを AWS Lambda アクションに送信してフォーマットし、別の AWS サービスに送信する方法を示します。このチュートリアルでは...

IAMロール

Detail of Lambda 02.

メッセージを発行するための必要な権限を付与します。通知先のSNSトピックが引数として渡されるため、ワイルドカード(*)を使用して不特定のSNSトピックへのメッセージ発行を許可します。

SNS

SNSトピックの通知先に携帯電話の電話番号を指定し、通知プロトコルにSMSを設定します。

詳細につきましては、以下のページをご確認ください。

あわせて読みたい
AWS SNSでSMS(ショートメッセージ)に通知する 【AWS SNSでSMS(ショートメッセージ)に通知する】 AWS SNS(Simple Notification Service)では、多彩な通知先を選択できます。公式ドキュメントによると、SNSイベント...

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)

テンプレート全体

GitHub
awstut-fa/162 at main · awstut-an-r/awstut-fa Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

動作確認

MQTT test clientページにアクセスして、動作を確認します。

トピックdevice/+/dataをサブスクライブします。

Detail of AWS IoT 03.

トピックdevice/32/dataにメッセージを発行します。

Detail of AWS IoT 04.

device/+/dataでメッセージを受信できます。temperatureの値が38であり、30より大きいです。AWS IoTルールの条件を満たしているため、SNSトピックにメッセージが送信されます。

携帯電話のSMSアプリを確認すると、メッセージが届いています。

Detail of SNS 02.

メッセージ内容は、Lambda関数でフォーマットされたものです。

次に、トピックdevice/33/dataにtemperatureの値を28としてメッセージを発行します。

Detail of AWS IoT 05.

メッセージの発行は成功しますが、SMSは届きません。temperatureの値が30以下のため、AWS IoTルールの条件を満たしていません。

まとめ

AWS IoTルールを使用して、MQTTメッセージ受信時にLambda関数を実行し、条件に応じてSNSでSMS通知を行う方法を確認しました。これにより、デバイスからのデータをリアルタイムで監視し、異常値が検出された際に即時通知する仕組みを構築できます。

目次