# 创建规则

本页主要介绍如何在 EMQX Dashboard 中创建数据处理的规则并为规则添加动作。登录 EMQX Dashboard，点击左侧导航目录中的 **集成** -> **规则**。然后点击**创建**按钮，跳转至规则创建页面。在这里，您可以定义规则 SQL 处理并筛选来自消息、事件以及外部数据系统的数据，并为规则添加动作，实现将处理结果通过消息发布、打印到控制台或通过 Sink 进行转发等操作。

本页面的演示以消息重发布动作作为示例，描述了如何创建一个规则，处理接收到的主题为 `t/#` 的消息，并将消息重新发布到主题 `a/1`。

此外，本页还介绍了如何测试规则以及如何查看已创建的规则。

## 输入规则 SQL

在**规则**页面上，输入规则的名称并添加备注以便未来管理。

在 **SQL 编辑器**中，您可以自定义语句以添加适合您业务需求的数据源。对于本教程，请保持默认设置，即选择并返回符合 `t/#` 模式的所有主题下的消息（例如 `t/a`、`t/a/b`、`t/a/b/c`等）。

::: tip

EMQX 内置了丰富的 SQL 语句示例，以帮助您入门。您可以在 **SQL 编辑器**下点击 **SQL 示例**按钮进行探索。有关 SQL 语法和用法的更多详细信息，请参阅 [SQL 语法与示例](./rule-sql-syntax.md)。

:::

<img src="./assets/create-rules.png" alt="create-rules" style="zoom:50%;" />

### SQL 生成器

从 EMQX 5.10.0 开始，SQL 编辑器支持通过 AI 驱动的 SQL 生成器，使用自然语言生成规则 SQL。该功能允许您用自然语言描述预期行为，系统将自动生成相应的 SQL 语句用于规则引擎。

SQL 生成器默认处于启用状态。您可以通过 Dashboard 右上角的**设置**菜单中的开关将其禁用。

要使用该功能，请按照以下步骤操作：

1. 进入**创建规则**页面，找到 **SQL 编辑器**区域。

2. 点击编辑器下方的 **SQL 生成器**按钮，打开**使用 AI 生成 SQL** 对话框。根据以下提示填写字段：

   - **任务描述**（必填）：使用自然语言描述您希望 SQL 实现的逻辑。

     示例：
      *“从 MQTT 消息的元数据中提取 `clientid`，并从 payload 中提取 `device_id` 和 `temperature`。仅匹配来自主题 `sensors/temperature` 且温度大于 30 的消息。”*

   - **相关主题**（可选）：指定要匹配的主题过滤器，如 `sensors/temperature`。

   - **输入示例（JSON）**（可选但推荐）：提供一条 MQTT 消息的 payload 示例，帮助 AI 更好地理解数据结构。
      示例：

     ```json
     {
       "device_id": "sensor001",
       "temperature": 32.5,
       "unit": "C"
     }
     ```

   - **输出示例（JSON）**（可选）：指定期望的输出格式。
      示例：

     ```json
     {
       "clientid": "client_a1b2c3",
       "device_id": "sensor001",
       "temperature": 32.5
     }
     ```

     ::: tip
     提供输入和输出示例可以显著提升 SQL 生成的准确性。
     :::

3. 点击**生成**以预览生成的 SQL。

4. 在预览对话框中，您可以：

   - 查看并手动编辑生成的 SQL；
   - 点击**应用 SQL**，将其插入到 SQL 编辑器中；
   - 或点击**返回表单**，修改任务描述或示例后重新生成。

5. 如果点击**应用 SQL**，生成的 SQL 将自动出现在 **SQL 编辑器**中，您可继续查看和修改。

#### 示例结果

根据上面的任务描述和示例，生成的 SQL 可能如下所示：

```sql
SELECT
  clientid,
  payload.device_id AS device_id,
  payload.temperature AS temperature
FROM
  "sensors/temperature"
WHERE
  payload.temperature > 30
```

