

# Creating AWS IoT rules to route device data to other services
<a name="iot-rules-tutorial"></a>

These tutorials show you how to create and test AWS IoT rules using some of the more common rule actions.

AWS IoT rules send data from your devices to other AWS services. They listen for specific MQTT messages, format the data in the message payloads, and send the result to other AWS services.

We recommend that you try these in the order they are shown here, even if your goal is to create a rule that uses a Lambda function or something more complex. The tutorials are presented in order from basic to complex. They present new concepts incrementally to help you learn the concepts you can use to create the rule actions that don't have a specific tutorial.

**Note**  
AWS IoT rules help you send the data from your IoT devices to other AWS services. To do that successfully, however, you need a working knowledge of the other services where you want to send data. While these tutorials provide the necessary information to complete the tasks, you might find it helpful to learn more about the services you want to send data to before you use them in your solution. A detailed explanation of the other AWS services is outside of the scope of these tutorials.

**Tutorial scenario overview**  
The scenario for these tutorials is that of a weather sensor device that periodically publishes its data. There are many such sensor devices in this imaginary system. The tutorials in this section, however, focus on a single device while showing how you might accommodate multiple sensors.

The tutorials in this section show you how to use AWS IoT rules to do the following tasks with this imaginary system of weather sensor devices.
+ 

**[Tutorial: Republishing an MQTT message](iot-repub-rule.md)**  
This tutorial shows how to republish an MQTT message received from the weather sensors as a message that contains only the sensor ID and the temperature value. It uses only AWS IoT Core services and demonstrates a simple SQL query and how to use the MQTT client to test your rule.
+ 

