

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 教程：重新发布 MQTT 消息
<a name="iot-repub-rule"></a>

本教程演示如何创建在收到指定的 MQTT 消息时发布 MQTT 消息的 AWS IoT 规则。可以在发布之前通过规则修改传入的消息有效载荷。这样就可以创建针对特定应用程序量身定制的消息，而无需更改设备或固件。您还可以使用规则的筛选功能仅在满足特定条件时发布消息。

通过规则重新发布的消息就像任何其他 AWS IoT 设备或客户端发送的消息一样。设备可以订阅重新发布的消息，就像订阅任何其它 MQTT 消息主题一样。

**您将在本教程中学到的内容：**
+ 如何在规则查询语句中使用简单的 SQL 查询和函数
+ 如何使用 MQTT 客户端测试规则 AWS IoT 

完成本教程需要大约 30 分钟。

**Topics**
+ [查看 MQTT 主题和规则 AWS IoT](#iot-repub-rule-mqtt)
+ [步骤 1：创建 AWS IoT 规则以重新发布 MQTT 消息](#iot-repub-rule-define)
+ [步骤 2：测试您的新规则](#iot-repub-rule-test)
+ [步骤 3：查看结果和后续步骤](#iot-repub-rule-review)

**在开始本教程之前，请确保您具有：**
+ 

**[设置 AWS 账户](setting-up.md)**  
你需要你的 AWS 账户 和 AWS IoT 主机才能完成本教程。
+ 

**审核 [使用 MQTT 客户端查看 AWS IoT MQTT 消息](view-mqtt-messages.md)**  
请确保您可以使用 MQTT 客户端订阅和发布主题。您将使用 MQTT 客户端在此流程中测试新规则。

## 查看 MQTT 主题和规则 AWS IoT
<a name="iot-repub-rule-mqtt"></a>

在讨论 AWS IoT 规则之前，先了解 MQTT 协议会有所帮助。在物联网解决方案中，MQTT 协议相比于其它网络通信协议（如 HTTP）更具优势，这使得它成为物联网设备使用的常用选择。本部分回顾了 MQTT 的关键方面，因为它们适用于本教程。有关如何将 MQTT 与 HTTP 进行比较的信息，请参阅 [为设备通信选择应用程序协议](protocols.md#protocol-selection)。

**MQTT 协议**  
MQTT 协议使用与其主机的 publish/subscribe 通信模型。为了发送数据，设备会向消息代理发布由主题标识的 AWS IoT 消息。要接收来自消息代理的消息，设备通过在订阅请求中向消息代理发送主题筛选条件，来订阅其将接收的主题。 AWS IoT 规则引擎从消息代理接收 MQTT 消息。

**AWS IoT 规则**  
AWS IoT 规则由规则查询语句和一个或多个规则操作组成。当 AWS IoT 规则引擎接收 MQTT 消息，则这些元素将按如下方式操作消息。
+ 

**规则查询语句**  
规则的查询语句描述了要使用的 MQTT 主题，解释消息有效载荷中的数据，并按类似于常用 SQL 数据库使用的语句的 SQL 语句的描述设置数据的格式。查询语句的结果是发送到规则操作的数据。
+ 

**规则操作**  
规则中的每个规则操作都对规则的查询语句生成的数据起作用。 AWS IoT 支持[许多规则操作](iot-rule-actions.md)。但是，在本教程中，您将专注于 [重新发布](republish-rule-action.md) 规则操作，该操作将查询语句的结果发布为带有特定主题的 MQTT 消息。

## 步骤 1：创建 AWS IoT 规则以重新发布 MQTT 消息
<a name="iot-repub-rule-define"></a>

您将在本教程中创建的 AWS IoT 规则订阅了 `device/device_id/data` MQTT 主题，其中*device\$1id*是发送消息的设备的 ID。这些主题由[主题筛选条件](topics.md#topicfilters)描述为 `device/+/data`，其中，`+` 是匹配两个正斜杠字符之间的任何字符串的通配符。

当规则收到来自匹配主题的消息时，它会重新发布 `device_id` 和 `temperature` 的值，以 `device/data/temp` 主题发布为新的 MQTT 消息。

例如，具有 `device/22/data` 主题的 MQTT 消息有效载荷如下所示：

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

该规则将 `temperature` 值从消息有效载荷中取出，将 `device_id` 从主题中取出，并将其作为 MQTT 消息以 `device/data/temp` 为主题和类似下面这样的消息有效载荷重新发布：

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

使用此规则，只需要设备 ID 和温度数据的设备会订阅 `device/data/temp` 主题以仅接收该信息。

**创建重新发布 MQTT 消息的规则**

1. 打开[AWS IoT 控制台的 “**规则**” 中心](https://console.aws.amazon.com//iot/home#/rulehub)。

1. 在 **Rules**（规则）中，选择 **Create**（创建）并开始创建新规则。

1. 在**创建规则**顶部：

   1. 在 **Name**（名称）下，输入规则的名称。在本教程中，将其命名为 **republish\$1temp**。

      请记住，规则名称在您的账户和区域中必须唯一，并且不能包含任何空格。我们在此名称中使用了下划线字符来分隔规则名称中的两个单词。

   1.  在**说明**中，描述规则。

      有意义的描述可以帮助您记住此规则的作用以及您创建它的原因。描述可以根据需要延长，因此请尽可能详细。

1. 在**创建规则**的**规则查询语句**中：

   1.  在**使用 SQL 版本**中，选择 **2016-03-23**。

   1. 在**规则查询语句**编辑框中，输入语句：

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

      本语句：
      + 侦听主题符合 `device/+/data`主题筛选条件的 MQTT 消息。
      + 从主题字符串中选择第二个元素，并将其分配给 `device_id`字段。
      + 从消息负载中选择 `temperature`字段的值，并将其分配给 `temperature`字段。

1. 在**设置一个或多个操作**中：

   1. 要打开此规则的规则操作列表，请选择**添加操作**。

   1. 在 **“选择操作**” 中，选择 “将**消息重新发布到 AWS IoT 主题**”。

   1. 在操作列表底部，选择 **Configure action**（配置操作）以打开选定操作的配置页面。

1. 在**配置操作**中：

   1.  在 **Topic**（主题）中输入 **device/data/temp**。这是此规则将发布的消息 MQTT 主题。

   1.  在 **Quality of Service**（服务质量）中，选择 **0 - The message is delivered zero or more times**（0-消息传递零次或多次）。

   1.  在**选择或创建角色以授予执行此操作的 AWS IoT 访问权限**中：

      1.  选择**创建角色**。**Create a new role**（创建新角色）对话框打开。

      1. 输入描述新角色的名称。在本教程中，请使用 **republish\$1role**。

         创建新角色时，将创建用于执行规则操作的正确策略并将其附加到新角色。如果更改此规则操作的主题或在其它规则操作中使用此角色，则必须更新该角色的策略以授权新主题或操作。要更新现有角色，请在本部分中选择 **Update role**（更新角色）。

      1. 选择 **Create Role**（创建角色）以创建角色并关闭对话框。

   1. 选择 **Add action**（添加操作）将操作添加到规则并返回到 **Create a rule**（创建规则）页。

1. “将**消息重新发布到 AWS IoT 主题**” 操作现在列在 **“设置一个或多个操作**” 中。

   在新动作的磁贴中，在**将消息重新发布至 AWS IoT 主题**下，您可以看到重新发布操作将发布到的主题。

   这是您将添加到此规则的唯一规则操作。

1. 在 **Create a rule**（创建规则）中，向下滚动到底部，然后选择 **Create rule**（创建规则）以创建规则并完成此步骤。

## 步骤 2：测试您的新规则
<a name="iot-repub-rule-test"></a>

要测试新规则，您将使用 MQTT 客户端发布和订阅此规则所使用的 MQTT 消息。

在新窗口中打开 [AWS IoT 控制台中的 MQTT 客户端](https://console.aws.amazon.com//iot/home#/test)。这将允许您在不丢失 MQTT 客户端配置的情况下编辑规则。如果您让其转到控制台中的其它页面，MQTT 客户端不会保留任何订阅或消息日志。

**如需使用 MQTT 客户端来测试您的规则**

1. 在 [AWS IoT 控制台中的 MQTT 客户端](https://console.aws.amazon.com//iot/home#/test)中，订阅输入主题，在本例中为 `device/+/data`。

   1. 在 MQTT 客户端中，在**订阅**下，选择**订阅主题**。

   1. 在**订阅主题**中，输入输入主题筛选条件的主题，**device/\$1/data**。

   1. 将其它字段保留为默认设置。

   1. 选择**订阅主题**。

      在**订阅**栏，在**发布到主题**项下，将会显示 **device/\$1/data**。

1. 订阅您的规则将发布的主题：`device/data/temp`。

   1. 在 **Subscriptions**（订阅）中，再次选择 **Subscribe to a topic**（订阅主题），并在 **Subscription topic**（订阅主题）中，输入重新发布消息的主题，**device/data/temp**。

   1. 将其它字段保留为默认设置。

   1. 选择 **Subscribe to topic**（订阅主题）。

      在 **Subscriptions**（订阅）栏，在 **device/\$1/data** 下，将会显示 **device/data/temp**。

1. 使用特定设备 ID **device/22/data**向输入主题发布消息。您无法发布到包含通配符的 MQTT 主题。

   1. 在 MQTT 客户端中，在**订阅**下，选择**订阅主题**。

   1. 在**发布**字段中，输入输入主题名称，**device/22/data**。

   1. 复制此处显示的示例数据，然后在主题名称下方的编辑框中粘贴示例数据。

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

   1. 要发送您的 MQTT 消息，请选择**发布到主题**。

1. 查看已发送的消息。

   1. 在 MQTT 客户端中，在 **Subscriptions**（订阅）项下，您之前订阅的两个主题旁边有一个绿点。

      绿色圆点表示自您上次查看它们以来已收到一条或多条新消息。

   1. 在**订阅**下，选择 **device/\$1/data** 来检查消息有效载荷是否与刚刚发布的内容匹配，如下所示：

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

   1. 在 “**订阅**” 下 **device/data/temp**，选择检查重新发布的消息有效负载是否如下所示：

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

      请注意，`device_id` 值是一个带引号的字符串，`temperature` 值为数字。这是因为 [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)函数从输入消息的主题名称中提取字符串，而 `temperature`值使用输入消息负载中的数值。

      如果您想使 `device_id`值为数值，请在规则查询语句中将 `topic(2)`替换为：

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

      请注意，将 `topic(2)`值设置为数字值仅在主题的该部分仅包含数字字符时才起作用。

1. 如果您看到已向该**device/data/temp**主题发布了正确的消息，则说明您的规则起作用了。请在下一部分中了解有关“重新发布规则”操作的更多信息。

   如果您没有看到正确的消息已发布到**设备/\$1/data** 或**device/data/temp**主题，请查看疑难解答提示。

### 重新发布消息规则疑难解答
<a name="iot-repub-rule-trouble"></a>

如果您没有看到期望的结果，可检查以下事项。
+ 

**您收到了一个错误的广告条**  
如果在您发布输入消息时出现错误，请先更正该错误。以下步骤可帮助您更正此错误。
+ 

**您未在 MQTT 客户端中看到输入消息**  
每次将输入消息发布到 `device/22/data`主题时，如果您如流程中所述订阅了 `device/+/data`主题筛选条件，则消息应当会在 MQTT 客户端中显示。

**要检查的事项**
  + 

**检查您订阅的主题筛选条件**  
如果您如流程中所述订阅了输入消息主题，则每次发布输入消息时都应看到该输入消息的副本。

    如果没有看到该消息，请检查您订阅的主题名称，并将其与您发布的主题进行比较。主题名称区分大小写，您订阅的主题必须与发布消息负载的主题相同。
  + 

**检查消息发布函数**  
在 MQTT 客户端中，在**订阅**下，选择 **device/\$1/data**，检查发布消息的主题，然后选择**发布到主题**。您应该会看到来自主题下方编辑框中的消息负载出现在消息列表中。
+ 

**您未在 MQTT 客户端中看到您的重新发布的消息**  
要使规则起作用，规则必须具有授权其接收和重新发布消息的正确策略，并且必须接收消息。

**要检查的事项**
  + 

**检查您 AWS 区域 的 MQTT 客户端和您创建的规则**  
您在其中运行 MQTT 客户端的控制台必须位于您所创建规则的同一 AWS 区域。
  + 

**检查规则查询语句中的输入消息主题**  
要使规则起作用，它必须收到一条消息，消息主题名称应与规则查询语句 FROM 子句中的主题筛选条件相匹配。

    检查规则查询语句中主题筛选条件的拼写与 MQTT 客户端中主题的拼写。主题名称区分大小写，消息的主题必须与规则查询语句中的主题筛选条件匹配。
  + 

**检查输入消息负载的内容**  
要使规则起作用，则必须在 SELECT 语句中声明的消息负载中找到数据字段。

    检查规则查询语句 `temperature`字段中的拼写与 MQTT 客户端中消息负载的拼写。字段名称区分大小写，规则查询语句中 `temperature`字段必须与消息负载中的 `temperature`字段相同。

    确保消息负载中的 JSON 文档格式正确。如果 JSON 有任何错误（例如缺少逗号），则规则将无法读取它。
  + 

**在规则操作中检查重新发布的消息主题**  
重新发布规则操作向其发布新消息的主题必须与您在 MQTT 客户端中订阅的主题匹配。

    在控制台中打开您创建的规则，然后检查规则操作将重新发布消息的主题。
  + 

**检查规则所使用的角色**  
规则操作必须具有接收原始主题和发布新主题的权限。

    授权规则接收消息数据并重新发布的策略特定于所使用的主题。如果更改用于重新发布消息数据的主题，则必须更新规则操作的角色，以更新其策略来匹配当前主题。

    如果怀疑这里出现了问题，请编辑“重新发布”规则操作并创建新角色。规则操作创建的新角色将接收执行这些操作所需的授权。

## 步骤 3：查看结果和后续步骤
<a name="iot-repub-rule-review"></a>

**在本教程中：**
+ 您在规则查询语句中使用了一个简单的 SQL 查询和几个函数来生成新的 MQTT 消息。
+ 您创建了重新发布该新消息的规则。
+ 您使用 MQTT 客户端来测试您的 AWS IoT 规则。

**后续步骤**  
使用此规则重新发布几条消息后，请尝试使用该规则进行实验，以了解更改教程的某些方面如何影响重新发布的消息。以下想法可以帮助您开始操作。
+ *device\$1id*在输入消息的主题中更改并观察重新发布的消息有效负载中的效果。
+ 更改规则查询语句中选定的字段，并观察重新发布的消息有效载荷中的效果。
+ 尝试本系列中的下一个教程，了解如何 [教程：发送 Amazon SNS 通知](iot-sns-rule.md)。

本教程中使用的“重新发布规则”操作也可以帮助您调试规则查询语句。例如，您可以将此操作添加到规则中，以查看其规则查询语句如何设置规则操作所使用的数据的格式。