该规则从主题 `sensors/temperature` 中提取 `clientid`、`device_id` 和 `temperature` 字段，并只处理温度大于 30 的消息。

#### 使用 SQL 生成器的场景

SQL 生成器特别适用于以下情况：

- 您不熟悉 EMQX SQL 语法；
- 您希望快速原型设计一个规则；
- 您正在处理结构化的 JSON 消息 payload。

如需更多自定义功能和语法说明，请参阅 [SQL 语法与示例](./rule-sql-syntax.md)文档。

### 测试 SQL 语句

您可以使用模拟数据执行 SQL 语句，在添加动作和创建规则之前，验证 SQL 执行结果是否符合预期。这是一个可选步骤，但如果您是首次编写 SQL，建议进行测试。如果您想测试整个规则的执行情况，请使用[测试规则](#测试规则)功能。

测试步骤如下：

1. 开启**启用调试**开关，并将测试目标选择为 **SQL**。

2. 选择与 SQL 匹配的**数据来源**，并确保它与规则中指定的来源（FROM 子句）保持一致。

3. 输入模拟数据：选定数据来源后，EMQX 为所有模拟数据字段提供了默认值，例如**客户端 ID**、**用户名**、**主题**、**QoS**、**Payload** 等，按照需求将其修改为适当的值。

4. 点击**运行测试**按钮即可提交测试，如果一切正常，将显示**测试通过**提示。

<img src="./assets/test-sql.png" alt="test-sql" style="zoom:40%;" />

SQL 处理结果将以 JSON 形式呈现在**输出结果**部分。SQL 处理结果中的所有字段都可以通过后续操作（内置操作或 Sink）以 `${key}` 的形式进行引用。有关字段的详细说明，请参阅 [SQL 数据源和字段](./rule-sql-events-and-fields.md)。

::: tip

本演示假设 Payload 是 JSON 格式。在实际使用中，您也可以使用[编解码](./schema-registry.md)来处理其他格式的消息。

:::

下一步，您可以在**创建规则**页面上，点击页面右侧的**添加动作**按钮，为规则添加多个动作。

## 添加动作

在**创建规则**页面上，点击右侧的**添加动作**按钮，将弹出**添加动作**页面。您可以从**动作类型**下拉列表中选择三种类型的动作之一：消息重新发布、控制台输出和使用数据桥接进行转发。

<img src="./assets/add_action.png" alt="add_action" style="zoom:80%;" />

### 添加消息重发布动作

消息重发布动作用来发布一条新的 MQTT 消息，适用于需要向设备发送下行消息的场景。

本节演示了如何将主题为 `t/#` 的消息重新发布到主题 `a/1`。在**添加动作**页面的**动作类型**下拉菜单中选择`消息重发布`，然后在点击**添加**按钮之前，配置以下设置：

- **主题**：在本示例中设置为目标主题 `a/1`；

- **QoS**：在本示例中设置为重新发布的消息的 QoS 为`0`；

- **Retain**：设置是否将此消息作为保留消息转发，本示例中保持默认设置 `false`；

- **Payload**：输入 `${payload}`，表示重新发布的消息将与原始消息具有相同的 payload，不进行任何修改。

- **MQTT 5.0 消息属性**：点击切换开关以根据需要配置消息属性，允许您为重新发布的消息添加丰富的消息元数据描述。

  <!-- - **用户属性**：您可以添加自定义键值对来配置重新发布消息的[用户属性](https://www.emqx.com/zh/blog/mqtt5-user-properties)，表示自定义消息元数据。 -->

  - **有效载荷指示器**：指示消息格式。值设置为 `false` 时，消息是未确定的字节，设置为 `true` 时，意味着消息体中的有效载荷是 UTF-8 编码的字符数据。这将有助于 MQTT 客户端或 MQTT 服务器可以更加有效的解析消息内容，而不用特意去对于消息体进行格式或类型的判断。
  - **消息过期时间**：输入一个值（以秒为单位）以指定消息应在经过一段时间后过期，并且如果未传递给预期的接收方，则被视为无效。
  - **内容类型**：指定重新发布消息中的载荷内容的类型或格式（MIME 类型），例如，`text/plain` 表示文本文件，`audio/aac` 表示音频文件，而 `application/json` 表示是一条 JSON 格式的应用消息。
  - **响应主题**：输入要将响应消息发布到的特定 MQTT 主题。例如，如果您希望将响应发送到名为"response/my_device"的主题，您应输入：`response/my_device`。
  - **对比数据**：输入一个唯一标识符或数据，以将响应消息与原始请求消息相关联。您可以输入唯一的请求标识符、事务 ID 或在您的应用程序上下文中有意义的任何其他信息。

- **直接派发**：切换此开关以启用或禁用直接派发。启用后，消息将直接发送给订阅者，避免触发额外的规则或导致同一规则的递归激活等意外行为。

在**创建规则**页面，点击底部的**创建**按钮以完成规则创建。此规则将作为新条目添加到**规则**页面。

::: tip 

重新发布操作不会阻止原始消息的传递。例如，根据规则，主题 `t/1`下的消息将重新发布到主题 `a/1`，与此同时，`t/1` 的消息仍然会传递到订阅了主题 `t/1`的客户端。 

:::

### 添加控制台输出动作

::: tip 

控制台输出动作仅用于调试。如果在生产环境中使用，可能会导致性能问题。

:::

控制台输出动作用于查看规则的输出结果，结果将以日志的形式打印到控制台或日志中。

- 当 EMQX 以控制台（`console`）或前台（`foreground`）模式（前台模式是在 Docker 环境中的默认模式）启动时，其输出将被直接发送到控制台。
- 如果通过 systemd 启动 EMQX，输出将被系统日志捕获并存储。这可以通过使用 `journalctl` 命令来查看。

输出格式如下所示：

```bash
[rule action] rule_id1
    Action Data: #{key1 => val1}
    Envs: #{key1 => val1, key2 => val2}
```

其中：

- `[rule action]` 是重新发布操作被触发的规则 ID。
- `Action Data` 是规则的输出结果，表示在执行操作时应传递给动作的数据或参数，即您设置消息重发布动作时的 payload 部分。
- `Envs` 是重新发布时应设置的环境变量，其中可能包含与执行此操作相关的数据源和其他内部信息。

### 添加发送到 Sink 的动作

您可以将规则结果通过 Sink 转发到外部数据系统，如 HTTP 服务器、Kafka 以及各种数据库。有关支持的 Sink 和使用方法，请参阅[数据集成](./data-bridges.md)。

## 测试规则

规则引擎提供了规则测试功能，可以使用模拟数据或真实客户端触发规则，执行规则 SQL 以及规则中添加的所有动作，并获得每个步骤的执行结果。

通过测试规则，可以验证规则是否按预期工作，快速排查并解决存在的问题。这不仅加快了开发速度，还确保了规则在实际运行时能够如期运行，避免在真实环境中出现故障。

### 测试步骤

1. 点击**启用调试**开关，并将测试目标选择为**规则**。注意，开始测试之前需要先保存规则。

2. 点击**开始测试**按钮开始测试，浏览器将等待当前规则触发以生成测试结果。

3. 触发规则进行测试，支持以下 2 种方式：
    - **模拟数据**：点击**输入模拟数据**按钮，在弹出的窗口中选择与 SQL 匹配的**数据来源**，并确保它与规则中指定的来源（FROM 子句）保持一致。
      
      EMQX 为所有字段提供了默认值，例如**客户端 ID**、**用户名**、**主题**、**QoS**、**Payload** 等。可以修改为需要的值，点击**提交测试**按钮即可触发一次规则进行测试。
      
    - **真实设备**：保持当前页面打开，使用真实客户端或 MQTT 客户端工具连接到 EMQX，触发对应的事件，进行测试。
    
4. 查看测试结果：当规则被触发时，会将执行结果输出到 Dashboard 上，详细展示每个步骤的执行结果。

### 测试示例

以 [MQTTX](https://mqttx.app/zh/docs/get-started) 为例，创建一个客户端，然后使用此客户端订阅主题 `a/1` 并发送一条 `t/1` 的消息。

您将在对话框中看到此消息也被重新发布到主题 `a/1`：

<img src="./assets/mqttx-test-rule.png" alt="mqttx-test-rule" style="zoom:40%;" />

相应的，Dashboard 测试界面上将显示整个规则的执行结果，显示内容如下：

- 左侧为规则执行记录，每次规则触发会产生一条记录，点击可以切换到对应的消息或事件详情。
- 右侧为选中规则记录下的动作列表，点击可以展开查看动作执行结果和日志。

当规则 SQL 或任意动作执行失败时，整个规则记录将标记为失败状态，可以选中记录查看对应动作的错误信息进行排查。

<img src="./assets/rule-test-result.png" alt="EMQX 规则测试" style="zoom:40%;" />

从上图可以看到，规则被触发了 4 次，其中 3 次规则执行完全成功，第 4 次由于 **HTTP 服务**动作执行失败，错误原因是响应了 302 状态码。

## 查看规则

**规则**页面提供了一个完整的列表，显示了您创建的所有规则。

列表中的每个条目都会显示基本信息，包括规则 ID、关联的 Source、启用状态和动作数量。将鼠标悬停在 Source 上可查看对应的 SQL 语句详情。要修改规则的配置，请在**操作**列中点击**设置**。您还可以使用**更多**按钮来复制或删除规则。

![view_rules](./assets/view_rules.png)

您可以在**规则**列表页上点击规则 ID，以查看规则与动作的执行统计信息。

注：如果更新规则，则下面页面中列出的统计指标将重置。

您还可以通过导航到**集成** -> **Flow 设计器**，在 [Flow 设计器](../flow-designer/introduction.md)中查看规则。通过**规则**页面创建的规则与通过 Flow 设计器创建的规则是完全互通的。

要查看规则的统计指标和动作执行次数等信息，您可以在**规则**页面上点击规则 ID 或在 **Flows** 页面点击规则名称。

![view_rules_flows](./assets/view_rules_flows.png)

::: tip 提示

如果您更新了规则动作或重新定义了数据源，页面上列出的统计信息将重置并刷新。

:::

<img src="./assets/rule-statistics.png" alt="rule-statistics" style="zoom:50%;" />

### 搜索规则

当规则列表中有许多规则时，您可以使用过滤器来缩小搜索范围，显示您想要查看的规则。您可以通过规则 ID、传入消息的主题或通配符、启用状态、规则备注以及与规则关联的动作或 Source 来过滤规则。

![search_rules](./assets/search_rules.png)

### 查看动作 (Sink) 和 Source

**规则**页面上的**动作** **(Sink)** 和 **Sources** 标签页显示了所有创建的动作 (Sink) 和 Source。您可以查看基本信息，如名称、连接状态、关联的规则、启用状态以及创建和更新的时间等。通过点击列标题旁的箭头您可以对条目进行排序。

在**是否启用** 列中，点击切换开关可以启用或停用某个 sink 或 source。点击**关联规则**列下的**查看规则**将跳转到包含该 sink 或 source 的规则列表，帮助您更轻松地管理数据集成设置。

您可以通过**操作**列重新连接或修改 sink 或 Source 的设置。点击**更多**，您可以删除该 sink 或 source，或者使用它创建新规则。

当 sink 和 source 列表中有许多条目时，您可以使用过滤器来缩小搜索范围，显示您想要查看的条目。您可以通过名称、状态以及启用状态来过滤 sink 和 source。

![view_sink_source](./assets/view_sink_source.png)

要查看动作 (Sink) 或 Source 的统计指标等信息，您可以在页面上点击 sink 或 source 的名称。

![action_statistics](./assets/action_statistics.png)