**[Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md)**  
This tutorial shows how to send an SNS message when a value from a weather sensor device exceeds a specific value. It builds on the concepts presented in the previous tutorial and adds how to work with another AWS service, the [Amazon Simple Notification Service](https://docs.aws.amazon.com//sns/latest/dg/welcome.html) (Amazon SNS).

  If you're new to Amazon SNS, review its [Getting started](https://docs.aws.amazon.com//sns/latest/dg/sns-getting-started.html) exercises before you start this tutorial. 
+ 

**[Tutorial: Storing device data in a DynamoDB table](iot-ddb-rule.md)**  
This tutorial shows how to store the data from the weather sensor devices in a database table. It uses the rule query statement and substitution templates to format the message data for the destination service, [Amazon DynamoDB](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Introduction.html).

  If you're new to DynamoDB, review its [Getting started](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html) exercises before you start this tutorial.
+ 

**[Tutorial: Formatting a notification by using an AWS Lambda function](iot-lambda-rule.md)**  
This tutorial shows how to call a Lambda function to reformat the device data and then send it as a text message. It adds a Python script and AWS SDK functions in an [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) function to format with the message payload data from the weather sensor devices and send a text message.

  If you're new to Lambda, review its [Getting started](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html) exercises before you start this tutorial.

**AWS IoT rule overview**  
All of these tutorials create AWS IoT rules. 

For an AWS IoT rule to send the data from a device to another AWS service, it uses: 


+ A rule query statement that consists of:
  + A SQL SELECT clause that selects and formats the data from the message payload
  + A topic filter (the FROM object in the rule query statement) that identifies the messages to use
  + An optional conditional statement (a SQL WHERE clause) that specifies specific conditions on which to act
+ At least one rule action

Devices publish messages to MQTT topics. The topic filter in the SQL SELECT statement identifies the MQTT topics to apply the rule to. The fields specified in the SQL SELECT statement format the data from the incoming MQTT message payload for use by the rule's actions. For a complete list of rule actions, see [AWS IoT Rule Actions](iot-rule-actions.md).

**Topics**
+ [Tutorial: Republishing an MQTT message](iot-repub-rule.md)
+ [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md)
+ [Tutorial: Storing device data in a DynamoDB table](iot-ddb-rule.md)
+ [Tutorial: Formatting a notification by using an AWS Lambda function](iot-lambda-rule.md)

# Tutorial: Republishing an MQTT message
<a name="iot-repub-rule"></a>

This tutorial demonstrates how to create an AWS IoT rule that publishes an MQTT message when a specified MQTT message is received. The incoming message payload can be modified by the rule before it's published. This makes it possible to create messages that are tailored to specific applications without the need to alter your device or its firmware. You can also use the filtering aspect of a rule to publish messages only when a specific condition is met.

The messages republished by a rule act like messages sent by any other AWS IoT device or client. Devices can subscribe to the republished messages the same way they can subscribe to any other MQTT message topic.

**What you'll learn in this tutorial:**
+ How to use simple SQL queries and functions in a rule query statement
+ How to use the MQTT client to test an AWS IoT rule

This tutorial takes about 30 minutes to complete.

**Topics**
+ [Review MQTT topics and AWS IoT rules](#iot-repub-rule-mqtt)
+ [Step 1: Create an AWS IoT rule to republish an MQTT message](#iot-repub-rule-define)
+ [Step 2: Test your new rule](#iot-repub-rule-test)
+ [Step 3: Review the results and next steps](#iot-repub-rule-review)

**Before you start this tutorial, make sure that you have:**
+ 

**[Set up AWS account](setting-up.md)**  
You'll need your AWS account and AWS IoT console to complete this tutorial.
+ 

**Reviewed [View MQTT messages with the AWS IoT MQTT client](view-mqtt-messages.md)**  
Be sure you can use the MQTT client to subscribe and publish to a topic. You'll use the MQTT client to test your new rule in this procedure.

## Review MQTT topics and AWS IoT rules
<a name="iot-repub-rule-mqtt"></a>

Before talking about AWS IoT rules, it helps to understand the MQTT protocol. In IoT solutions, the MQTT protocol offers some advantages over other network communication protocols, such as HTTP, which makes it a popular choice for use by IoT devices. This section reviews the key aspects of MQTT as they apply to this tutorial. For information about how MQTT compares to HTTP, see [Choosing an application protocol for your device communication](protocols.md#protocol-selection).

**MQTT protocol**  
The MQTT protocol uses a publish/subscribe communication model with its host. To send data, devices publish messages that are identified by topics to the AWS IoT message broker. To receive messages from the message broker, devices subscribe to the topics they will receive by sending topic filters in subscription requests to the message broker. The AWS IoT rules engine receives MQTT messages from the message broker.

**AWS IoT rules**  
AWS IoT rules consist of a rule query statement and one or more rule actions. When the AWS IoT rules engine receives an MQTT message, these elements act on the message as follows.
+ 

**Rule query statement**  
The rule's query statement describes the MQTT topics to use, interprets the data from the message payload, and formats the data as described by a SQL statement that is similar to statements used by popular SQL databases. The result of the query statement is the data that is sent to the rule's actions.
+ 

**Rule action**  
Each rule action in a rule acts on the data that results from the rule's query statement. AWS IoT supports [many rule actions](iot-rule-actions.md). In this tutorial, however, you'll concentrate on the [Republish](republish-rule-action.md) rule action, which publishes the result of the query statement as an MQTT message with a specific topic.

## Step 1: Create an AWS IoT rule to republish an MQTT message
<a name="iot-repub-rule-define"></a>

The AWS IoT rule that you'll create in this tutorial subscribes to the `device/device_id/data` MQTT topics where *device\$1id* is the ID of the device that sent the message. These topics are described by a [topic filter](topics.md#topicfilters) as `device/+/data`, where the `+` is a wildcard character that matches any string between the two forward slash characters.

When the rule receives a message from a matching topic, it republishes the `device_id` and `temperature` values as a new MQTT message with the `device/data/temp` topic. 

For example, the payload of an MQTT message with the `device/22/data` topic looks like this:

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

The rule takes the `temperature` value from the message payload, and the `device_id` from the topic, and republishes them as an MQTT message with the `device/data/temp` topic and a message payload that looks like this:

```
{
  "device_id": "22",
  "temperature": 28
}
```

With this rule, devices that only need the device's ID and the temperature data subscribe to the `device/data/temp` topic to receive only that information.

**To create a rule that republishes an MQTT message**

1. Open [the **Rules** hub of the AWS IoT console](https://console.aws.amazon.com//iot/home#/rulehub).

1. In **Rules**, choose **Create** and start creating your new rule.

1. In the top part of **Create a rule**:

   1. In **Name**, enter the rule's name. For this tutorial, name it **republish\$1temp**.

      Remember that a rule name must be unique within your Account and Region, and it can't have any spaces. We've used an underscore character in this name to separate the two words in the rule's name.

   1.  In **Description**, describe the rule. 

      A meaningful description helps you remember what this rule does and why you created it. The description can be as long as needed, so be as detailed as possible. 

1. In **Rule query statement** of **Create a rule**:

   1.  In **Using SQL version**, select **2016-03-23**. 

   1. In the **Rule query statement** edit box, enter the statement: 

      ```
      SELECT topic(2) as device_id, temperature FROM 'device/+/data'
      ```

      This statement:
      + Listens for MQTT messages with a topic that matches the `device/+/data` topic filter.
      + Selects the second element from the topic string and assigns it to the `device_id` field.
      + Selects the value `temperature` field from the message payload and assigns it to the `temperature` field.

1. In **Set one or more actions**:

   1. To open up the list of rule actions for this rule, choose **Add action**.

   1. In **Select an action**, choose **Republish a message to an AWS IoT topic**.

   1. At the bottom of the action list, choose **Configure action** to open the selected action's configuration page.

1. In **Configure action**:

   1.  In **Topic**, enter **device/data/temp**. This is the MQTT topic of the message that this rule will publish. 

   1.  In **Quality of Service**, choose **0 - The message is delivered zero or more times**. 

   1.  In **Choose or create a role to grant AWS IoT access to perform this action**:

      1.  Choose **Create Role**. The **Create a new role** dialog box opens. 

      1. Enter a name that describes the new role. In this tutorial, use **republish\$1role**. 

         When you create a new role, the correct policies to perform the rule action are created and attached to the new role. If you change the topic of this rule action or use this role in another rule action, you must update the policy for that role to authorize the new topic or action. To update an existing role, choose **Update role** in this section.

      1. Choose **Create Role** to create the role and close the dialog box. 

   1. Choose **Add action** to add the action to the rule and return to the **Create a rule** page. 

1. The **Republish a message to an AWS IoT topic** action is now listed in **Set one or more actions**.

   In the new action's tile, below **Republish a message to an AWS IoT topic**, you can see the topic to which your republish action will publish.

   This is the only rule action you'll add to this rule.

1. In **Create a rule**, scroll down to the bottom and choose **Create rule** to create the rule and complete this step.

## Step 2: Test your new rule
<a name="iot-repub-rule-test"></a>

To test your new rule, you'll use the MQTT client to publish and subscribe to the MQTT messages used by this rule.

Open the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test) in a new window. This will let you edit the rule without losing the configuration of your MQTT client. The MQTT client does not retain any subscriptions or message logs if you leave it to go to another page in the console.

**To use the MQTT client to test your rule**

1. In the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test), subscribe to the input topics, in this case, `device/+/data`.

   1. In the MQTT client, under **Subscriptions**, choose **Subscribe to a topic**.

   1. In **Subscription topic**, enter the topic of the input topic filter, **device/\$1/data**.

   1. Keep the rest of the fields at their default settings.

   1. Choose **Subscribe to topic**.

      In the **Subscriptions** column, under **Publish to a topic**, **device/\$1/data** appears. 

1. Subscribe to the topic that your rule will publish: `device/data/temp`.

   1. Under **Subscriptions**, choose **Subscribe to a topic** again, and in **Subscription topic**, enter the topic of the republished message, **device/data/temp**.

   1. Keep the rest of the fields at their default settings.

   1. Choose **Subscribe to topic**.

      In the **Subscriptions** column, under **device/\$1/data**, **device/data/temp** appears. 

1. Publish a message to the input topic with a specific device ID, **device/22/data**. You can't publish to MQTT topics that contain wildcard characters.

   1. In the MQTT client, under **Subscriptions**, choose **Publish to topic**.

   1. In the **Publish** field, enter the input topic name, **device/22/data**.

   1. Copy the sample data shown here and, in the edit box below the topic name, paste the sample data.

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. To send your MQTT message, choose **Publish to topic**.

1. Review the messages that were sent.

   1. In the MQTT client, under **Subscriptions**, there is a green dot next to the two topics to which you subscribed earlier.

      The green dots indicate that one or more new messages have been received since the last time you looked at them.

   1. Under **Subscriptions**, choose **device/\$1/data** to check that the message payload matches what you just published and looks like this:

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. Under **Subscriptions**, choose **device/data/temp** to check that your republished message payload looks like this:

      ```
      {
        "device_id": "22",  
        "temperature": 28
      }
      ```

      Notice that the `device_id` value is a quoted string and the `temperature` value is numeric. This is because the [https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic](https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic) function extracted the string from the input message's topic name while the `temperature` value uses the numeric value from the input message's payload.

      If you want to make the `device_id` value a numeric value, replace `topic(2)` in the rule query statement with:

      ```
      cast(topic(2) AS DECIMAL)
      ```

      Note that casting the `topic(2)` value to a numeric value will only work if that part of the topic contains only numeric characters.

1. If you see that the correct message was published to the **device/data/temp** topic, then your rule worked. See what more you can learn about the Republish rule action in the next section.

   If you don't see that the correct message was published to either the **device/\$1/data** or **device/data/temp** topics, check the troubleshooting tips.

### Troubleshooting your Republish message rule
<a name="iot-repub-rule-trouble"></a>

Here are some things to check in case you're not seeing the results you expect.
+ 

**You got an error banner**  
If an error appeared when you published the input message, correct that error first. The following steps might help you correct that error.
+ 

**You don't see the input message in the MQTT client**  
Every time you publish your input message to the `device/22/data` topic, that message should appear in the MQTT client if you subscribed to the `device/+/data` topic filter as described in the procedure.

**Things to check**
  + 

**Check the topic filter you subscribed to**  
If you subscribed to the input message topic as described in the procedure, you should see a copy of the input message every time you publish it.

    If you don't see the message, check the topic name you subscribed to and compare it to the topic to which you published. Topic names are case sensitive and the topic to which you subscribed must be identical to the topic to which you published the message payload.
  + 

**Check the message publish function**  
In the MQTT client, under **Subscriptions**, choose **device/\$1/data**, check the topic of the publish message, and then choose **Publish to topic**. You should see the message payload from the edit box below the topic appear in the message list. 
+ 

**You don't see your republished message in the MQTT client**  
For your rule to work, it must have the correct policy that authorizes it to receive and republish a message and it must receive the message.

**Things to check**
  + 

**Check the AWS Region of your MQTT client and the rule that you created**  
The console in which you're running the MQTT client must be in the same AWS Region as the rule you created. 
  + 

**Check the input message topic in the rule query statement**  
For the rule to work, it must receive a message with the topic name that matches the topic filter in the FROM clause of the rule query statement.

    Check the spelling of the topic filter in the rule query statement with that of the topic in the MQTT client. Topic names are case sensitive and the message's topic must match the topic filter in the rule query statement.
  + 

**Check the contents of the input message payload**  
For the rule to work, it must find the data field in the message payload that is declared in the SELECT statement.

    Check the spelling of the `temperature` field in the rule query statement with that of the message payload in the MQTT client. Field names are case sensitive and the `temperature` field in the rule query statement must be identical to the `temperature` field in the message payload.

    Make sure that the JSON document in the message payload is correctly formatted. If the JSON has any errors, such as a missing comma, the rule will not be able to read it. 
  + 

**Check the republished message topic in the rule action**  
The topic to which the Republish rule action publishes the new message must match the topic to which you subscribed in the MQTT client.

    Open the rule you created in the console and check the topic to which the rule action will republish the message.
  + 

**Check the role being used by the rule**  
The rule action must have permission to receive the original topic and publish the new topic. 

    The policies that authorize the rule to receive message data and republish it are specific to the topics used. If you change the topic used to republish the message data, you must update the rule action's role to update its policy to match the current topic.

    If you suspect this is the problem, edit the Republish rule action and create a new role. New roles created by the rule action receive the authorizations necessary to perform these actions.

## Step 3: Review the results and next steps
<a name="iot-repub-rule-review"></a>

**In this tutorial**
+ You used a simple SQL query and a couple of functions in a rule query statement to produce a new MQTT message.
+ You created a rule that republished that new message.
+ You used the MQTT client to test your AWS IoT rule.

**Next steps**  
After you republish a few messages with this rule, try experimenting with it to see how changing some aspects of the tutorial affect the republished message. Here are some ideas to get you started.
+ Change the *device\$1id* in the input message's topic and observe the effect in the republished message payload.
+ Change the fields selected in the rule query statement and observe the effect in the republished message payload.
+ Try the next tutorial in this series and learn how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md).

The Republish rule action used in this tutorial can also help you debug rule query statements. For example, you can add this action to a rule to see how its rule query statement is formatting the data used by its rule actions.

# Tutorial: Sending an Amazon SNS notification
<a name="iot-sns-rule"></a>

This tutorial demonstrates how to create an AWS IoT rule that sends MQTT message data to an Amazon SNS topic so that it can be sent as an SMS text message. 

In this tutorial, you create a rule that sends message data from a weather sensor to all subscribers of an Amazon SNS topic, whenever the temperature exceeds the value set in the rule. The rule detects when the reported temperature exceeds the value set by the rule, and then creates a new message payload that includes only the device ID, the reported temperature, and the temperature limit that was exceeded. The rule sends the new message payload as a JSON document to an SNS topic, which notifies all subscribers to the SNS topic.

**What you'll learn in this tutorial:**
+ How to create and test an Amazon SNS notification
+ How to call an Amazon SNS notification from an AWS IoT rule
+ How to use simple SQL queries and functions in a rule query statement
+ How to use the MQTT client to test an AWS IoT rule

This tutorial takes about 30 minutes to complete.

**Topics**
+ [Step 1: Create an Amazon SNS topic that sends a SMS text message](#iot-sns-rule-create-sns-topic)
+ [Step 2: Create an AWS IoT rule to send the text message](#iot-sns-rule-create-rule)
+ [Step 3: Test the AWS IoT rule and Amazon SNS notification](#iot-sns-rule-test-rule)
+ [Step 4: Review the results and next steps](#iot-sns-rule-review-results)

**Before you start this tutorial, make sure that you have:**
+ 

**[Set up AWS account](setting-up.md)**  
You'll need your AWS account and AWS IoT console to complete this tutorial.
+ 

**Reviewed [View MQTT messages with the AWS IoT MQTT client](view-mqtt-messages.md)**  
Be sure you can use the MQTT client to subscribe and publish to a topic. You'll use the MQTT client to test your new rule in this procedure.
+ 

**Reviewed the [Amazon Simple Notification Service](https://docs.aws.amazon.com//sns/latest/dg/welcome.html)**  
If you haven't used Amazon SNS before, review [Setting up access for Amazon SNS](https://docs.aws.amazon.com//sns/latest/dg/sns-setting-up.html). If you've already completed other AWS IoT tutorials, your AWS account should already be configured correctly.

## Step 1: Create an Amazon SNS topic that sends a SMS text message
<a name="iot-sns-rule-create-sns-topic"></a>

This procedure exaplains how to create the Amazon SNS topic your weather sensor can send message data to. The Amazon SNS topic will then notify all of its subscribers via a SMS text message of the temperature limit that was exceeded.

**To create an Amazon SNS topic that sends an SMS text message**

1. **Create an Amazon SNS topic.**

   1. Sign in to the [Amazon SNS console](https://console.aws.amazon.com//sns/home).

   1. In the left navigation pane, choose **Topics**.

   1. On the **Topics** page, choose **Create topic**.

   1. In **Details**, choose the **Standard** type. By default, the console creates a FIFO topic.

   1. In **Name**, enter the SNS topic name. For this tutorial, enter **high\$1temp\$1notice**.

   1. Scroll to the end of the page and choose **Create topic**.

      The console opens the new topic's **Details** page.

1. **Create an Amazon SNS subscription.**
**Note**  
The phone number that you use in this subscription might incur text messaging charges from the messages you will send in this tutorial.

   1. In the **high\$1temp\$1notice** topic's details page, choose **Create subscription**.

   1. In **Create subscription**, in the **Details** section, in the **Protocol** list, choose **SMS**.

   1. In **Endpoint**, enter the number of a phone that can receive text messages. Be sure to enter it such that it starts with a `+`, includes the country and area code, and doesn't include any other punctuation characters.

   1. Choose **Create subscription**.

1. **Test the Amazon SNS notification.**

   1. In the [Amazon SNS console](https://console.aws.amazon.com//sns/home), in the left navigation pane, choose **Topics**.

   1. To open the topic's details page, in **Topics**, in the list of topics, choose **high\$1temp\$1notice**.

   1. To open the **Publish message to topic** page, in the **high\$1temp\$1notice** details page, choose **Publish message**.

   1. In **Publish message to topic**, in the** Message body** section, in **Message body to send to the endpoint**, enter a short message.

   1. Scroll down to the bottom of the page and choose **Publish message**.

   1. On the phone with the number you used earlier when creating the subscription, confirm that the message was received.

   If you did not receive the test message, double check the phone number and your phone's settings.

   Make sure you can publish test messages from the [Amazon SNS console](https://console.aws.amazon.com//sns/home) before you continue the tutorial.

## Step 2: Create an AWS IoT rule to send the text message
<a name="iot-sns-rule-create-rule"></a>

The AWS IoT rule that you'll create in this tutorial subscribes to the `device/device_id/data` MQTT topics where `device_id` is the ID of the device that sent the message. These topics are described in a topic filter as `device/+/data`, where the `+` is a wildcard character that matches any string between the two forward slash characters. This rule also tests the value of the `temperature` field in the message payload.

When the rule receives a message from a matching topic, it takes the `device_id` from the topic name, the `temperature` value from the message payload, and adds a constant value for the limit it's testing, and sends these values as a JSON document to an Amazon SNS notification topic. 

 For example, an MQTT message from weather sensor device number 32 uses the `device/32/data` topic and has a message payload that looks like this: 

```
{
  "temperature": 38,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

The rule's rule query statement takes the `temperature` value from the message payload, the `device_id` from the topic name, and adds the constant `max_temperature` value to send a message payload that looks like this to the Amazon SNS topic: 

```
{
  "device_id": "32",
  "reported_temperature": 38,
  "max_temperature": 30
}
```

**To create an AWS IoT rule to detect an over-limit temperature value and create the data to send to the Amazon SNS topic**

1. Open [the **Rules** hub of the AWS IoT console](https://console.aws.amazon.com//iot/home#/rulehub).

1. If this is your first rule, choose **Create**, or **Create a rule**.

1. In **Create a rule**:

   1. In **Name**, enter **temp\$1limit\$1notify**.

      Remember that a rule name must be unique within your AWS account and Region, and it can't have any spaces. We've used an underscore character in this name to separate the words in the rule's name. 

   1. In **Description**, describe the rule.

      A meaningful description makes it easier to remember what this rule does and why you created it. The description can be as long as needed, so be as detailed as possible. 

1. In **Rule query statement** of **Create a rule**:

   1.  In **Using SQL version**, select **2016-03-23**. 

   1. In the **Rule query statement** edit box, enter the statement: 

      ```
      SELECT topic(2) as device_id, 
          temperature as reported_temperature, 
          30 as max_temperature 
        FROM 'device/+/data' 
        WHERE temperature > 30
      ```

      This statement:
      + Listens for MQTT messages with a topic that matches the `device/+/data` topic filter and that have a `temperature` value greater than 30. 
      + Selects the second element from the topic string and assigns it to the `device_id` field.
      + Selects the value `temperature` field from the message payload and assigns it to the `reported_temperature` field. 
      + Creates a constant value `30` to represent the limit value and assigns it to the `max_temperature` field. 

1. To open up the list of rule actions for this rule, in **Set one or more actions**, choose **Add action**.

1. In **Select an action**, choose **Send a message as an SNS push notification**.

1. To open the selected action's configuration page, at the bottom of the action list, choose **Configure action**. 

1. In **Configure action**:

   1. In **SNS target**, choose **Select**, find your SNS topic named **high\$1temp\$1notice**, and choose **Select**.

   1. In **Message format**, choose **RAW**.

   1. In **Choose or create a role to grant AWS IoT access to perform this action**, choose **Create Role**.

   1. In **Create a new role**, in **Name**, enter a unique name for the new role. For this tutorial, use **sns\$1rule\$1role**.

   1. Choose **Create role**.

   If you're repeating this tutorial or reusing an existing role, choose **Update role** before continuing. This updates the role's policy document to work with the SNS target.

1. Choose **Add action** and return to the **Create a rule** page.

   In the new action's tile, below **Send a message as an SNS push notification**, you can see the SNS topic that your rule will call. 

   This is the only rule action you'll add to this rule.

1. To create the rule and complete this step, in **Create a rule**, scroll down to the bottom and choose **Create rule**.

## Step 3: Test the AWS IoT rule and Amazon SNS notification
<a name="iot-sns-rule-test-rule"></a>

To test your new rule, you'll use the MQTT client to publish and subscribe to the MQTT messages used by this rule.

Open the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test) in a new window. This will let you edit the rule without losing the configuration of your MQTT client. If you leave the MQTT client to go to another page in the console, it won't retain any subscriptions or message logs.

**To use the MQTT client to test your rule**

1. In the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test), subscribe to the input topics, in this case, `device/+/data`.

   1. In the MQTT client, under **Subscriptions**, choose **Subscribe to a topic**.

   1. In **Subscription topic**, enter the topic of the input topic filter, **device/\$1/data**.

   1. Keep the rest of the fields at their default settings.

   1. Choose **Subscribe to topic**.

      In the **Subscriptions** column, under **Publish to a topic**, **device/\$1/data** appears. 

1. Publish a message to the input topic with a specific device ID, **device/32/data**. You can't publish to MQTT topics that contain wildcard characters.

   1. In the MQTT client, under **Subscriptions**, choose **Publish to topic**.

   1. In the **Publish** field, enter the input topic name, **device/32/data**.

   1. Copy the sample data shown here and, in the edit box below the topic name, paste the sample data.

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. Choose **Publish to topic** to publish your MQTT message.

1. Confirm that the text message was sent.

   1. In the MQTT client, under **Subscriptions**, there is a green dot next to the topic to which you subscribed earlier.

      The green dot indicates that one or more new messages have been received since the last time you looked at them.

   1. Under **Subscriptions**, choose **device/\$1/data** to check that the message payload matches what you just published and looks like this:

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. Check the phone that you used to subscribe to the SNS topic and confirm the contents of the message payload look like this:

      ```
      {"device_id":"32","reported_temperature":38,"max_temperature":30}
      ```

      Notice that the `device_id` value is a quoted string and the `temperature` value is numeric. This is because the [https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic](https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic) function extracted the string from the input message's topic name while the `temperature` value uses the numeric value from the input message's payload.

      If you want to make the `device_id` value a numeric value, replace `topic(2)` in the rule query statement with:

      ```
      cast(topic(2) AS DECIMAL)
      ```

      Note that casting the `topic(2)` value to a numeric, `DECIMAL` value will only work if that part of the topic contains only numeric characters.

1. Try sending an MQTT message in which the temperature does not exceed the limit.

   1. In the MQTT client, under **Subscriptions**, choose **Publish to topic**.

   1. In the **Publish** field, enter the input topic name, **device/33/data**.

   1. Copy the sample data shown here and, in the edit box below the topic name, paste the sample data.

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. To send your MQTT message, choose **Publish to topic**.

   You should see the message that you sent in the **device/\$1/data** subscription. However, because the temperature value is below the max temperature in the rule query statement, you shouldn't receive a text message.

   If you don't see the correct behavior, check the troubleshooting tips.

### Troubleshooting your SNS message rule
<a name="iot-sns-rule-trouble"></a>

Here are some things to check, in case you're not seeing the results you expect.
+ 

**You got an error banner**  
If an error appeared when you published the input message, correct that error first. The following steps might help you correct that error.
+ 

**You don't see the input message in the MQTT client**  
Every time you publish your input message to the `device/22/data` topic, that message should appear in the MQTT client, if you subscribed to the `device/+/data` topic filter as described in the procedure.

**Things to check**
  + 

**Check the topic filter you subscribed to**  
If you subscribed to the input message topic as described in the procedure, you should see a copy of the input message every time you publish it.

    If you don't see the message, check the topic name you subscribed to and compare it to the topic to which you published. Topic names are case sensitive and the topic to which you subscribed must be identical to the topic to which you published the message payload.
  + 

**Check the message publish function**  
In the MQTT client, under **Subscriptions**, choose **device/\$1/data**, check the topic of the publish message, and then choose **Publish to topic**. You should see the message payload from the edit box below the topic appear in the message list. 
+ 

**You don't receive an SMS message**  
For your rule to work, it must have the correct policy that authorizes it to receive a message and send an SNS notification, and it must receive the message.

**Things to check**
  + 

**Check the AWS Region of your MQTT client and the rule that you created**  
The console in which you're running the MQTT client must be in the same AWS Region as the rule you created.
  + 

**Check that the temperature value in the message payload exceeds the test threshold**  
If the temperature value is less than or equal to 30, as defined in the rule query statement, the rule will not perform any of its actions.
  + 

**Check the input message topic in the rule query statement**  
For the rule to work, it must receive a message with the topic name that matches the topic filter in the FROM clause of the rule query statement.

    Check the spelling of the topic filter in the rule query statement with that of the topic in the MQTT client. Topic names are case sensitive and the message's topic must match the topic filter in the rule query statement.
  + 

**Check the contents of the input message payload**  
For the rule to work, it must find the data field in the message payload that is declared in the SELECT statement.

    Check the spelling of the `temperature` field in the rule query statement with that of the message payload in the MQTT client. Field names are case sensitive and the `temperature` field in the rule query statement must be identical to the `temperature` field in the message payload.

    Make sure that the JSON document in the message payload is correctly formatted. If the JSON has any errors, such as a missing comma, the rule will not be able to read it.
  + 

**Check the republished message topic in the rule action**  
The topic to which the Republish rule action publishes the new message must match the topic to which you subscribed in the MQTT client.

    Open the rule you created in the console and check the topic to which the rule action will republish the message.
  + 

**Check the role being used by the rule**  
The rule action must have permission to receive the original topic and publish the new topic. 

    The policies that authorize the rule to receive message data and republish it are specific to the topics used. If you change the topic used to republish the message data, you must update the rule action's role to update its policy to match the current topic.

    If you suspect this is the problem, edit the Republish rule action and create a new role. New roles created by the rule action receive the authorizations necessary to perform these actions.

## Step 4: Review the results and next steps
<a name="iot-sns-rule-review-results"></a>

**In this tutorial:**
+ You created and tested an Amazon SNS notification topic and subscription.
+ You used a simple SQL query and functions in a rule query statement to create a new message for your notification.
+ You created an AWS IoT rule to send an Amazon SNS notification that used your customized message payload.
+ You used the MQTT client to test your AWS IoT rule.

**Next steps**  
After you send a few text messages with this rule, try experimenting with it to see how changing some aspects of the tutorial affect the message and when it's sent. Here are some ideas to get you started.
+ Change the *device\$1id* in the input message's topic and observe the effect in the text message contents.
+ Change the fields selected in the rule query statement and observe the effect in the text message contents.
+ Change the test in the rule query statement to test for a minimum temperature instead of a maximum temperature. Remember to change the name of `max_temperature`\$1
+ Add a republish rule action to send an MQTT message when an SNS notification is sent.
+ Try the next tutorial in this series and learn how to [Tutorial: Storing device data in a DynamoDB table](iot-ddb-rule.md).

# Tutorial: Storing device data in a DynamoDB table
<a name="iot-ddb-rule"></a>

This tutorial demonstrates how to create an AWS IoT rule that sends message data to a DynamoDB table.

In this tutorial, you create a rule that sends message data from an imaginary weather sensor device to a DynamoDB table. The rule formats the data from many weather sensors such that they can be added to a single database table.

**What you'll learn in this tutorial**
+ How to create a DynamoDB table
+ How to send message data to a DynamoDB table from an AWS IoT rule
+ How to use substitution templates in an AWS IoT rule
+ How to use simple SQL queries and functions in a rule query statement
+ How to use the MQTT client to test an AWS IoT rule

This tutorial takes about 30 minutes to complete.

**Topics**
+ [Step 1: Create the DynamoDB table for this tutorial](#iot-ddb-rule-ddb-table)
+ [Step 2: Create an AWS IoT rule to send data to the DynamoDB table](#iot-ddb-rule-topic-rule)
+ [Step 3: Test the AWS IoT rule and DynamoDB table](#iot-ddb-rule-test)
+ [Step 4: Review the results and next steps](#iot-ddb-rule-review)

**Before you start this tutorial, make sure that you have:**
+ 

**[Set up AWS account](setting-up.md)**  
You'll need your AWS account and AWS IoT console to complete this tutorial.
+ 

**Reviewed [View MQTT messages with the AWS IoT MQTT client](view-mqtt-messages.md)**  
Be sure you can use the MQTT client to subscribe and publish to a topic. You'll use the MQTT client to test your new rule in this procedure.
+ 

**Reviewed the [Amazon DynamoDB](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Introduction.html) overview**  
If you've not used DynamoDB before, review [Getting Started with DynamoDB](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html) to become familiar with the basic concepts and operations of DynamoDB.

## Step 1: Create the DynamoDB table for this tutorial
<a name="iot-ddb-rule-ddb-table"></a>

In this tutorial, you'll create a DynamoDB table with these attributes to record the data from the imaginary weather sensor devices: 
+ `sample_time` is a primary key and describes the time the sample was recorded.
+ `device_id` is a sort key and describes the device that provided the sample 
+ `device_data` is the data received from the device and formatted by the rule query statement

**To create the DynamoDB table for this tutorial**

1. Open the [DynamoDB console](https://console.aws.amazon.com//dynamodb/home), and then choose **Create table**.

1. In **Create table**:

   1.  In **Table name**, enter the table name: **wx\$1data**.

   1. In **Partition key**, enter **sample\$1time**, and in the option list next to the field, choose **Number**.

   1. In **Sort key**, enter **device\$1id**, and in the option list next to the field, choose **Number**.

   1. At the bottom of the page, choose **Create**.

You'll define `device_data` later, when you configure the DynamoDB rule action.

## Step 2: Create an AWS IoT rule to send data to the DynamoDB table
<a name="iot-ddb-rule-topic-rule"></a>

In this step, you'll use the rule query statement to format the data from the imaginary weather sensor devices to write to the database table.

A sample message payload received from a weather sensor device looks like this:

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

For the database entry, you'll use the rule query statement to flatten the structure of the message payload to look like this:

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind_velocity": 22,
  "wind_bearing": 255
}
```

In this rule, you'll also use a couple of [Substitution templates](iot-substitution-templates.md). Substitution templates are expressions that let you insert dynamic values from functions and message data.

**To create the AWS IoT rule to send data to the DynamoDB table**

1. Open [the Rules hub of the AWS IoT console](https://console.aws.amazon.com//iot/home#/rulehub). Or, you can open the AWS IoT homepage within the AWS Management Console and navigate to **Message routing>Rules**.

1. To start creating your new rule in **Rules**, choose **Create rule**.

1. In **Rule properties**:

   1. In **Rule name**, enter **wx\$1data\$1ddb**.

      Remember that a rule name must be unique within your AWS account and Region, and it can't have any spaces. We've used an underscore character in this name to separate the two words in the rule's name.

   1. In **Rule description**, describe the rule.

      A meaningful description makes it easier to remember what this rule does and why you created it. The description can be as long as needed, so be as detailed as possible. 

1. Choose **Next** to continue.

1. In **SQL statement**:

   1. In **SQL version**, select **2016-03-23**.

   1. In the **SQL statement** edit box, enter the statement: 

      ```
      SELECT temperature, humidity, barometer,
        wind.velocity as wind_velocity,
        wind.bearing as wind_bearing,
      FROM 'device/+/data'
      ```

      This statement:
      + Listens for MQTT messages with a topic that matches the `device/+/data` topic filter.
      + Formats the elements of the `wind` attribute as individual attributes.
      + Passes the `temperature`, `humidity`, and `barometer` attributes unchanged.

1. Choose **Next** to continue.

1. In **Rule actions**:

   1. To open the list of rule actions for this rule, in **Action 1**, choose **DynamoDB**.
**Note**  
Make sure that you choose DynamoDB and not DynamoDBv2 as the rule action.

   1. In **Table name**, choose the name of the DynamoDB table you created in a previous step: **wx\$1data**.

      The **Partition key type** and **Sort key type** fields are filled with the values from your DynamoDB table.

   1. In **Partition key**, enter **sample\$1time**.

   1. In **Partition key value**, enter **\$1\$1timestamp()\$1**.

      This is the first of the [Substitution templates](iot-substitution-templates.md) you'll use in this rule. Instead of using a value from the message payload, it will use the value returned from the timestamp function. To learn more, see [timestamp](iot-sql-functions.md#iot-function-timestamp) in the *AWS IoT Core Developer Guide*.

   1. In **Sort key**, enter **device\$1id**.

   1. In **Sort key value**, enter **\$1\$1cast(topic(2) AS DECIMAL)\$1**.

      This is the second one of the [Substitution templates](iot-substitution-templates.md) you'll use in this rule. It inserts the value of the second element in topic name, which is the device's ID, after it casts it to a DECIMAL value to match the numeric format of the key. To learn more about topics, see [topic](iot-sql-functions.md#iot-function-topic) in the *AWS IoT Core Developer Guide*. Or to learn more about casting, see [cast](iot-sql-functions.md#iot-sql-function-cast) in the *AWS IoT Core Developer Guide*.

   1. In **Write message data to this column**, enter **device\$1data**.

      This will create the `device_data` column in the DynamoDB table.

   1. Leave **Operation** blank.

   1. In **IAM role**, choose **Create new role**.

   1. In the **Create role** dialog box, for **Role name**, enter **wx\$1ddb\$1role**. This new role will automatically contain a policy with a prefix of "aws-iot-rule" that will allow the **wx\$1data\$1ddb** rule to send data to the **wx\$1data** DynamoDB table you created.

   1. In **IAM role**, choose **wx\$1ddb\$1role**.

   1. At the bottom of the page, choose **Next**.

1. At the bottom of the **Review and create** page, choose **Create** to create the rule.

## Step 3: Test the AWS IoT rule and DynamoDB table
<a name="iot-ddb-rule-test"></a>

To test the new rule, you'll use the MQTT client to publish and subscribe to the MQTT messages used in this test.

Open the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test) in a new window. This will let you edit the rule without losing the configuration of your MQTT client. The MQTT client does not retain any subscriptions or message logs if you leave it to go to another page in the console. You'll also want a separate console window open to the [DynamoDB Tables hub in the AWS IoT console](https://console.aws.amazon.com//dynamodb/home#tables:) to view the new entries that your rule sends.

**To use the MQTT client to test your rule**

1. In the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test), subscribe to the input topic, `device/+/data`.

   1. In the MQTT client, choose **Subscribe to a topic**.

   1. For **Topic filter**, enter the topic of the input topic filter, **device/\$1/data**.

   1. Choose **Subscribe**.

1. Now, publish a message to the input topic with a specific device ID, **device/22/data**. You can't publish to MQTT topics that contain wildcard characters.

   1. In the MQTT client, choose **Publish to a topic**.

   1. For **Topic name**, enter the input topic name, **device/22/data**.

   1. For **Message payload**, enter the following sample data.

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. To publish the MQTT message, choose **Publish**.

   1. Now, in the MQTT client, choose **Subscribe to a topic**. In the **Subscribe** column, choose the **device/\$1/data** subscription. Confirm that the sample data from the previous step appears there.

1. Check to see the row in the DynamoDB table that your rule created.

   1. In the [DynamoDB Tables hub in the AWS IoT console](https://console.aws.amazon.com//dynamodb/home#tables:), choose **wx\$1data**, and then choose the **Items** tab.

      If you're already on the **Items** tab, you might need to refresh the display by choosing the refresh icon in the upper-right corner of the table's header.

   1. Notice that the **sample\$1time** values in the table are links and open one. If you just sent your first message, it will be the only one in the list.

      This link displays all the data in that row of the table.

   1. Expand the **device\$1data** entry to see the data that resulted from the rule query statement.

   1. Explore the different representations of the data that are available in this display. You can also edit the data in this display.

   1. After you have finished reviewing this row of data, to save any changes you made, choose **Save**, or to exit without saving any changes, choose **Cancel**.

If you don't see the correct behavior, check the troubleshooting tips.

### Troubleshooting your DynamoDB rule
<a name="iot-ddb-rule-trouble"></a>

Here are some things to check in case you're not seeing the results you expect.
+ 

**You got an error banner**  
If an error appeared when you published the input message, correct that error first. The following steps might help you correct that error.
+ 

**You don't see the input message in the MQTT client**  
Every time you publish your input message to the `device/22/data` topic, that message should appear in the MQTT client if you subscribed to the `device/+/data` topic filter as described in the procedure.

**Things to check**
  + 

**Check the topic filter you subscribed to**  
If you subscribed to the input message topic as described in the procedure, you should see a copy of the input message every time you publish it.

    If you don't see the message, check the topic name you subscribed to and compare it to the topic to which you published. Topic names are case sensitive and the topic to which you subscribed must be identical to the topic to which you published the message payload.
  + 

**Check the message publish function**  
In the MQTT client, under **Subscriptions**, choose **device/\$1/data**, check the topic of the publish message, and then choose **Publish to topic**. You should see the message payload from the edit box below the topic appear in the message list. 
+ 

**You don't see your data in the DynamoDB table**  
The first thing to do is to refresh the display by choosing the refresh icon in the upper-right corner of the table's header. If that doesn't display the data you're looking for, check the following.

**Things to check**
  + 

**Check the AWS Region of your MQTT client and the rule that you created**  
The console in which you're running the MQTT client must be in the same AWS Region as the rule you created. 
  + 

**Check the input message topic in the rule query statement**  
For the rule to work, it must receive a message with the topic name that matches the topic filter in the FROM clause of the rule query statement.

    Check the spelling of the topic filter in the rule query statement with that of the topic in the MQTT client. Topic names are case sensitive and the message's topic must match the topic filter in the rule query statement.
  + 

**Check the contents of the input message payload**  
For the rule to work, it must find the data field in the message payload that is declared in the SELECT statement.

    Check the spelling of the `temperature` field in the rule query statement with that of the message payload in the MQTT client. Field names are case sensitive and the `temperature` field in the rule query statement must be identical to the `temperature` field in the message payload.

    Make sure that the JSON document in the message payload is correctly formatted. If the JSON has any errors, such as a missing comma, the rule will not be able to read it. 
  + 

**Check the key and field names used in the rule action**  
The field names used in the topic rule must match those found in the JSON message payload of the published message.

    Open the rule you created in the console and check the field names in the rule action configuration with those used in the MQTT client.
  + 

**Check the role being used by the rule**  
The rule action must have permission to receive the original topic and publish the new topic. 

    The policies that authorize the rule to receive message data and update the DynamoDB table are specific to the topics used. If you change the topic or DynamoDB table name used by the rule, you must update the rule action's role to update its policy to match.

    If you suspect this is the problem, edit the rule action and create a new role. New roles created by the rule action receive the authorizations necessary to perform these actions.

## Step 4: Review the results and next steps
<a name="iot-ddb-rule-review"></a>

After you send a few messages to the DynamoDB table with this rule, try experimenting with it to see how changing some aspects from the tutorial affect the data written to the table. Here are some ideas to get you started.
+ Change the *device\$1id* in the input message's topic and observe the effect on the data. You could use this to simulate receiving data from multiple weather sensors.
+ Change the fields selected in the rule query statement and observe the effect on the data. You could use this to filter the data stored in the table.
+ Add a republish rule action to send an MQTT message for each row added to the table. You could use this for debugging.

After you have completed this tutorial, check out [Tutorial: Formatting a notification by using an AWS Lambda function](iot-lambda-rule.md).

# Tutorial: Formatting a notification by using an AWS Lambda function
<a name="iot-lambda-rule"></a>

This tutorial demonstrates how to send MQTT message data to an AWS Lambda action for formatting and sending to another AWS service. In this tutorial, the AWS Lambda action uses the AWS SDK to send the formatted message to the Amazon SNS topic you created in the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md).

In the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md), the JSON document that resulted from the rule's query statement was sent as the body of the text message. The result was a text message that looked something like this example:

```
{"device_id":"32","reported_temperature":38,"max_temperature":30}
```

In this tutorial, you'll use an AWS Lambda rule action to call an AWS Lambda function that formats the data from the rule query statement into a friendlier format, such as this example:

```
Device 32 reports a temperature of 38, which exceeds the limit of 30.
```

The AWS Lambda function you'll create in this tutorial formats the message string by using the data from the rule query statement and calls the [SNS publish](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html#SNS.Client.publish) function of the AWS SDK to create the notification.

**What you'll learn in this tutorial**
+ How to create and test an AWS Lambda function
+ How to use the AWS SDK in an AWS Lambda function to publish an Amazon SNS notification
+ How to use simple SQL queries and functions in a rule query statement
+ How to use the MQTT client to test an AWS IoT rule

This tutorial takes about 45 minutes to complete.

**Topics**
+ [Step 1: Create an AWS Lambda function that sends a text message](#iot-lambda-rule-create-lambda)
+ [Step 2: Create an AWS IoT rule with an AWS Lambda rule action](#iot-lambda-rule-create-rule)
+ [Step 3: Test the AWS IoT rule and AWS Lambda rule action](#iot-lambda-rule-test-rule)
+ [Step 4: Review the results and next steps](#iot-lambda-rule-next-steps)

**Before you start this tutorial, make sure that you have:**
+ 

**[Set up AWS account](setting-up.md)**  
You'll need your AWS account and AWS IoT console to complete this tutorial.
+ 

**Reviewed [View MQTT messages with the AWS IoT MQTT client](view-mqtt-messages.md)**  
Be sure you can use the MQTT client to subscribe and publish to a topic. You'll use the MQTT client to test your new rule in this procedure.
+ 

**Completed the other rules tutorials in this section**  
This tutorial requires the SNS notification topic you created in the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md). It also assumes that you've completed the other rules-related tutorials in this section.
+ 

**Reviewed the [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) overview**  
If you haven't used AWS Lambda before, review [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) and [Getting started with Lambda](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html) to learn its terms and concepts.

## Step 1: Create an AWS Lambda function that sends a text message
<a name="iot-lambda-rule-create-lambda"></a>

The AWS Lambda function in this tutorial receives the result of the rule query statement, inserts the elements into a text string, and sends the resulting string to Amazon SNS as the message in a notification.

Unlike the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md), which used an AWS IoT rule action to send the notification, this tutorial sends the notification from the Lambda function by using a function of the AWS SDK. The actual Amazon SNS notification topic used in this tutorial, however, is the same one that you used in the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md).

**To create an AWS Lambda function that sends a text message**

1. Create a new AWS Lambda function.

   1. In the [AWS Lambda console](https://console.aws.amazon.com//lambda/home), choose **Create function**.

   1. In **Create function**, select **Use a blueprint**.

      Search for and select the **hello-world-python** blueprint, and then choose **Configure**.

   1. In **Basic information**:

      1. In **Function name**, enter the name of this function, **format-high-temp-notification**. 

      1. In **Execution role**, choose **Create a new role from AWS policy templates**.

      1. In Role name, enter the name of the new role, **format-high-temp-notification-role**.

      1. In **Policy templates - *optional***, search for and select **Amazon SNS publish policy**.

      1. Choose **Create function**.

1. Modify the blueprint code to format and send an Amazon SNS notification.

   1. After you created your function, you should see the **format-high-temp-notification** details page. If you don't, open it from the [Lambda **Functions**](https://console.aws.amazon.com//lambda/home#/functions) page.

   1. In the **format-high-temp-notification** details page, choose the **Configuration** tab and scroll to the **Function code** panel.

   1. In the **Function code** window, in the **Environment** pane, choose the Python file, `lambda_function.py`.

   1. In the **Function code** window, delete all of the original program code from the blueprint and replace it with this code.

      ```
      import boto3
      #
      #   expects event parameter to contain:
      #   {
      #       "device_id": "32",
      #       "reported_temperature": 38,
      #       "max_temperature": 30,
      #       "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
      #   }
      # 
      #   sends a plain text string to be used in a text message
      #
      #      "Device {0} reports a temperature of {1}, which exceeds the limit of {2}."
      #   
      #   where:
      #       {0} is the device_id value
      #       {1} is the reported_temperature value
      #       {2} is the max_temperature value
      #
      def lambda_handler(event, context):
      
          # Create an SNS client to send notification
          sns = boto3.client('sns')
      
          # Format text message from data
          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'])
              )
      
          # Publish the formatted message
          response = sns.publish(
                  TopicArn = event['notify_topic_arn'],
                  Message = message_text
              )
      
          return response
      ```

   1. Choose **Deploy**.

1. In a new window, look up the Amazon Resource Name (ARN) of your Amazon SNS topic from the tutorial about how to [Tutorial: Sending an Amazon SNS notification](iot-sns-rule.md).

   1. In a new window, open the [Topics page of the Amazon SNS console](https://console.aws.amazon.com//sns/v3/home#/topics). 

   1. In the **Topics** page, find the **high\$1temp\$1notice** notification topic in the list of Amazon SNS topics.

   1. Find the **ARN** of the **high\$1temp\$1notice** notification topic to use in the next step.

1. Create a test case for your Lambda function.

   1. In the [Lambda **Functions**](https://console.aws.amazon.com//lambda/home#/functions) page of the console, on the **format-high-temp-notification** details page, choose **Select a test event** in the upper right corner of the page (even though it looks disabled), and then choose **Configure test events**.

   1. In **Configure test event**, choose **Create new test event**.

   1. In **Event name**, enter **SampleRuleOutput**.

   1. In the JSON editor below **Event name**, paste this sample JSON document. This is an example of what your AWS IoT rule will send to the Lambda function.

      ```
      {
        "device_id": "32",
        "reported_temperature": 38,
        "max_temperature": 30,
        "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
      }
      ```

   1. Refer to the window that has the **ARN** of the **high\$1temp\$1notice** notification topic and copy the ARN value.

   1. Replace the `notify_topic_arn` value in the JSON editor with the ARN from your notification topic.

      Keep this window open so you can use this ARN value again when you create the AWS IoT rule.

   1. Choose **Create**.

1. Test the function with sample data.

   1. In the **format-high-temp-notification** details page, in the upper-right corner of the page, confirm that **SampleRuleOutput** appears next to the **Test** button. If it doesn't, choose it from the list of available test events.

   1. To send the sample rule output message to your function, choose **Test**.

If the function and the notification both worked, you will get a text message on the phone that subscribed to the notification.

If you didn't get a text message on the phone, check the result of the operation. In the **Function code** panel, in the **Execution result** tab, review the response to find any errors that occurred. Don't continue to the next step until your function can send the notification to your phone.

## Step 2: Create an AWS IoT rule with an AWS Lambda rule action
<a name="iot-lambda-rule-create-rule"></a>

In this step, you'll use the rule query statement to format the data from the imaginary weather sensor device to send to a Lambda function, which will format and send a text message.

A sample message payload received from the weather devices looks like this:

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

In this rule, you'll use the rule query statement to create a message payload for the Lambda function that looks like this:

```
{
  "device_id": "32",
  "reported_temperature": 38,
  "max_temperature": 30,
  "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
}
```

This contains all the information the Lambda function needs to format and send the correct text message.

**To create the AWS IoT rule to call a Lambda function**

1. Open the [**Rules** hub of the AWS IoT console](https://console.aws.amazon.com//iot/home#/rulehub).

1. To start creating your new rule in **Rules**, choose **Create**.

1. In the top part of **Create a rule**:

   1. In **Name**, enter the rule's name, **wx\$1friendly\$1text**.

      Remember that a rule name must be unique within your AWS account and Region, and it can't have any spaces. We've used an underscore character in this name to separate the two words in the rule's name.

   1.  In **Description**, describe the rule. 

      A meaningful description makes it easier to remember what this rule does and why you created it. The description can be as long as needed, so be as detailed as possible. 

1. In **Rule query statement** of **Create a rule**:

   1.  In **Using SQL version**, select **2016-03-23**. 

   1. In the **Rule query statement** edit box, enter the statement: 

      ```
      SELECT 
        cast(topic(2) AS DECIMAL) as device_id, 
        temperature as reported_temperature,
        30 as max_temperature,
        'arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice' as notify_topic_arn
      FROM 'device/+/data' WHERE temperature > 30
      ```

      This statement:
      + Listens for MQTT messages with a topic that matches the `device/+/data` topic filter and that have a `temperature` value greater than 30. 
      + Selects the second element from the topic string, converts it to a decimal number, and then assigns it to the `device_id` field.
      + Selects the value of the `temperature` field from the message payload and assigns it to the `reported_temperature` field. 
      + Creates a constant value, `30`, to represent the limit value and assigns it to the `max_temperature` field. 
      + Creates a constant value for the `notify_topic_arn` field.

   1. Refer to the window that has the **ARN** of the **high\$1temp\$1notice** notification topic and copy the ARN value.

   1. Replace the ARN value (*arn:aws:sns:us-east-1:57EXAMPLE833:high\$1temp\$1notice*) in the rule query statement editor with the ARN of your notification topic.

1. In **Set one or more actions**:

   1. To open up the list of rule actions for this rule, choose **Add action**.

   1. In **Select an action**, choose **Send a message to a Lambda function**.

   1. To open the selected action's configuration page, at the bottom of the action list, choose **Configure action**.

1. In **Configure action**:

   1. In **Function name**, choose **Select**.

   1. Choose **format-high-temp-notification**.

   1. At the bottom of **Configure action**, choose **Add action**.

   1. To create the rule, at the bottom of **Create a rule**, choose **Create rule**.

## Step 3: Test the AWS IoT rule and AWS Lambda rule action
<a name="iot-lambda-rule-test-rule"></a>

To test your new rule, you'll use the MQTT client to publish and subscribe to the MQTT messages used by this rule.

Open the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test) in a new window. Now you can edit the rule without losing the configuration of your MQTT client. If you leave the MQTT client to go to another page in the console, you'll lose your subscriptions or message logs.

**To use the MQTT client to test your rule**

1. In the [MQTT client in the AWS IoT console](https://console.aws.amazon.com//iot/home#/test), subscribe to the input topics, in this case, `device/+/data`.

   1. In the MQTT client, under **Subscriptions**, choose **Subscribe to a topic**.

   1. In **Subscription topic**, enter the topic of the input topic filter, **device/\$1/data**.

   1. Keep the rest of the fields at their default settings.

   1. Choose **Subscribe to topic**.

      In the **Subscriptions** column, under **Publish to a topic**, **device/\$1/data** appears. 

1. Publish a message to the input topic with a specific device ID, **device/32/data**. You can't publish to MQTT topics that contain wildcard characters.

   1. In the MQTT client, under **Subscriptions**, choose **Publish to topic**.

   1. In the **Publish** field, enter the input topic name, **device/32/data**.

   1. Copy the sample data shown here and, in the edit box below the topic name, paste the sample data.

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. To publish your MQTT message, choose **Publish to topic**.

1. Confirm that the text message was sent.

   1. In the MQTT client, under **Subscriptions**, there is a green dot next to the topic to which you subscribed earlier.

      The green dot indicates that one or more new messages have been received since the last time you looked at them.

   1. Under **Subscriptions**, choose **device/\$1/data** to check that the message payload matches what you just published and looks like this:

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. Check the phone that you used to subscribe to the SNS topic and confirm the contents of the message payload look like this:

      ```
      Device 32 reports a temperature of 38, which exceeds the limit of 30.
      ```

      If you change the topic ID element in the message topic, remember that casting the `topic(2)` value to a numeric value will only work if that element in the message topic contains only numeric characters.

1. Try sending an MQTT message in which the temperature does not exceed the limit.

   1. In the MQTT client, under **Subscriptions**, choose **Publish to topic**.

   1. In the **Publish** field, enter the input topic name, **device/33/data**.

   1. Copy the sample data shown here and, in the edit box below the topic name, paste the sample data.

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. To send your MQTT message, choose **Publish to topic**.

   You should see the message that you sent in the **device/\$1/data** subscription; however, because the temperature value is below the max temperature in the rule query statement, you shouldn't receive a text message.

   If you don't see the correct behavior, check the troubleshooting tips.

### Troubleshooting your AWS Lambda rule and notification
<a name="iot-lambda-rule-troubleshoot"></a>

Here are some things to check, in case you're not seeing the results you expect.
+ 

**You got an error banner**  
If an error appeared when you published the input message, correct that error first. The following steps might help you correct that error.
+ 

**You don't see the input message in the MQTT client**  
Every time you publish your input message to the `device/32/data` topic, that message should appear in the MQTT client, if you subscribed to the `device/+/data` topic filter as described in the procedure.

**Things to check**
  + 

**Check the topic filter you subscribed to**  
If you subscribed to the input message topic as described in the procedure, you should see a copy of the input message every time you publish it.

    If you don't see the message, check the topic name you subscribed to and compare it to the topic to which you published. Topic names are case sensitive and the topic to which you subscribed must be identical to the topic to which you published the message payload.
  + 

**Check the message publish function**  
In the MQTT client, under **Subscriptions**, choose **device/\$1/data**, check the topic of the publish message, and then choose **Publish to topic**. You should see the message payload from the edit box below the topic appear in the message list. 
+ 

**You don't receive an SMS message**  
For your rule to work, it must have the correct policy that authorizes it to receive a message and send an SNS notification, and it must receive the message.

**Things to check**
  + 

**Check the AWS Region of your MQTT client and the rule that you created**  
The console in which you're running the MQTT client must be in the same AWS Region as the rule you created.
  + 

**Check that the temperature value in the message payload exceeds the test threshold**  
If the temperature value is less than or equal to 30, as defined in the rule query statement, the rule will not perform any of its actions.
  + 

**Check the input message topic in the rule query statement**  
For the rule to work, it must receive a message with the topic name that matches the topic filter in the FROM clause of the rule query statement.

    Check the spelling of the topic filter in the rule query statement with that of the topic in the MQTT client. Topic names are case sensitive and the message's topic must match the topic filter in the rule query statement.
  + 

**Check the contents of the input message payload**  
For the rule to work, it must find the data field in the message payload that is declared in the SELECT statement.

    Check the spelling of the `temperature` field in the rule query statement with that of the message payload in the MQTT client. Field names are case sensitive and the `temperature` field in the rule query statement must be identical to the `temperature` field in the message payload.

    Make sure that the JSON document in the message payload is correctly formatted. If the JSON has any errors, such as a missing comma, the rule will not be able to read it.
  + 

**Check the Amazon SNS notification**  
In [Step 1: Create an Amazon SNS topic that sends a SMS text message](iot-sns-rule.md#iot-sns-rule-create-sns-topic), refer to step 3 that describes how to test the Amazon SNS notification and test the notification to make sure the notification works.
  + 

**Check the Lambda function**  
In [Step 1: Create an AWS Lambda function that sends a text message](#iot-lambda-rule-create-lambda), refer to step 5 that describes how to test the Lambda function using test data and test the Lambda function.
  + 

**Check the role being used by the rule**  
The rule action must have permission to receive the original topic and publish the new topic. 

    The policies that authorize the rule to receive message data and republish it are specific to the topics used. If you change the topic used to republish the message data, you must update the rule action's role to update its policy to match the current topic.

    If you suspect this is the problem, edit the Republish rule action and create a new role. New roles created by the rule action receive the authorizations necessary to perform these actions.

## Step 4: Review the results and next steps
<a name="iot-lambda-rule-next-steps"></a>

**In this tutorial:**
+ You created an AWS IoT rule to call a Lambda function that sent an Amazon SNS notification that used your customized message payload.
+ You used a simple SQL query and functions in a rule query statement to create a new message payload for your Lambda function.
+ You used the MQTT client to test your AWS IoT rule.

**Next steps**  
After you send a few text messages with this rule, try experimenting with it to see how changing some aspects of the tutorial affect the message and when it's sent. Here are some ideas to get you started.
+ Change the *device\$1id* in the input message's topic and observe the effect in the text message contents.
+ Change the fields selected in the rule query statement, update the Lambda function to use them in a new message, and observe the effect in the text message contents.
+ Change the test in the rule query statement to test for a minimum temperature instead of a maximum temperature. Update the Lambda function to format a new message and remember to change the name of `max_temperature`.
+ To learn more about how to find errors that might occur while you're developing and using AWS IoT rules, see [Monitoring AWS IoT](monitoring_overview.md).