AWS IoT rules to execute Lambda functions when receiving MQTT messages
In this page, we will verify how to use AWS IoT Rules to execute a Lambda function when an MQTT message is received.
A Lambda (lambda) action invokes an AWS Lambda function, passing in an MQTT message. AWS IoT invokes Lambda functions asynchronously.
Lambda
In this article, we will build a system that combines AWS IoT Rules, Lambda functions, and SNS to perform SMS notifications under specific conditions. This allows for dynamic processing based on the content of MQTT messages and real-time notification of results.
Configuration
- Create an AWS IoT Rule that passes messages published to a specific topic to a Lambda function.
- Create an IAM role for the AWS IoT Rule.
- The Lambda function acts as a publisher that sends messages to an SNS topic.
- The function’s runtime environment is Python 3.12.
- Set SMS as the notification destination for SNS, and configure it with a mobile phone number.
Resources
AWS IoT Rule
For basic information on AWS IoT rules, please refer to the following pages.
SQL
Define the specific rule using SQL. We create a message composed of four data elements.
- device_id: Use the cast and topic functions to convert the second string obtained by splitting the topic name by slashes into a numeric value.
- reported_temperature: Rename and use the data named temperature from the original message.
- max_temperature: Set a fixed value of “30”.
- notify_topic_arn: Specify the ARN of the SNS topic. Embed this value using CloudFormation’s intrinsic function Sub.
In the FROM clause, target the topic name device/+/data. Use the WHERE clause to process data under certain conditions. Specifically, we only notify SNS when the temperature value is greater than 30.
Action
Specify the Lambda function as the action target.
Lambda
Function
A Lambda function that publishes messages to an SNS topic. The function uses the arguments passed to it to create the message body. Notably, the SNS topic that is the message destination is also passed as an argument. This is specified on the AWS IoT Rule side.
IAM Role
Grant the necessary permissions to publish messages. Pay attention to how the Resource property is described. In this configuration, the SNS topic that is the notification destination is passed as an argument. Therefore, to enable message publication to unspecified SNS topics that are passed, use a wildcard (*) in the topic name.
SNS
Specify a mobile phone number as the notification destination for this SNS topic, and set SMS as the notification protocol.
CloudFormation Template
AWS IoT Rule
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 Permission
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)
For AWS IoT to invoke a Lambda function, you must configure a policy that grants the lambda:InvokeFunction permission to AWS IoT. You can only invoke a Lambda function defined in the same AWS Region where your Lambda policy exists. Lambda functions use resource-based policies, so you must attach the policy to the Lambda function itself.
Lambda
Lambda
Function
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 Role
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)
Full Template
Verification
Access the MQTT test client page to verify the operation.
Subscribe to the topic device/+/data.
Publish a message to the topic device/32/data.
The message can be received via the topic device/+/data. This topic uses wildcard notation to receive messages. Looking at the temperature value, it is 38, which is greater than 30. Therefore, this message meets the condition of the AWS IoT Rule, and a message is sent to the SNS topic.
Check the SMS app on your mobile phone. A message has been received.
The content of the message is a string with three data elements embedded. These values were specified in the SQL expression and formatted by the Lambda function. In other words, the Lambda function was invoked by the IoT Rule, and a message was sent via the SNS topic to SMS.
Send another message. Publish a message to the topic device/33/data. Set the temperature value to 28.
The message was successfully published. However, no SMS was received on the mobile phone. This is because the temperature value of the published message was 28, which is less than 30. Therefore, this message did not meet the condition of the AWS IoT Rule, and no message was sent to the SNS topic.
Conclusion
We have confirmed how to execute a Lambda function when an MQTT message is received using AWS IoT Rules, and perform SMS notifications via SNS under certain conditions. This allows you to monitor data from devices in real-time and build a system that immediately notifies you when abnormal values are detected.