

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

# 支持 MQTT 的边缘版 V3 网关 AWS IoT SiteWise
<a name="mqtt-enabled-v3-gateway"></a>

AWS IoT SiteWise 可以使用支持 MQTT 的 V3 网关，这代表了 SiteWise Edge 网关架构的重大进步。这种网关类型利用 MQTT（消息队列遥测传输）协议进行数据通信，为工业物联网部署提供了更高的灵活性和效率。

支持 MQTT 的 V3 网关使用 MQTT 进行数据传输，从而实现了轻量级的发布-订阅网络协议，可在设备和云之间高效传输消息。您可以设置各种数据目标，包括直接将实时数据摄入 AWS IoT SiteWise 和使用 Amazon S3 进行缓冲数据摄取。要实现精确的数据收集，您可以实现路径过滤器来订阅特定的 MQTT 主题。

支持 MQTT 的 V3 网关带有预先配置的实时目的地，过滤器设置为 “\$1”（所有主题），您可以根据需要对其进行自定义或删除。为了简化数据管理，每个网关中只能存在一个实时目的地。

支持 MQTT 的架构与经典流 V2 网关有很大不同。虽然 V2 使用基于流的方法，但 V3 采用 MQTT，提供了更多可配置的数据目的地和筛选选项。但是，请注意，V3 不支持数据处理包，该包在 V2 中可用。

支持 MQTT 的 V3 网关具有以下优点：
+ 由于 MQTT 的轻量级特性，提高了可扩展性，可以更好地处理大量设备和高频数据传输。
+ 通过路径筛选器增强数据控制，实现对数据收集的精细管理，减少不必要的数据传输和处理。
+ 灵活的数据处理，允许根据特定需求在实时处理和缓冲存储之间进行配置。
+ 与现代物联网通信标准保持一致，为未来的增强和集成奠定基础。

考虑采用支持 MQTT 的 V3 网关进行新部署，尤其是在您需要灵活的数据摄取选项和精确控制数据收集时。

**注意**  
对于需要数据处理包（Classic Streams）的现有部署或场景，V2 网关仍然是一个可行的选择。

通过提供这两种网关类型，无论您优先考虑高级 MQTT 功能还是与现有系统的兼容性，都可以 AWS IoT SiteWise 确保您可以选择最适合您的特定工业物联网需求的解决方案。

## 目的地和路径过滤器
<a name="create-destination-summary"></a>

查看以下主题，详细了解启用 MQTT 的网关中的目的地和路径过滤器：
+ [了解 AWS IoT SiteWise 边缘目的地](gw-destinations.md#source-destination)
+ [添加 AWS IoT SiteWise Edge 实时目的地](destinations-real-time.md)
+ [使用 Amazon S3 添加 AWS IoT SiteWise 缓冲目的地](destinations-buffered.md)
+ [了解 AWS IoT SiteWise Edge 目标的路径过滤器了解路径筛选条件](gw-destinations.md#destinations-path-filters)
+ [向 AWS IoT SiteWise Edge 目标添加路径过滤器](destinations-add-path-filters.md)
+ [管理 AWS IoT SiteWise 边缘目的地](destinations-manage.md)

# 将外部应用程序连接到 EMQX 代理
<a name="connect-external-applications-emqx"></a>

本指南介绍如何通过已部署的支持 MQTT 的 V AWS IoT SiteWise 3 网关上的 EMQX 代理将外部应用程序连接到 Edge 网关。外部应用程序可能包括自定义监控工具、第三方可视化软件或需要在边缘与工业数据交互的传统系统。

我们将介绍 Linux 和Microsoft Windows环境的配置步骤，包括 EMQX 部署配置、用于安全连接的 TLS 设置以及用于控制对特定主题的访问的授权规则。

**注意**  
EMQX 不是 Edge 的供应商或供应商。 AWS IoT SiteWise 

**重要**  
为了保护与网关的连接，我们强烈建议通过 AWS IoT Greengrass 客户端设备身份验证功能使用基于证书的身份验证。此方法通过双向 TLS (mTLS) 身份验证提供强大的安全性。有关更多信息，请参阅《*AWS IoT Greengrass Version 2 开发者指南》*中的 [Connect 客户端设备与核心设备](https://docs.aws.amazon.com/greengrass/v2/developerguide/connect-client-devices.html)。

如果您无法使用基于证书的身份验证，请按照本指南使用用户名和密码设置身份验证。

## 先决条件
<a name="emqx-broker-prerequisites"></a>
+ 支持 SiteWise Edge MQTT 的 V3 网关，该网关已部署并处于联机状态
+ 访问网关主机
+ 访问 AWS IoT SiteWise 和 AWS IoT Greengrass 控制台

**Topics**
+ [先决条件](#emqx-broker-prerequisites)
+ [Edge 上的 EMQX 代理的消息有效载荷格式 AWS IoT SiteWise](connect-broker-payload-format.md)
+ [配置 EMQX 代理](configure-emqx-broker.md)
+ [将应用程序连接到 Edge 上的 EMQX 代理 AWS IoT SiteWise](connect-app-to-broker.md)
+ [在 EMQX 中为 AWS IoT SiteWise Edge 设置授权规则](authorization-rules-emqx-broker.md)

# Edge 上的 EMQX 代理的消息有效载荷格式 AWS IoT SiteWise
<a name="connect-broker-payload-format"></a>

要让 IoT SiteWise 发布者组件使用来自外部应用程序的数据并将其发布到 AWS IoT SiteWise 云端，发送到代理的有效负载必须满足特定要求。

了解有效载荷格式是成功与 AWS IoT SiteWise Edge 进行 MQTT 通信的关键。虽然连接设置过程将在后面的章节中介绍，但我们将首先介绍有效负载要求，以帮助您规划实施。

## MQTT 主题要求
<a name="connect-broker-mqtt-requirements"></a>

对 MQTT 主题结构没有限制，包括使用的关卡数量或字符数。但是，我们建议主题与有效载荷中的`propertyAlias`字段相匹配。

**Example 属性别名示例**  
如果 MQTT 主题是`site1/line1/compressor1/temperature`，请确保`propertyAlias`匹配。  

```
{
  "assetId": "compressor_asset_01",
  "propertyAlias": "site1/line1/compressor1/temperature",
  "propertyId": "temperature_sensor_01",
  "propertyValues": [
    {
      "quality": "GOOD",
      "timestamp": {
        "offsetInNanos": 0,
        "timeInSeconds": 1683000000
      },
      "value": {
        "doubleValue": 23.5
      }
    }
  ]
}
```

## JSON 负载结构
<a name="connect-broker-json-payload"></a>

MQTT 消息负载以 JSON 编写，并遵循 [AWS IoT SiteWise API 参考](https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/API_PutAssetPropertyValueEntry.html)中定义的`PutAssetPropertyValueEntry`消息格式。

```
{
   "assetId": "string",
   "propertyAlias": "string",
   "propertyId": "string",
   "propertyValues": [
      {
         "quality": "string",
         "timestamp": {
            "offsetInNanos": number,
            "timeInSeconds": number
         },
         "value": {
            "booleanValue": boolean,
            "doubleValue": number,
            "integerValue": number,
            "stringValue": "string"
         }
      }
   ]
}
```

**注意**  
要使消息被视为有效，只能满足以下条件之一：  
`propertyAlias`已设置，或者
`assetId`和`propertyId`都设置好了
`PutAssetPropertyValueEntry`有一个在此上下文中不是必填的`entryId`字段。

# 配置 EMQX 代理
<a name="configure-emqx-broker"></a>

本节介绍如何添加用户名和密码。它还介绍了如何使用添加的用户名和密码从外部来源建立 TLS 连接。您可以使用 Linux 来配置 EMQX 代理，也可以使用。Microsoft Windows

**注意**  
要配置代理，您需要在支持 MQTT 的 V3 网关中使用默认 EMQX 配置设置的核心设备。

**重要**  
完成此过程后，我们强烈建议您配置授权规则。有关更多信息，请参阅 [在 EMQX 中为 AWS IoT SiteWise Edge 设置授权规则](authorization-rules-emqx-broker.md)。针对已添加用户的授权规则可增强安全性。

## 更新 EMQX 部署配置以进行身份验证
<a name="update-emqx-broker-authentication"></a>

**更新 EMQX 部署配置以进行身份验证**

1. <a name="sitewise-open-console"></a>导航至 [AWS IoT SiteWise 控制台](https://console.aws.amazon.com/iotsitewise/)。

1. 在左侧导航栏中，选择 **Edge 部分的 **Edge** 网关**。

1. 选择要配置的网关。

1. 在 **Edge 网关配置**部分，复制您的 **Greengrass 核心设备值**。将其保存以备后用。

1. 打开 [AWS IoT 控制台](https://console.aws.amazon.com/iot/)。

1. **在左侧导航栏的 “**管理**” 部分下，选择 **Greengrass** 设备，然后选择 “部署”。**

1. 找到您之前保存的核心设备值，然后选择该链接以打开部署。

1. 选择 “**操作**” 下拉按钮，然后选择 “**修改**”。

1. 阅读显示的消息，然后选择**修订部署**。将出现 **“指定目标**” 页面。

1. 选择 “**下一步**”，直到进入 “**配置组件**” 步骤。

1. 选择 `aws.greengrass.clientdevices.mqtt.EMQX` 单选按钮。

1. 选择 “**配置组件**” 按钮。此时将显示该组件的配置页面。

1. 在 “**配置更新**” 下，选择 “**重置为组件版本的默认配置：2.\$1”。 **\$1。

1. 根据您的操作系统，在 “**要合并的配置**” 部分中输入以下配置。

------
#### [ Linux ]

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "allow"
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               },
               "ssl": {
                   "default": {
                       "enabled": true,
                       "enable_authn": true,
                       "ssl_options": {
                           "verify": "verify_none",
                           "fail_if_no_peer_cert": false
                       }
                   }
               }
           },
           "authentication": {
               "enable": true,
               "backend": "built_in_database",
               "mechanism": "password_based",
               "password_hash_algorithm": {
                   "iterations": 210000,
                   "mac_fun": "sha512",
                   "name": "pbkdf2"
               },
               "user_id_type": "username"
           },
           "dashboard": {
               "listeners": {
                   "http": {
                       "bind": 18083
                   }
               }
           }
       },
       "authMode": "bypass",
       "dockerOptions": "-p 8883:8883 -p 127.0.0.1:1883:1883 -p 127.0.0.1:18083:18083 -v emqx-data:/opt/emqx/data -e EMQX_NODE__NAME=emqx@local",
       "requiresPrivilege": "true"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "allow"
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               },
               "ssl": {
                   "default": {
                       "enabled": true,
                       "enable_authn": true,
                       "ssl_options": {
                           "verify": "verify_none",
                           "fail_if_no_peer_cert": false
                       }
                   }
               }
           },
           "authentication": {
               "enable": true,
               "backend": "built_in_database",
               "mechanism": "password_based",
               "password_hash_algorithm": {
                   "iterations": 210000,
                   "mac_fun": "sha512",
                   "name": "pbkdf2"
               },
               "user_id_type": "username"
           },
           "dashboard": {
               "listeners": {
                   "http": {
                       "bind": 18083
                   }
               }
           }
       },
       "authMode": "bypass",
       "requiresPrivilege": "true"
   }
   ```

   该`dockerOptions`字段仅适用于 Linux 网关。

------

1. 选择**确认**。

1. 选择 “**下一**步”，直到进入 “**查看**” 步骤。

1. 选择**部署**。

1. 部署成功后，继续下一步。

## 启用用户名和密码认证
<a name="emqx-broker-username-password-auth"></a>

本节介绍如何通过 EMQX 控制面板 GUI 添加用户名和密码。

**注意**  
所提供的 EMQX 相关说明仅供参考。由于 EMQX 的文档和功能可能会随着时间的推移而发生变化，并且我们不保留其文档，因此我们建议您查阅 [EMQX 的官方文档](https://docs.emqx.com/en/emqx/latest/)以获取最新信息。

------
#### [ EMQX Dashboard ]

**通过 EMQX 控制面板启用用户名和密码身份验证**

1. 确保您在网关主机内。

1. 打开浏览器窗口并访问[http://localhost:18083/](http://localhost:18083/)。

1. 输入的默认用户名**admin**和默认的密码**public**。*有关更多信息，请参阅 [EMQX 文档中的 EMQX 控制面板](https://docs.emqx.com/en/emqx/latest/dashboard/introduction.html#first-login)。*

1. 登录后，系统会提示您更改密码。更新您的密码以继续进入 EMQX 控制面板。

1. 在左侧导航栏中，选择盾牌图标，然后选择**身份验证**。

1. 在 “**内置数据库**” 行中，选择 “**用户**” 按钮。

1. 选择加号图标按钮以添加用户。**将出现 “添加**” 屏幕。

1. 输入外部应用程序用户的用户名和密码。

1. 选择**保存**。您选择的用户名将显示在 “**身份验证**” 页面的表格中。

**注意**  
现有或默认的授权规则适用于新用户。建议根据您的外部应用程序需求对其进行审查和调整。

------
#### [ EMQX Management with Linux ]

使用 AWS IoT SiteWise EMQX CLI 工具，网址为。`/greengrass/v2/bin/swe-emqx-cli`

**使用 Linux 通过 EMQX 管理启用用户名和密码认证**

1. 通过运行以下命令更改管理员密码：

   ```
   /greengrass/v2/bin/swe-emqx-cli admin change-pwd
   ```

1. 出现提示时，请执行以下操作：

   1. 输入您当前的管理员用户（默认为`admin`）和密码（默认为`public`）。

   1. 输入并确认您的新密码。

   如果成功，您将看到以下消息：

   ```
   admin password changed successfully
   ```

1. 通过运行以下命令为外部应用程序添加用户：

   ```
   /greengrass/v2/bin/swe-emqx-cli users add
   ```

1. 出现提示时，请执行以下操作：

   1. 输入新用户的用户名。

   1. 输入并确认新用户的密码。

   如果成功，您将看到以下消息：

   ```
   User '[username]' created successfully
   ```

1. 通过运行以下命令来验证用户配置：

   ```
   /greengrass/v2/bin/swe-emqx-cli users list
   ```

   输出显示所有已配置的用户：

   ```
   Users:
   - [your-added-username]
   
   Total users: 1
   ```

------
#### [ EMQX Management with Windows ]

在以下位置之一使用 AWS IoT SiteWise EMQX CLI 工具：
+ PowerShell: `C:\greengrass\v2\bin\swe-emqx-cli.ps1`
+ 命令提示符：`C:\greengrass\v2\bin\swe-emqx-cli.bat`

**使用 Windows 通过 EMQX 管理功能启用用户名和密码身份验证**

1. 通过运行以下命令更改管理员密码：

   ```
   C:\greengrass\v2\bin\swe-emqx-cli.ps1 admin change-pwd
   ```

1. 出现提示时，请执行以下操作：

   1. 输入您当前的管理员用户（默认为`admin`）和密码（默认为`public`）。

   1. 输入并确认您的新密码。

   如果成功，您将看到以下消息：

   ```
   admin password changed successfully
   ```

1. 通过运行以下命令为外部应用程序添加用户：

   ```
   C:\greengrass\v2\bin\swe-emqx-cli.ps1 users add
   ```

1. 出现提示时，请执行以下操作：

   1. 输入新用户的用户名。

   1. 输入并确认新用户的密码。

   如果成功，您将看到以下消息：

   ```
   User '[username]' created successfully
   ```

1. 通过运行以下命令来验证用户配置：

   ```
   C:\greengrass\v2\bin\swe-emqx-cli.ps1 users list
   ```

   输出显示所有已配置的用户：

   ```
   Users:
   - [your-added-username]
   
   Total users: 1
   ```

------

# 将应用程序连接到 Edge 上的 EMQX 代理 AWS IoT SiteWise
<a name="connect-app-to-broker"></a>

EMQX 代理在端口 8883 上使用传输层安全 (TLS) 来加密所有通信，确保您的数据在传输过程中受到保护。本节将引导您完成在应用程序和 EMQX 代理之间建立连接的步骤。遵循这些步骤有助于维护工业数据的完整性和机密性。连接过程包括两种主要方法：通过组件使用自动 IP 发现，或者在 TLS 证书中手动将 DNS 名称和 IP 地址配置为主题备用名称 (SANs)。每种方法都有其自身的优势，具体取决于您的网络设置和安全要求。本文档将指导您完成这两个选项。

**Topics**
+ [配置 TLS 以实现与 Edge 上的 EMQX 代理的安全连接 AWS IoT SiteWise](#configure-tls-emqx-broker)
+ [在 Edge 上测试 EMQX 代理连接 AWS IoT SiteWise](#test-emqx-connection)
+ [使用你自己的 CA](#configure-tls-custom-ca)
+ [为外部防火墙连接打开 8883 端口](#emqx-firewall)

## 配置 TLS 以实现与 Edge 上的 EMQX 代理的安全连接 AWS IoT SiteWise
<a name="configure-tls-emqx-broker"></a>

默认情况下，为 EMQX 代理 AWS IoT Greengrass 生成由核心设备证书颁发机构 (CA) 签名的 TLS 服务器证书。有关更多信息，请参阅使用 [MQTT 代理将客户端设备连接到 AWS IoT Greengrass 核心设备](https://docs.aws.amazon.com/greengrass/v2/developerguide/connecting-to-mqtt.html)。

### 检索 TLS 证书
<a name="configure-tls-retrieve-certificate"></a>

要获取 CA 证书，请在网关主机上运行以下命令：

------
#### [ Linux ]

在网关主机上的 shell 会话中运行以下命令：

```
/greengrass/v2/bin/swe-emqx-cli cert
```

此命令显示证书位置并打印证书的内容。

您也可以使用以下命令将证书保存到文件中：

```
/greengrass/v2/bin/swe-emqx-cli cert --output /path/to/certificate.pem
```

------
#### [ Windows ]

在网关主机的 PowerShell 会话中运行以下命令：

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 cert
```

此命令显示证书位置并打印证书的内容。

您也可以使用以下命令将证书保存到文件中：

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 cert --output C:\path\to\certificate.pem
```

无论您的系统上的确切路径如何，CLI 都会自动找到证书。

------

将 ca.pem 文件的内容复制到要连接到代理的外部应用程序中。将其保存为 `BrokerCoreDeviceCA.pem`。

### 向 TLS 服务器证书添加自定义 DNS names/IP 地址
<a name="configure-tls-custom-dns-ip"></a>

由生成的证书上的主题备用名称 (SAN) AWS IoT Greengrass 是`localhost`。从网关主机外部建立 TLS 连接时，TLS 验证步骤会失败，因为代理的主机名与服务器证书`localhost`上的主机名不匹配。

为了解决主机名不匹配的问题， AWS IoT Greengrass 提供了两种管理核心设备端点的方法。本节涵盖这两个选项。有关更多详细信息，请参阅《*AWS IoT Greengrass Version 2 开发人员指南》*中的[管理核心设备端点](https://docs.aws.amazon.com/greengrass/v2/developerguide/manage-core-device-endpoints.html)。
+ 要使用核心设备的 IP 地址连接到 EMQX 代理，请使用自动 IP 发现部分。
+ 要使用 DNS 名称而不是 IP 地址连接到 EMQX 代理，请使用手动管理部分。

------
#### [ Automated IP discovery ]

此选项允许您的核心设备自动发现其 IP 地址，并将其作为主题备用名称 (SAN) 添加到代理证书中。

1. 将该`aws.greengrass.clientdevices.IPDetector`组件添加到核心设备的部署中。

1. 将更改部署到您的设备

1. 等待部署完成。

   部署完成后，您可以使用代理的 IP 地址建立安全的 TLS 连接。

   IP 地址将作为 SAN 自动添加到代理证书中。

------
#### [ Manual DNS and IP Configuration ]

您可以手动将 DNS 名称和 IP 地址作为主题备用名称 (SANs) 添加到您的 TLS 证书。当您为网关主机配置了 DNS 名称时，此方法很有用。

**重要**  
如果您正在使用该 IPDetector 组件，请在继续操作之前将其从部署中删除。该 IPDetector组件会覆盖手动端点配置。

**手动配置终端节点**

1. <a name="sitewise-open-console"></a>导航至 [AWS IoT SiteWise 控制台](https://console.aws.amazon.com/iotsitewise/)。

1. 在左侧导航栏中，选择 **Edge 部分的 **Edge** 网关**。

1. 选择要配置的网关。

1. 在 **Edge 网关配置**部分，选择您的 **Greengrass 核心设备**网址。将显示核心设备的页面。

1. 选择 “**客户端设备**” 选项卡。

1. 选择**管理端点**。

1. 在 “管理终端节点” 对话框中，输入 DNS 名称和要添加的任何 IP 地址 SANs。使用端口 8883。

1. 选择**更新**。

代理的 TLS 服务器证书会自动更新以包含您的新端点。

**使用 Linux 验证 TLS 服务器证书更新**

1. 在您的网关主机上启动 shell 会话。

   ```
   docker exec emqx openssl x509 -in ./data/cert.pem -text -noout | grep -A1 "Subject Alternative Name"
   ```

1. 该命令返回的输出类似于以下内容：

   ```
   X509v3 Subject Alternative Name: 
   DNS:endpoint_you_added, DNS:localhost
   ```

1. 验证您的终端节点是否出现在列表中 SANs。

**使用 Windows 验证 TLS 服务器证书更新**

1. 在您的网关主机上启动 shell 会话。

   ```
   (Get-PfxCertificate -FilePath "C:\greengrass\v2\work\aws.greengrass.clientdevices.mqtt.EMQX\v2\data\cert.pem").Extensions | Where-Object { $_.Oid.FriendlyName -eq "Subject Alternative Name" } | ForEach-Object { "Subject Alternative Name:", ($_.Format($true) -split "`n")[0..1] }
   ```

1. 该命令返回的输出类似于以下内容：

   ```
   Subject Alternative Name:
   DNS Name=your-endpoint
   DNS Name=localhost
   ```

1. 验证您添加的终端节点是否在列表中 SANs。

------

## 在 Edge 上测试 EMQX 代理连接 AWS IoT SiteWise
<a name="test-emqx-connection"></a>

使用 TLS 证书和身份验证凭证配置 EMQX 代理后，请务必验证您的设置是否正常运行。测试连接有助于确保您的安全配置得到正确实施，并且客户端可以成功地与代理建立加密连接。本节演示如何使用 Mosquitto 命令行接口 (CLI) 客户端（一种广泛使用的支持 TLS 加密和身份验证的 MQTT 客户端工具）测试您的代理连接。

### 使用 Mosqitto CLI 客户端测试 EMQX 代理连接
<a name="test-emqx-connection-mosquitto"></a>

在此步骤中，我们将使用 mosquitto CLI 客户端来测试我们的设置，并确保我们可以使用之前创建的用户名和密码成功连接到代理。要获取`BrokerCoreDeviceCA.pem`步骤 3：设置 TLS 下的以下步骤。

```
mosquitto_sub -h hostname|ip address \
    -p 8883 \
    -t "#" \
    -q 1 \
    -u username -P password \
    --cafile BrokerCoreDeviceCA.pem
```

**注意**  
如果您要连接 hostname/IP 的地址与您传递给客户端的 CA 证书上的主题备用名称 (SAN) 不匹配，则可能会出现 SSL: Verify 错误。有关如何使用正确的 SAN 获取证书，请参阅步骤 3：设置 TLS 下的 “向 TLS 服务器证书添加自定义 DNS names/IP 地址”。

此时，所有用户都可以发布和订阅经纪商上的所有主题。继续执行[在 EMQX 中为 AWS IoT SiteWise Edge 设置授权规则](authorization-rules-emqx-broker.md)。

## 使用你自己的 CA
<a name="configure-tls-custom-ca"></a>

AWS IoT Greengrass 概述了如何将自己的客户端设备身份验证组件配置为使用自己的证书颁发机构 (CA)。客户端设备身份验证组件（`aws.greengrass.clientdevices.Auth`）对客户端设备进行身份验证并授权客户端设备操作。有关更多信息，请参阅《*AWS IoT Greengrass Version 2 开发人员指南》*中的[使用自己的证书颁发机构](https://docs.aws.amazon.com/greengrass/v2/developerguide/connecting-to-mqtt.html#use-your-own-CA)。

要使用自己的 CA，请将该`aws.greengrass.clientdevices.Auth`组件添加到您的部署中，以便您可以指定自定义配置。

## 为外部防火墙连接打开 8883 端口
<a name="emqx-firewall"></a>

------
#### [ Linux ]

在 Linux 主机防火墙规则中，为端口 8883 添加入站规则，以允许来自网关主机外部的传入连接。如果有任何防火墙，请确保允许端口 8883 上的传入 TLS 连接。

------
#### [ Windows ]

在您的Microsoft Windows主机防火墙规则中，为端口 8883 添加入站规则，以允许来自网关主机外部的传入连接。确保该规则是允许规则，类型为端口，指定端口 8883。您可以根据自己的网络配置进行配置，以允许从外部应用程序连接到代理。

------

# 在 EMQX 中为 AWS IoT SiteWise Edge 设置授权规则
<a name="authorization-rules-emqx-broker"></a>

EMQX 支持根据用户名、IP 地址或客户端 ID 等标识符添加授权规则。如果您想限制连接到各种操作或主题的外部应用程序的数量，这很有用。

**Topics**
+ [在 Linux 中使用内置数据库配置授权](add-auth-rules-database-emqx-broker-linux.md)
+ [在 Windows 中使用内置数据库配置授权](add-auth-rules-database-emqx-broker-windows.md)
+ [更新 EMQX 部署配置以进行授权](update-emqx-broker-authorization.md)
+ [通过 EMQX 控制面板为用户添加授权规则](add-rules-emqx-broker.md)

# 在 Linux 中使用内置数据库配置授权
<a name="add-auth-rules-database-emqx-broker-linux"></a>

配置授权规则时，有两种配置选项取决于您的部署设置。
+ **Docker**— 如果您在没有的情况下运行标准Docker安装Litmus Edge，请使用 **Docker 网桥网关**配置。当你只部署了 AWS IoT SiteWise 组件时，通常会出现这种情况。
+ **Litmus Edge**— 如果您已在网关上Litmus Edge安装，请使用**Litmus Edge网络子网**配置。

**注意**  
如果您最初配置网Docker桥网关，然后再进行安装Litmus Edge，请使用Litmus Edge网络子网选项重新配置授权规则，以确保所有组件之间的通信正常。

**添加基本授权规则**

1. 验证 EMQX 代理是否已部署并正在运行。

1. 在您的网关主机上启动 shell 会话。

------
#### [ Docker without Litmus Edge ]

   对于不带标准Docker安装Litmus Edge，请运行：

   ```
   /greengrass/v2/bin/swe-emqx-cli acl init
   ```

------
#### [ Litmus Edge network subnet ]

   如果你使用的是Litmus Edge，请确定 Litmus Edge 网络子网 IP：

   ```
   docker network inspect LitmusNetwork | grep IPAM -A9
   ```

   记下输出中的子网值并运行以下命令。`litmus_subnet_ip`替换为上一步中的子网值。

   ```
   /greengrass/v2/bin/swe-emqx-cli acl init litmus_subnet_ip
   ```

------

   该工具会自动创建并应用授权规则，以允许从提供的 IP 地址连接到代理。它允许访问所有主题。这包括物联网 SiteWise OPC UA 收集器和物联网 SiteWise 发布者。

1. 继续执行[更新 EMQX 部署配置以进行授权](update-emqx-broker-authorization.md)。

# 在 Windows 中使用内置数据库配置授权
<a name="add-auth-rules-database-emqx-broker-windows"></a>

本节介绍如何使用内置数据库为 Windows 部署配置授权规则。

**添加基本授权规则**

1. 验证 EMQX 代理是否已部署并正在运行。

1. 运行 AWS IoT SiteWise EMQX CLI 工具：

   ```
   C:\greengrass\v2\bin\swe-emqx-cli.ps1 acl init
   ```

   该工具会自动创建并应用 ACL 规则，允许从本地主机 (127.0.0.1) 连接到代理。它允许访问所有主题。这包括物联网 SiteWise OPC UA 收集器和物联网 SiteWise 发布者。

1. 继续执行[更新 EMQX 部署配置以进行授权](update-emqx-broker-authorization.md)。

# 更新 EMQX 部署配置以进行授权
<a name="update-emqx-broker-authorization"></a>

**更新 EMQX 部署配置以进行授权**

1. <a name="sitewise-open-console"></a>导航至 [AWS IoT SiteWise 控制台](https://console.aws.amazon.com/iotsitewise/)。

1. 在左侧导航栏中，选择 **Edge 部分的 **Edge** 网关**。

1. 选择要配置的网关。

1. 在 **Edge 网关配置**部分，复制您的 **Greengrass 核心设备值**。将其保存以备后用。

1. 打开 [AWS IoT 控制台](https://console.aws.amazon.com/iot/)。

1. **在左侧导航栏的 “**管理**” 部分下，选择 **Greengrass** 设备，然后选择 “部署”。**

1. 找到您之前保存的核心设备值，然后选择该链接以打开部署。

1. 选择 “**操作**” 下拉按钮，然后选择 “**修改**”。

1. 阅读显示的消息，然后选择**修订部署**。将出现 **“指定目标**” 页面。

1. 选择 “**下一步**”，直到进入 “**配置组件**” 步骤。

1. 选择 `aws.greengrass.clientdevices.mqtt.EMQX` 单选按钮。

1. 选择 “**配置组件**” 按钮。此时将显示该组件的配置页面。

1. 在 “**配置更新**” 下，选择 “**重置为组件版本的默认配置：2.\$1”。 **\$1。

1. 根据您的操作系统将以下内容粘贴**到要合并的配置**部分。

------
#### [ Linux ]

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "deny",
               "sources": [
                   {
                       "type": "built_in_database"
                   },
                   {
                       "type": "file",
                       "path": "data/authz/acl.conf"
                   }
               ]
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               },
               "ssl": {
                   "default": {
                       "enabled": true,
                       "enable_authn": true,
                       "ssl_options": {
                           "verify": "verify_none",
                           "fail_if_no_peer_cert": false
                       }
                   }
               }
           },
           "authentication": {
               "enable": true,
               "backend": "built_in_database",
               "mechanism": "password_based",
               "password_hash_algorithm": {
                   "iterations": 210000,
                   "mac_fun": "sha512",
                   "name": "pbkdf2"
               },
               "user_id_type": "username"
           },
           "dashboard": {
               "listeners": {
                   "http": {
                       "bind": 18083
                   }
               }
           }
       },
       "authMode": "bypass",
       "dockerOptions": "-p 8883:8883 -p 127.0.0.1:1883:1883 -p 127.0.0.1:18083:18083 -v emqx-data:/opt/emqx/data -e EMQX_NODE__NAME=emqx@local",
       "requiresPrivilege": "true"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "deny",
               "sources": [
                   {
                       "type": "built_in_database"
                   },
                   {
                       "type": "file",
                       "path": "C:\\greengrass\\v2\\work\\aws.greengrass.clientdevices.mqtt.EMQX\\v2\\data\\authz\\acl.conf"
                   }
               ]
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               },
               "ssl": {
                   "default": {
                       "enabled": true,
                       "enable_authn": true,
                       "ssl_options": {
                           "verify": "verify_none",
                           "fail_if_no_peer_cert": false
                       }
                   }
               }
           },
           "authentication": {
               "enable": true,
               "backend": "built_in_database",
               "mechanism": "password_based",
               "password_hash_algorithm": {
                   "iterations": 210000,
                   "mac_fun": "sha512",
                   "name": "pbkdf2"
               },
               "user_id_type": "username"
           },
           "dashboard": {
               "listeners": {
                   "http": {
                       "bind": 18083
                   }
               }
           }
       },
       "authMode": "bypass",
       "requiresPrivilege": "true"
   }
   ```

------

1. 选择**确认**。

1. 选择 “**下一**步”，直到进入 “**查看**” 步骤。

1. 选择**部署**。

**注意**  
此后，您无法编辑 ACL 文件来更新授权规则。或者，您可以在成功部署[通过 EMQX 控制面板为用户添加授权规则](add-rules-emqx-broker.md)后继续。

# 通过 EMQX 控制面板为用户添加授权规则
<a name="add-rules-emqx-broker"></a>

您可以使用 EMQX 控制面板或 EMQX CLI 工具添加或更新授权规则。 AWS IoT SiteWise AWS IoT SiteWise EMQX CLI 工具使用 EMQX 的内置数据库管理授权。

**注意**  
添加授权规则是一个高级配置步骤，需要了解 MQTT 主题模式和访问控制。*有关使用 EMQX 的内置数据库创建授权规则的更多信息，请参阅 EMQX 文档中的[使用内置数据库](https://docs.emqx.com/en/emqx/latest/access-control/authz/mnesia.html)。*

**注意**  
所提供的 EMQX 相关说明仅供参考。由于 EMQX 的文档和功能可能会随着时间的推移而发生变化，并且我们不保留其文档，因此我们建议您查阅 [EMQX 的官方文档](https://docs.emqx.com/en/emqx/latest/)以获取最新信息。

------
#### [ EMQX dashboard ]

此过程说明如何在 EMQX 控制面板上添加授权规则。

EMQX 控制面板只能从网关主机内部访问。如果您尝试从网关主机外部进行连接，则无法访问控制面板。

**使用 EMQX 控制面板添加授权规则**

1. 确保您在网关主机内。

1. 打开浏览器窗口并访问[http://localhost:18083/](http://localhost:18083/)。

1. 登录 EMQX 控制面板。此过程假设您已将默认登录凭证更改为自己选择的登录凭证。有关初始设置的更多信息，请参阅[启用用户名和密码认证](configure-emqx-broker.md#emqx-broker-username-password-auth)。

1. 选择盾牌图标，然后从下拉菜单中选择 “**授权**”。

1. 在 “**内置数据库**” 行上选择 “**权限**” 按钮。

1. 在 “内置数据库授权” 部分，根据您的业务需求添加或更新用户授权规则。有关创建规则的更多指导，请参阅 *EMQX* 文档中的[使用内置数据库](https://docs.emqx.com/en/emqx/latest/access-control/authz/mnesia.html)部分。

------
#### [ AWS IoT SiteWise CLI tool using Linux ]

**要在 Linux 中使用 AWS IoT SiteWise EMQX CLI 工具管理授权规则，请执行以下操作：**
+ 使用以下格式为用户添加授权规则：

  ```
  /greengrass/v2/bin/swe-emqx-cli auth add your-username your-action your-permission your-topic [your-action-permission-topic]
  ```

**Example 为用户添加授权规则**  
此示例说明如何为名为`system1`：的用户添加规则：  

```
/greengrass/v2/bin/swe-emqx-cli auth add system1 \
    publish allow "sensors/#" \
    subscribe allow "control/#" \
    all deny "#"
```

**Example ：查看用户的授权规则**  
要查看`system1`用户的授权规则，请运行以下命令：  

```
/greengrass/v2/bin/swe-emqx-cli auth list system1
```

**Example : 查看所有现有的授权规则**  
要查看您当前拥有的所有授权规则，请运行以下命令：  

```
/greengrass/v2/bin/swe-emqx-cli auth list
```

**Example : 删除用户的所有授权规则**  
要删除应用于特定用户的所有授权规则，请运行以下命令：  

```
/greengrass/v2/bin/swe-emqx-cli auth delete system1
```
系统将提示您确认删除。

------
#### [ AWS IoT SiteWise CLI tool using Windows ]

**要使用 AWS IoT SiteWise EMQX CLI 工具管理授权规则，请执行以下操作：Windows PowerShell**
+ 使用以下格式为用户添加授权规则：

  ```
  C:\greengrass\v2\bin\swe-emqx-cli.ps1 auth add your-username your-action your-permission your-topic [your-action-permission-topic]
  ```

**Example : 为用户添加授权规则**  
此示例说明如何为名为`system1`：的用户添加规则：  

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 auth add system1 `
    publish allow "sensors/#" `
    subscribe allow "control/#" `
    all deny "#"
```

**Example ：查看用户的授权规则**  
要查看`system1`用户的授权规则，请运行以下命令：  

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 auth list system1
```

**Example : 查看所有现有的授权规则**  
要查看您当前拥有的所有授权规则，请运行以下命令：  

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 auth list
```

**Example : 删除用户的所有授权规则**  
要删除应用于特定用户的所有授权规则，请运行以下命令：  

```
C:\greengrass\v2\bin\swe-emqx-cli.ps1 auth delete system1
```
系统将提示您确认删除。

------

# 使用 SiteWise Edge 和开源工具处理和可视化数据
<a name="open-source-edge-integrations"></a>

使用开源工具配置支持 AWS IoT SiteWise Edge MQTT 的网关，用于本地处理和可视化，以增强您的工业数据管理能力。

借 SiteWise 助 Edge，您可以使用外部开源工具创建本地数据处理管道。[使用 [Node-RED®](https://nodered.org/) 通过 [InfluxDB® 存储时间序列数据，并通过 Grafana®](https://www.influxdata.com/lp/influxdb-database/) 仪表板监控操作。](https://grafana.com/)

Node-red 处理和转换您的数据流，而 InfluxDB 提供时间序列数据存储。Grafana 显示您的实时运营数据。将这些工具与 SiteWise Edge 配合使用，可以在本地环境与之间同步数据 AWS 云，从而为您提供即时的本地见解和基于云的长期分析功能。

**注意**  
Node-red®、InfluxDB® 和 Grafana® 不是 Edge 的供应商或供应商。 SiteWise 

![\[该图显示了一些数据源以及连接到 EMQX Broker 以供发布的涡轮机仿真器。然后 EMQX 代理订阅 AWS IoT SiteWise 网关和 Node-red。节点红色输入到 InfluxDB，然后 Influx DB 输入到 Grafana 控制面板。\]](http://docs.aws.amazon.com/zh_cn/iot-sitewise/latest/userguide/images/gateway-open-source-overview.png)


**注意**  
在本指南中，我们使用的是开源版本的 [Grafana](https://grafana.com/) for Edge，而不是[亚马逊托管](https://docs.aws.amazon.com/grafana/latest/userguide/what-is-Amazon-Managed-Service-Grafana.html) Grafana SiteWise 服务。

## 部署选项
<a name="deployment-options"></a>

您可以使用以下两种方法之一来部署此解决方案。通过Microsoft Windows手动设置，您可以控制组件配置以及与基础架构的集成。使用Linux，您可以使用 Docker 在容器中部署预配置的组件。

选择符合您的操作要求的方法。
+ [手动设置开源集成 (Windows)](windows-manual-setup.md)— 用于自定义配置或现有基础架构
+ [设置与 Docker 的开源集成 (Linux)](linux-docker-setup.md)— 使用预先配置的组件进行快速部署

## 风电场示例概述
<a name="open-source-example-overview"></a>

本指南以风力发电场为例，演示如何监控风力发电场中涡轮机的风速。这个实际场景说明了常见的工业监控需求，在这些需求中，本地和基于云的可视性对于提高运营效率都非常重要。

通过此集成，您可以：
+ 使用 AWS IoT SiteWise Edge 网关从工业设备收集数据
+ 使用 Node-RED、InfluxDB 和 Grafana 在本地处理数据
+ 使用 InfluxDB 在本地存储数据
+ 使用 Grafana 仪表板实时监控数据

在本指南中，我们以风电场为例。我们使用 Node-RED 来模拟生成风速数据的涡轮机。Node-red 转换数据有效负载，将数据发布到 SiteWise Edge MQTT 代理，订阅接收来自代理的数据，并将数据本地存储在 InfluxDB 中。这种方法可确保所有运营数据均可在本地立即访问，也可在云端进行进一步分析。通过实施这种模式，您可以获得抵御网络中断的弹性，同时保持在网络中执行高级分析的能力。 AWS 云 Grafana 连接到 InfluxDB 进行本地监控，让操作员无需依赖云即可实时查看指标。支持 SiteWise Edge MQTT 的网关连接到同一 MQTT 代理以向其发送数据 AWS IoT SiteWise，从而在边缘操作和基于云的服务之间架起一座桥梁。

无论您是在监控制造设备、公用事业基础设施还是其他工业资产，您都可以使用自己的数据和配置来创建针对您的特定行业要求量身定制的类似工作流程。

## 开源集成的要求
<a name="open-source-requirements"></a>

在与 SiteWise Edge 实现开源集成之前，请确保您的环境满足必要要求。
+ **硬件要求**-您的网关硬件必须满足 SiteWise Edge 网关的要求。有关更多信息，请参阅启[AWS IoT SiteWise Edge 自托管网关要求](configure-gateway-ggv2.md)用 MQTT、V3 网关和。[AWS IoT SiteWise 边缘应用程序的要求](siemens-app-gateway-requirements.md)
**重要**  
[部署其他开源组件时，请确保您的硬件满足 [InfluxDB](https://docs.influxdata.com/influxdb/v2/install/)、[Nod](https://nodered.org/docs/getting-started/) e-RED 和 Grafana 的要求。](https://grafana.com/docs/grafana/latest/setup-grafana/installation/)
+ 您的网络配置必须支持组件之间的本地通信和 SiteWise Edge 的云连接。
+ 所有服务都必须在同一台主机上运行。

## 安全注意事项
<a name="open-source-security-considerations"></a>

我们建议您对组件之间的所有通信进行加密，尤其是在从非本地网络访问接口时。对每个组件实施适当的访问控制，并遵循 AWS IoT SiteWise 边缘网关配置和 AWS 账户安全 AWS 的最佳实践。

**开发环境**  
本指南演示了 Node-RED、InfluxDB 和 Grafana 在网关主机上运行和本地访问。对于需要外部访问的生产部署，请实施包括 TLS 加密、身份验证和授权在内的安全措施。遵循每个应用程序的安全最佳实践。

**第三方软件**  
此解决方案使用非由其维护的第三方软件 AWS，包括 InfluxDB、Node-RED、Grafana 和插件。`node-red-contrib-influxdb`在部署之前，请确保这些组件符合贵组织的安全要求、合规性标准和监管政策。

**重要**  
本指南引用并使用并非由其拥有或维护的第三方软件 AWS。在实施之前，请确保所有组件都满足您的安全、合规和管理要求。使用最新的安全补丁更新所有软件，并遵循最佳实践来保护边缘部署。  
 InfluxDB、Node-red、Grafana 不是 Edge 的供应商或供应商。 SiteWise 

## 其他考虑因素
<a name="open-source-other-considerations"></a>

在实现与 SiteWise Edge 的开源集成时，请考虑这些其他因素。
+ 使用所有服务、工具和组件的最新版本。
+ 在云端传输之前，在本地筛选和聚合数据，以降低 AWS IoT SiteWise 数据摄取成本。在 InfluxDB 中配置适当的数据保留期，并正确调整网关硬件的大小。有关更多信息，请参阅[AWS IoT SiteWise 定价](https://aws.amazon.com/iot-sitewise/pricing/)。
+ 对所有数据实施定期备份程序。
+ 监控网关上的资源使用情况，并为每个组件配置适当的资源限制。在InfluxDB中实施数据保留策略以管理磁盘使用情况。

# 手动设置开源集成 (Windows)
<a name="windows-manual-setup"></a>

使用本指南为与 Grafana® 和 Node-RED® 连接的风速数据手动创建时序存储桶。

 手动安装和配置 Node-RED、InfluxDB® 和 Grafana 以控制您的部署配置。Microsoft Windows您可以使用InfluxDB存储和管理来自设备的时间序列数据。

## 手动设置的先决条件
<a name="windows-open-source-prerequisites"></a>

在开始之前，请完成以下要求：

**注意**  
在同一台主机上运行所有服务（SiteWise Edge、InfluxDB、Node-RED 和 Grafana）。
+ 安装支持 MQTT 的 V3 网关。有关更多信息，请参阅 [支持 MQTT 的边缘版 V3 网关 AWS IoT SiteWise](mqtt-enabled-v3-gateway.md)。
+ 在本地安装和运行以下服务：
  + InfluxDB OSS v2。有关安装步骤，请参阅[安装 InfluxDB](https://docs.influxdata.com/influxdb/v2/install/)。
  + Node-red。有关安装步骤，请参阅在本地[安装 Node-RED](https://nodered.org/docs/getting-started/local)。
  + Grafana。有关安装步骤，请参阅[安装 Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/installation/)。

# 使用 InfluxDB 设置本地存储
<a name="windows-influxdb-setup"></a>

使用 InfluxDB®，您可以在本地存储设备上的时间序列数据。本地存储功能的目的是在网络中断期间保持操作可见性，并减少时间关键型应用程序的延迟。您可以在边缘执行分析和可视化，同时仍然可以选择性地将数据转发到云端。

在本节中，您将为涡轮机风速数据创建时间序列存储桶，并为 Grafana® 和 Node-RED® 连接生成一个 API 令牌。InfluxDB 存储桶可用作时间序列数据的专用存储容器，类似于传统系统中的数据库。API 令牌支持以编程方式安全地访问您的数据。

**设置 InfluxDB**

1. 完成必备步骤并确保所有工具都在同一台主机上运行后，打开您的 Web 浏览器并前往 [http://127.0.0.1:8086](http://127.0.0.1:8086)。

1. （可选）启用 TLS 加密以增强安全性。有关更多信息，请参阅中的[启用 TLS 加密*InfluxData Documentation*](https://docs.influxdata.com/influxdb/v2/admin/security/enable-tls/)。

1. 创建一个时间序列 InfluxDB 存储桶来存储来自 Node-RED 的数据。该存储桶将用作风电场数据的专用容器，允许您组织和管理特定于该数据集的保留策略。有关更多信息，请参阅中的[管理存储桶](https://docs.influxdata.com/influxdb/v2/admin/buckets/)。*InfluxData Documentation*

1. （可选）为您的边缘站点配置数据保留期。设置适当的保留期可以自动删除本地操作不再需要的旧数据，从而有助于高效地管理存储资源。

   有关数据保留的信息，请参阅[中的 InfluxDB 中的数据保留](https://docs.influxdata.com/influxdb/v2/reference/internals/data-retention/)。*InfluxData Documentation*

1. 为存储桶生成 API 令牌。该令牌将启用InfluxDB与其他组件（例如Node-red和Grafana）之间的安全通信。这样，只有经过授权的服务才能读取或写入您的数据存储。有关更多信息，请参阅中的[创建令牌*InfluxData Documentation*](https://docs.influxdata.com/influxdb/cloud/admin/tokens/create-token/)。

完成这些步骤后，您可以将时间序列数据存储在InfluxDB实例中，从而为边缘环境中的本地数据持久性和分析奠定基础。

# 为数据集成配置 Node-red 流程 AWS IoT SiteWise
<a name="windows-nodered-config"></a>

借助 Node-red®，您可以实现两个流程来管理设备和之间的数据。 AWS IoT SiteWise这些流程共同创建了一个全面的数据管理解决方案，可同时满足本地和云端数据流的需求。
+ **数据发布流程**-发布到云端。数据发布流程将数据发送到 AWS IoT SiteWise。该流程通过生成传感器数据、将其转换为 AWS IoT SiteWise 格式并发布到 SiteWise Edge MQTT 代理来模拟涡轮机设备。这使您能够利用 AWS IoT SiteWise云功能进行存储、分析以及与其他 AWS 服务的集成。

  有关更多信息，请参阅 [配置数据发布流程](windows-nodered-data-publish-flow.md)。
+ **数据保留流程**-将数据存储在边缘。数据保留流程订阅 SiteWise Edge MQTT 代理以接收数据，将其转换为 InfluxDB® 格式，然后将其存储在本地以进行监控。这种本地存储允许即时访问操作数据，减少时间关键型应用程序的延迟，并确保网络中断期间的连续性。

  有关更多信息，请参阅 [配置数据保留流程](windows-nodered-data-retention-flow.md)。

这两个流程协同工作，确保数据既发送到本地， AWS IoT SiteWise 又存储在本地，以便立即访问。

[要访问你的 Node-red 主机，请访问 http://127.0.0.1:1880。](http://127.0.0.1:1880)有关启用 TLS 的信息，请参阅[启用 TLS 加密](https://docs.influxdata.com/influxdb/v2/admin/security/enable-tls/)。

# 配置数据发布流程
<a name="windows-nodered-data-publish-flow"></a>

数据发布流程使用三个节点来创建将您的工业数据发送到云端的管道。该流程对于实现基于云的分析、长期存储以及与其他 AWS 服务的集成至关重要。首先，将模拟设备数据发送到 SiteWise Edge MQTT 代理。网关从经纪人那里获取数据，然后将其传输到 AWS IoT SiteWise 云端，在那里你可以利用强大的分析和可视化功能。
+ **数据输入**-接收来自工业设备或模拟器的设备数据
+ **数据转换器 AWS IoT SiteWise**-将数据转换为 AWS IoT SiteWise 格式，以确保与 SiteWise Edge 网关兼容
+ **MQTT 发布者**-向 SiteWise Edge MQTT 代理发布数据，使其可供本地和云用户使用

![\[显示了 Node-red 数据发布流程的图表。它将模拟设备数据发送到 SiteWise Edge MQTT 代理，由 Ed SiteWise ge Gateway 获取，然后发送到 AWS IoT SiteWise 云端。\]](http://docs.aws.amazon.com/zh_cn/iot-sitewise/latest/userguide/images/gateway-open-source-nodered-publish-flow.png)


## 配置数据输入节点
<a name="windows-nodered-data-input-config"></a>

在此示例中，数据输入节点使用模拟风力涡轮机设备来生成风速数据。无论是来自模拟源（如我们的示例）还是来自生产环境中的实际工业设备，此节点都是您的工业数据的入口点。

我们对数据负载使用自定义 JSON 格式，以提供可与本地处理工具和 AWS IoT SiteWise 云服务高效配合使用的标准化结构。这种格式包括时间戳和质量指标等基本元数据以及实际测量值，从而在整个管道中实现全面的数据管理和质量跟踪。导入注入节点，以此标准化 JSON 格式接收带有时间戳、质量指标和值的模拟数据。

*有关 Node-RED 注入节点的更多信息，请参阅文档中的[注入](https://nodered.org/docs/user-guide/nodes#inject)部分。Node-RED*

涡轮机模拟器每秒以这种标准化 JSON 格式生成风速数据：

**Example : 涡轮机数据有效载荷**  

```
{
    name: string,         // Property name/identifier
    timestamp: number,    // Epoch time in nanoseconds
    quality: "GOOD" | "UNCERTAIN" | "BAD",
    value: number | string | boolean
}
```

这种格式有几个好处：
+ 该`name`字段标识特定的属性或测量值，允许您跟踪来自同一设备的多个数据点
+ `timestamp`以纳秒为单位可确保精确的时间跟踪，从而进行准确的历史分析
+ 该`quality`指标可帮助您根据数据的可靠性筛选和管理数据
+ 灵活的`value`字段支持不同的数据类型，以适应不同的传感器输出

**Example : 涡轮模拟器的注入节点**  

```
[
    {
        "id": "string",
        "type": "inject",
        "z": "string",
        "name": "Turbine Simulator",
        "props": [
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "payload.quality",
                "v": "GOOD",
                "vt": "str"
            },
            {
                "p": "payload.value",
                "v": "$random()",
                "vt": "jsonata"
            },
            {
                "p": "payload.name",
                "v": "/Renton/WindFarm/Turbine/WindSpeed",
                "vt": "str"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": "",
        "topic": "",
        "x": 270,
        "y": 200,
        "wires": [
            [
                "string"
            ]
        ]
    }
]
```

## 为数据转换配置节点
<a name="windows-nodered-sitewiseise-translator-config"></a>

E SiteWise dge 网关需要特定格式的数据，以确保与 AWS IoT SiteWise 云的兼容性。转换器节点是将输入数据转换为所需 AWS IoT SiteWise 有效载荷格式的重要组件。此转换步骤可确保您的工业数据能够在 AWS IoT SiteWise 云环境中得到正确处理、存储和分析。

通过在此阶段对数据格式进行标准化，您可以实现边缘设备与云服务之间的集成，您可以在其中使用资产建模、分析和可视化功能。使用以下结构：

**Example : SiteWise Edge 数据解析的有效载荷结构**  

```
{
  "propertyAlias": "string",  
  "propertyValues": [
    {
      "value": { 
          "booleanValue": boolean, 
          "doubleValue": number, 
          "integerValue": number,
          "stringValue": "string" 
     },
      "timestamp": {
          "timeInSeconds": number,
          "offsetInNanos": number
      },
      "quality": "GOOD" | "UNCERTAIN" | "BAD",
  }]
}
```

**注意**  
`propertyAlias`将与您的 MQTT 主题层次结构相匹配（例如，`/Renton/WindFarm/Turbine/WindSpeed`）。这样可以确保您的数据与中的正确资产属性正确关联 AWS IoT SiteWise。有关更多信息，请参阅中的 “数据流别名” 概念[AWS IoT SiteWise 概念](concept-overview.md)。

1. 导入用于 AWS IoT SiteWise 有效载荷转换的示例函数节点。此函数处理从标准化输入格式到 AWS IoT SiteWise兼容格式的转换，确保正确的时间戳格式、质量指标和值键入。

   ```
   [
       {
           "id": "string",
           "type": "function",
           "z": "string",
           "name": "Translate to SiteWise payload",
           "func": "let input = msg.payload;\nlet output = {};\n\noutput[\"propertyAlias\"] = input.name;\n\nlet propertyVal = {}\n\nlet timeInSeconds = Math.floor(input.timestamp / 1000);\nlet offsetInNanos = (input.timestamp % 1000) * 1000000;\n\npropertyVal[\"timestamp\"] = {\n    \"timeInSeconds\": timeInSeconds,\n    \"offsetInNanos\": offsetInNanos,\n};\n\npropertyVal[\"quality\"] = input.quality\n\nlet typeNameConverter = {\n    \"number\": (x) => Number.isInteger(x) ? \"integerValue\" : \"doubleValue\",\n    \"boolean\": (x) => \"booleanValue\",\n    \"string\": (x) => \"stringValue\", \n}\nlet typeName = typeNameConverter[typeof input.value](input.value)\npropertyVal[\"value\"] = {}\npropertyVal[\"value\"][typeName] = input.value;\n\noutput[\"propertyValues\"] = [propertyVal]\n\nreturn {\n    payload: JSON.stringify(output)\n};",
           "outputs": 1,
           "timeout": "",
           "noerr": 0,
           "initialize": "",
           "finalize": "",
           "libs": [],
           "x": 530,
           "y": 200,
           "wires": [
               [
                   "string"
               ]
           ]
       }
   ]
   ```

1. 验证 JavaScript 代码是否正确转换了风速数据。该函数执行几项重要任务：
   + 从输入中提取属性名称并将其设置为 propertyAlias
   + 将时间戳从毫秒转换为所需的秒和纳秒格式
   + 保留用于数据可靠性跟踪的质量指标
   + 自动检测值类型并根据 AWS IoT SiteWise 要求对其进行格式化

1. 将该节点连接到您的流程，将其链接到数据输入节点和 MQTT 发布者之间。

有关编写特定于业务需求的函数的指导，请参阅*Node-RED文档*中的[编写函数](https://nodered.org/docs/user-guide/writing-functions)

## 配置 MQTT 发布器
<a name="windows-nodered-mqtt-publisher-config"></a>

翻译完成后，数据就可以发布到 SiteWise Edge MQTT 代理了。

使用以下设置配置 MQTT 发布者以向 SiteWise Edge MQTT 代理发送数据：

**导入 MQTT 输出节点**

1. 使用`"type": "mqtt out"`将 MQTT 导出配置节点。MQTT 输出节点允许您共享经纪商的配置。

1. 输入键值对以获取与 MQTT 代理连接和消息路由相关的信息。

导入示例`mqtt out`节点。

**Example**  

```
[
    {
        "id": "string",
        "type": "mqtt out",
        "z": "string",
        "name": "Publish to MQTT broker",
        "topic": "/Renton/WindFarm/Turbine/WindSpeed",
        "qos": "1",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "string",
        "x": 830,
        "y": 200,
        "wires": []
    },
    {
        "id": "string",
        "type": "mqtt-broker",
        "name": "emqx",
        "broker": "127.0.0.1",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "5",
        "keepalive": 15,
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]
```

示例 MQTT 输出节点使用以下信息创建 MQTT 连接：
+ Server：`127.0.0.1`
+ 端口：`1883`
+ 协议：`MQTT V5`

然后，MQTT 输出节点使用以下信息配置消息路由：
+ 主题: `/Renton/WindFarm/Turbine/WindSpeed`
+ 服务质量：`1`

## 部署并验证节点
<a name="windows-verify-deployment"></a>

配置三个数据发布流程节点后，请按照以下步骤部署流程并验证数据是否正确传输到 AWS IoT SiteWise

**部署和验证连接**

1. 按照数据发布流程所示连接三个节点。  
![\[Data publish flow diagram showing input from turbine simulator to AWS IoT SiteWise to MQTT broker.\]](http://docs.aws.amazon.com/zh_cn/iot-sitewise/latest/userguide/images/gateway-open-source-nodered-publish-flow.png)

1. 选择 **Deploy** 以应用所有节点连接更改。

1. 导航到[AWS IoT SiteWise 控制台](https://console.aws.amazon.com/iotsitewise/)并选择 “**数据流**”。

1. 确保在下拉菜单中选择了**别名前缀**。然后，搜索`/Renton/WindFarm/Turbine/WindSpeed`别名。

如果您在搜索中看到正确的别名，则表示您已经部署了流程并验证了数据传输。

# 配置数据保留流程
<a name="windows-nodered-data-retention-flow"></a>

数据保留流程可用于保持边缘的操作可见性。这在网络中断或需要立即访问数据时非常有用。此流程订阅 MQTT 代理以接收设备数据，将其转换为 InfluxDB® 格式，然后将其存储在本地。通过实施此流程，您可以创建弹性本地数据存储，操作员无需依赖云即可访问该数据存储，从而实现边缘的实时监控和决策。

该流程由三个关键组件组成，它们协同工作，以确保正确捕获和存储您的数据：
+ **MQTT 订阅客户端**-接收来自经纪商的数据，确保您捕获所有相关的行业数据
+ **InfluxDB 转换器**-将 AWS IoT SiteWise 有效负载转换为 InfluxDB 格式，为高效的时间序列存储做好准备
+ **InfluxDB 写入器**-处理本地存储，确保本地应用程序的数据持久性和可用性

![\[Node-red 数据保留流程\]](http://docs.aws.amazon.com/zh_cn/iot-sitewise/latest/userguide/images/gateway-open-source-nodered-data-retention.png)


## 设置 MQTT 订阅客户端
<a name="windows-nodered-mqtt-subscriber"></a>
+ 通过导入以下示例，在 Node-RED 中配置 MQTT 订阅客户端，使其接收来自 MQTT EMQX 代理的数据。 AWS IoT SiteWise   
**Example : 节点中的 MQTT**  

  ```
  [
      {
          "id": "string",
          "type": "mqtt in",
          "z": "string",
          "name": "Subscribe to MQTT broker",
          "topic": "/Renton/WindFarm/Turbine/WindSpeed",
          "qos": "1",
          "datatype": "auto-detect",
          "broker": "string",
          "nl": false,
          "rap": true,
          "rh": 0,
          "inputs": 0,
          "x": 290,
          "y": 340,
          "wires": [
              [
                  "string"
              ]
          ]
      },
      {
          "id": "string",
          "type": "mqtt-broker",
          "name": "emqx",
          "broker": "127.0.0.1",
          "port": "1883",
          "clientid": "",
          "autoConnect": true,
          "usetls": false,
          "protocolVersion": "5",
          "keepalive": 15,
          "cleansession": true,
          "autoUnsubscribe": true,
          "birthTopic": "",
          "birthQos": "0",
          "birthPayload": "",
          "birthMsg": {},
          "closeTopic": "",
          "closePayload": "",
          "closeMsg": {},
          "willTopic": "",
          "willQos": "0",
          "willPayload": "",
          "willMsg": {},
          "userProps": "",
          "sessionExpiry": ""
      }
  ]
  ```

此订阅可确保捕获发布给经纪商的所有相关数据以供本地存储，从而提供您的工业运营的完整记录。该节点使用与该[配置 MQTT 发布器](windows-nodered-data-publish-flow.md#windows-nodered-mqtt-publisher-config)部分相同的 MQTT 连接参数，订阅设置如下：
+ 话题 — `/Renton/WindFarm/Turbine/WindSpeed`
+ 服务质量 — `1`

有关更多信息，请参阅*Node-RED文档*中的 [Connect 到 MQTT 代理](https://cookbook.nodered.org/mqtt/connect-to-broker)。

## 配置 InfluxDB 转换器
<a name="windows-nodered-influxdb-translator"></a>

InfluxDB 使用[标签](https://docs.influxdata.com/influxdb/v1/concepts/glossary/#tag)进行索引，使用[字段](https://docs.influxdata.com/influxdb/v1/concepts/glossary/#field)作为值来组织数据。该组织优化了时间序列数据的查询性能和存储效率。导入包含将 AWS IoT SiteWise 有效载荷转换为 InfluxDB 格式的 JavaScript 代码的示例函数节点。翻译器将属性分成两组：
+ 标签-用于高效索引的质量和名称属性
+ 字段-时间戳（自纪元以来的毫秒数）和值

**Example : 转换为 InfluxDB 有效负载的函数节点**  

```
[
    {
        "id": "string",
        "type": "function",
        "z": "string",
        "name": "Translate to InfluxDB payload",
        "func": "let data = msg.payload;\n\nlet timeInSeconds = data.propertyValues[0].timestamp.timeInSeconds;\nlet offsetInNanos = data.propertyValues[0].timestamp.offsetInNanos;\nlet timestampInMilliseconds = (timeInSeconds * 1000) + (offsetInNanos / 1000000);\n\nmsg.payload = [\n    {\n        \"timestamp(milliseconds_since_epoch)\": timestampInMilliseconds,\n        \"value\": data.propertyValues[0].value.doubleValue\n    },\n    {\n        \"name\": data.propertyAlias,\n        \"quality\": data.propertyValues[0].quality\n    }\n]\n\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 560,
        "y": 340,
        "wires": [
            [
                "string"
            ]
        ]
    }
]
```

有关其他配置选项，请参阅 Node-red GitHub 存储库[node-red-contrib-influxdb](https://github.com/mblackstock/node-red-contrib-influxdb)中的。

## 设置 InfluxDB 写入器
<a name="windows-nodered-influxdb-writer"></a>

InfluxDB 写入器节点是数据保留流程中的最后一个组件，负责将工业数据存储在本地 InfluxDB 数据库中。这种本地存储对于在网络中断期间保持操作可见性以及为时间紧迫的应用程序提供即时数据访问非常重要。

1. 通过 “管理面板” 选项安装 node-red-contrib-influxdb软件包。该软件包提供了将 Node-RED 与 InfluxDB 连接所需的节点。

1. 向您的流程中添加一个 InfluxDB 输出节点。这个节点将处理向你的InfluxDB数据库实际写入数据。

1. 配置服务器属性以建立与InfluxDB实例的安全连接：

   1. 将版本设置为 2.0-这指定您要连接到 InfluxDB v2.x，该版本使用与早期版本不同的 API

   1. 将 URL 设置为 `http://127.0.0.1:8086`-这指向您的本地 InfluxDB 实例

   1. 输入你的 InfluxDB 身份验证令牌。此安全令牌授权与您的数据库的连接。您在[使用 InfluxDB 设置本地存储](windows-influxdb-setup.md)操作过程中生成了令牌。

1. 指定存储位置参数以定义数据的存储位置和方式：

   1. 输入您的InfluxDB组织名称-该组织是一个供一组用户使用的工作空间，您的存储桶和仪表板属于该组。有关更多信息，请参阅中的[管理组织*InfluxData Documentation*](https://docs.influxdata.com/influxdb/v2/admin/organizations/)。

   1. 指定 InfluxDB 存储桶（例如，`WindFarmData`）— 该存储桶等同于传统系统中的数据库，可用作时间序列数据的容器

   1. 设置 InfluxDB 测量（例如`TurbineData`）— 测量值类似于关系数据库中的表，用于组织相关数据点

**注意**  
在InfluxDB实例的左侧边栏中找到您的组织名称。组织、存储桶和测量概念是InfluxDB数据组织模型的基础。有关更多信息，请参阅 [InfluxDB 文档](https://docs.influxdata.com/influxdb/v2/admin/organizations/)。

## 部署并验证保留流程
<a name="windows-nodered-retention-deploy"></a>

配置数据保留流程的所有组件后，您需要部署并验证系统是否正常运行。这种验证可确保您的工业数据正确存储在本地，便于即时访问和分析。

1. 如数据保留流程图所示，连接三个节点。这将创建从数据订阅到本地存储的完整管道。  
![\[Node-red 数据保留流程\]](http://docs.aws.amazon.com/zh_cn/iot-sitewise/latest/userguide/images/gateway-open-source-nodered-data-retention.png)

1. 选择 **Deploy** 以应用您的更改并激活流程。这将启动数据收集和存储过程。

1. 使用 InfluxDB 数据资源管理器查询和可视化您的数据。此工具允许您验证数据存储是否正确，并创建时间序列数据的初始可视化效果。

   在 Data Explorer 中，您应该能够看到随时间推移记录的风速测量结果，从而确认从数据生成到本地存储的整个管道是否正常运行。

   有关更多信息，请参阅[中的在数据资源管理器中查询*InfluxData Documentation*](https://docs.influxdata.com/influxdb/v2/query-data/execute-queries/data-explorer/)。

部署了数据发布流程和数据保留流程后，您现在拥有了一个完整的系统，可以将数据发送到 AWS IoT SiteWise 云端，同时维护本地副本以实现即时访问和弹性。这种双路径方法可确保您从基于云的分析和存储中受益，同时保持边缘的运营可见性。

# 为 Edge 设置 Gra SiteWise fana
<a name="windows-grafana"></a>

 Grafana® 允许您为工业数据创建本地实时监控仪表板。通过可视化存储在InfluxDB® 中的数据，您可以为操作员提供有关设备性能、过程效率和潜在问题的即时见解。这种边缘可见性对于时间敏感型运营和在网络中断期间保持连续性非常重要。

## 配置数据来源
<a name="windows-grafana-data-source-config"></a>

将 Grafana 连接到您的 InfluxDB 数据库可为您的工业数据创建强大的可视化层。这种连接支持实时监控仪表板，操作员可以使用这些仪表板做出明智的决策，而无需依赖云。

1. 在浏览器中导航到 http://127.0.0.1:3000，即可在本地访问你的 Grafana 实例[。](http://127.0.0.1:3000)*如果需要启用 TLS，您可以参考文档中的[设置 Grafana HTTPS 以实现安全的网络](https://grafana.com/docs/grafana/latest/setup-grafana/set-up-https/)流量。Grafana Labs*

1. 添加一个 InfluxDB 数据源，该数据源指向 Node-RED 写入数据的 InfluxDB 时间序列存储桶。例如 `WindFarmData`。此连接在您存储的数据和可视化平台之间建立了链接。

1. *有关详细说明，请参阅文档[中的配置 InfluxDB 数据源](https://grafana.com/docs/grafana/latest/datasources/influxdb/configure-influxdb-data-source/)。Grafana Labs*

### 为边缘数据创建 Grafana 控制面板 SiteWise
<a name="windows-grafana-create-dashboard"></a>

创建仪表板是构建本地监控解决方案的最后一步。仪表板可直观地呈现您的工业数据，使您可以更轻松地一目了然地识别趋势、异常和潜在问题。
+ 按照指南创建仪表板。有关更多信息，请参阅*Grafana Labs文档*中的[创建您的第一个仪表板](https://grafana.com/docs/grafana/latest/getting-started/build-first-dashboard/)。此模板假设您的存储桶已命名`WindFarmData`，测量值为`TurbineData`。

  您还可以使用快速入门指南，通过导入提供的示例仪表板模板来快速创建带有时间序列图的仪表板，该仪表板包含上一节中 Node-RED 生成的数据的时间序列图。此模板提供了一个起点，您可以对其进行自定义以满足您的特定监控需求。

  ```
  {
    "__inputs": [
      {
        "name": "DS_WINDFARM-DEMO",
        "label": "windfarm-demo",
        "description": "",
        "type": "datasource",
        "pluginId": "influxdb",
        "pluginName": "InfluxDB"
      }
    ],
    "__elements": {},
    "__requires": [
      {
        "type": "grafana",
        "id": "grafana",
        "name": "Grafana",
        "version": "11.6.0-pre"
      },
      {
        "type": "datasource",
        "id": "influxdb",
        "name": "InfluxDB",
        "version": "1.0.0"
      },
      {
        "type": "panel",
        "id": "timeseries",
        "name": "Time series",
        "version": ""
      }
    ],
    "annotations": {
      "list": [
        {
          "builtIn": 1,
          "datasource": {
            "type": "grafana",
            "uid": "-- Grafana --"
          },
          "enable": true,
          "hide": true,
          "iconColor": "rgba(0, 211, 255, 1)",
          "name": "Annotations & Alerts",
          "type": "dashboard"
        }
      ]
    },
    "editable": true,
    "fiscalYearStartMonth": 0,
    "graphTooltip": 0,
    "id": null,
    "links": [],
    "panels": [
      {
        "datasource": {
          "type": "influxdb",
          "uid": "${DS_WINDFARM-DEMO}"
        },
        "fieldConfig": {
          "defaults": {
            "color": {
              "mode": "palette-classic"
            },
            "custom": {
              "axisBorderShow": false,
              "axisCenteredZero": false,
              "axisColorMode": "text",
              "axisLabel": "",
              "axisPlacement": "auto",
              "barAlignment": 0,
              "barWidthFactor": 0.6,
              "drawStyle": "line",
              "fillOpacity": 0,
              "gradientMode": "none",
              "hideFrom": {
                "legend": false,
                "tooltip": false,
                "viz": false
              },
              "insertNulls": false,
              "lineInterpolation": "linear",
              "lineWidth": 1,
              "pointSize": 5,
              "scaleDistribution": {
                "type": "linear"
              },
              "showPoints": "auto",
              "spanNulls": false,
              "stacking": {
                "group": "A",
                "mode": "none"
              },
              "thresholdsStyle": {
                "mode": "off"
              }
            },
            "mappings": [],
            "thresholds": {
              "mode": "absolute",
              "steps": [
                {
                  "color": "green"
                },
                {
                  "color": "red",
                  "value": 80
                }
              ]
            }
          },
          "overrides": []
        },
        "gridPos": {
          "h": 8,
          "w": 12,
          "x": 0,
          "y": 0
        },
        "id": 1,
        "options": {
          "legend": {
            "calcs": [],
            "displayMode": "list",
            "placement": "bottom",
            "showLegend": true
          },
          "tooltip": {
            "hideZeros": false,
            "mode": "single",
            "sort": "none"
          }
        },
        "pluginVersion": "11.6.0-pre",
        "targets": [
          {
            "datasource": {
              "type": "influxdb",
              "uid": "${DS_WINDFARM-DEMO}"
            },
            "query": "from(bucket: \"WindFarmData\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"TurbineData\")\n  |> filter(fn: (r) => r[\"_field\"] == \"value\")\n  |> filter(fn: (r) => r[\"name\"] == \"/Renton/WindFarm/Turbine/WindSpeed\")\n  |> filter(fn: (r) => r[\"quality\"] == \"GOOD\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")",
            "refId": "A"
          }
        ],
        "title": "Panel Title",
        "type": "timeseries"
      }
    ],
    "schemaVersion": 41,
    "tags": [],
    "templating": {
      "list": []
    },
    "time": {
      "from": "now-6h",
      "to": "now"
    },
    "timepicker": {},
    "timezone": "browser",
    "title": "demo dashboard",
    "uid": "fejc0t08o6d4wb",
    "version": 1,
    "weekStart": ""
  }
  ```

# 设置与 Docker 的开源集成 (Linux)
<a name="linux-docker-setup"></a>

为了简化部署流程，你可以使用 Docker 在 Linux 环境中设置 Node-RED®、InfluxDB® 和 Grafana®。此方法使用预先配置的容器，可以快速部署并更轻松地管理组件。

## Docker 安装前提条件
<a name="linux-docker-prerequisites"></a>

在开始之前，请验证是否符合以下条件：
+ 支持 MQTT 的 V3 网关。有关更多信息，请参阅 [支持 MQTT 的边缘版 V3 网关 AWS IoT SiteWise](mqtt-enabled-v3-gateway.md)。
+ Docker Compose 插件。有关安装步骤，请参阅 *Docker* 手册文档中的[安装Docker Compose插件](https://docs.docker.com/compose/install/linux/)。

## 部署服务
<a name="linux-docker-deployment"></a>

此部署在同一台主机上运行 SiteWise Edge、InfluxDB、Node-RED 和 Grafana。

### 设置环境
<a name="linux-docker-env-setup"></a>

1. 获得根访问权限：

   ```
   sudo -i
   ```

1. 创建.env 文件或导出以下环境变量：

   ```
   export INFLUXDB_PASSWORD=your-secure-influxdb-password
   export INFLUXDB_TOKEN=your-secure-influxdb-token
   export GRAFANA_PASSWORD=your-secure-grafana-password
   ```

### 配置 Docker 网络
<a name="linux-docker-network-config"></a>
+ 使用名称创建桥接网络`SiteWiseEdgeNodeRedDemoNetwork`。

  ```
  docker network create --driver=bridge SiteWiseEdgeNodeRedDemoNetwork
  ```

### 准备Docker Compose文件
<a name="linux-docker-compose-file"></a>

将以下 YAML 文件的内容复制到您的 SiteWise Edge 网关设备。

#### 展开查看 Docker Compose YAML 文件示例
<a name="collapsible-section-docker-compose-file"></a>

```
services:
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    ports:
      - "127.0.0.1:8086:8086"
    volumes:
      - influxdb-storage:/.influxdbv2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PASSWORD}
      - DOCKER_INFLUXDB_INIT_ORG=iot-sitewise-edge
      - DOCKER_INFLUXDB_INIT_BUCKET=WindFarmData
      - DOCKER_INFLUXDB_INIT_RETENTION=0
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${INFLUXDB_TOKEN}
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - grafana-storage:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
      - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_PATHS_CONFIG=/etc/grafana/grafana.ini
      - GF_LOG_LEVEL=info
    configs:
      - source: grafana_datasource
        target: /etc/grafana/provisioning/datasources/influxdb.yaml
      - source: grafana_preload_dashboard_config
        target: /etc/grafana/provisioning/dashboards/dashboard.yml
      - source: grafana_preload_dashboard
        target: /etc/grafana/provisioning/dashboards/demo_dashboard.json
    depends_on:
      - influxdb
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

  nodered:
    build:
      context: .
      dockerfile_inline: |
        FROM nodered/node-red:latest
        RUN npm install node-red-contrib-influxdb
    container_name: nodered
    ports:
      - "127.0.0.1:1880:1880"
    volumes:
      - node_red_data:/data
    environment:
      - NODE_RED_ENABLE_SAFE_MODE=false
      - NODE_RED_ENABLE_PALETTE_EDIT=true
      - NODE_RED_AUTO_INSTALL_MODULES=true
    configs:
      - source: nodered_flows
        target: /data/flows.json
      - source: nodered_settings
        target: /data/settings.js
      - source: nodered_flows_cred
        target: /data/flows_cred.json
    depends_on:
      - influxdb
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

volumes:
  influxdb-storage:
  grafana-storage:
  node_red_data:

networks:
  SiteWiseEdgeNodeRedDemoNetwork:
    external: true

configs:
  grafana_datasource:
    content: |
      apiVersion: 1
      datasources:
        - name: windfarm-demo
          type: influxdb
          access: proxy
          url: http://influxdb:8086
          jsonData:
            version: Flux
            organization: iot-sitewise-edge
            defaultBucket: WindFarmData
            tlsSkipVerify: true
          secureJsonData:
            token: ${INFLUXDB_TOKEN}
          editable: false

  grafana_preload_dashboard_config:
    content: |
      apiVersion: 1
      providers:
        - name: "Dashboard provider"
          orgId: 1
          type: file
          options: 
            path: /etc/grafana/provisioning/dashboards

  grafana_preload_dashboard:
    content: |
      {
        "annotations": {
          "list": [
            {
              "builtIn": 1,
              "datasource": {
                "type": "grafana",
                "uid": "-- Grafana --"
              },
              "enable": true,
              "hide": true,
              "iconColor": "rgba(0, 211, 255, 1)",
              "name": "Annotations & Alerts",
              "type": "dashboard"
            }
          ]
        },
        "editable": true,
        "fiscalYearStartMonth": 0,
        "graphTooltip": 0,
        "id": 1,
        "links": [],
        "panels": [
          {
            "datasource": {
              "type": "influxdb",
              "uid": "PEB0DCBF338B3CEB2"
            },
            "fieldConfig": {
              "defaults": {
                "color": {
                  "mode": "palette-classic"
                },
                "custom": {
                  "axisBorderShow": false,
                  "axisCenteredZero": false,
                  "axisColorMode": "text",
                  "axisLabel": "",
                  "axisPlacement": "auto",
                  "barAlignment": 0,
                  "barWidthFactor": 0.6,
                  "drawStyle": "line",
                  "fillOpacity": 0,
                  "gradientMode": "none",
                  "hideFrom": {
                    "legend": false,
                    "tooltip": false,
                    "viz": false
                  },
                  "insertNulls": false,
                  "lineInterpolation": "linear",
                  "lineWidth": 1,
                  "pointSize": 5,
                  "scaleDistribution": {
                    "type": "linear"
                  },
                  "showPoints": "auto",
                  "spanNulls": false,
                  "stacking": {
                    "group": "A",
                    "mode": "none"
                  },
                  "thresholdsStyle": {
                    "mode": "off"
                  }
                },
                "mappings": [],
                "thresholds": {
                  "mode": "absolute",
                  "steps": [
                    {
                      "color": "green"
                    },
                    {
                      "color": "red",
                      "value": 80
                    }
                  ]
                }
              },
              "overrides": []
            },
            "gridPos": {
              "h": 8,
              "w": 12,
              "x": 0,
              "y": 0
            },
            "id": 1,
            "options": {
              "legend": {
                "calcs": [],
                "displayMode": "list",
                "placement": "bottom",
                "showLegend": true
              },
              "tooltip": {
                "hideZeros": false,
                "mode": "single",
                "sort": "none"
              }
            },
            "pluginVersion": "11.6.0",
            "targets": [
              {
                "datasource": {
                  "type": "influxdb",
                  "uid": "PEB0DCBF338B3CEB2"
                },
                "query": "from(bucket: \"WindFarmData\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"TurbineData\")\n  |> filter(fn: (r) => r[\"_field\"] == \"value\")\n  |> filter(fn: (r) => r[\"name\"] == \"/Renton/WindFarm/Turbine/WindSpeed\")\n  |> filter(fn: (r) => r[\"quality\"] == \"GOOD\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")",
                "refId": "A"
              }
            ],
            "title": "Wind Speed",
            "type": "timeseries"
          }
        ],
        "preload": false,
        "schemaVersion": 41,
        "tags": [],
        "templating": {
          "list": []
        },
        "time": {
          "from": "now-6h",
          "to": "now"
        },
        "timepicker": {},
        "timezone": "browser",
        "title": "Demo Dashboard",
        "uid": "eejtureqjo9a8c",
        "version": 2
      }

  nodered_flows:
    content: |
      [
        {
          "id": "95fce448fdd43b47",
          "type": "tab",
          "label": "Demo Flow",
          "disabled": false,
          "info": ""
        },
        {
          "id": "5f63740b66af3386",
          "type": "mqtt out",
          "z": "95fce448fdd43b47",
          "name": "Publish to MQTT broker",
          "topic": "/Renton/WindFarm/Turbine/WindSpeed",
          "qos": "1",
          "retain": "",
          "respTopic": "",
          "contentType": "",
          "userProps": "",
          "correl": "",
          "expiry": "",
          "broker": "5744207557fa19be",
          "x": 830,
          "y": 200,
          "wires": []
        },
        {
          "id": "8f2eb590d596679b",
          "type": "function",
          "z": "95fce448fdd43b47",
          "name": "Translate to SiteWise payload",
          "func": "let input = msg.payload;\nlet output = {};\n\noutput[\"propertyAlias\"] = input.name;\n\nlet propertyVal = {}\n\nlet timeInSeconds = Math.floor(input.timestamp / 1000);\nlet offsetInNanos = (input.timestamp % 1000) * 1000000;\n\npropertyVal[\"timestamp\"] = {\n    \"timeInSeconds\": timeInSeconds,\n    \"offsetInNanos\": offsetInNanos,\n};\n\npropertyVal[\"quality\"] = input.quality\n\nlet typeNameConverter = {\n    \"number\": (x) => Number.isInteger(x) ? \"integerValue\" : \"doubleValue\",\n    \"boolean\": (x) => \"booleanValue\",\n    \"string\": (x) => \"stringValue\", \n}\nlet typeName = typeNameConverter[typeof input.value](input.value)\npropertyVal[\"value\"] = {}\npropertyVal[\"value\"][typeName] = input.value;\n\noutput[\"propertyValues\"] = [propertyVal]\n\nreturn {\n    payload: JSON.stringify(output)\n};",
          "outputs": 1,
          "timeout": "",
          "noerr": 0,
          "initialize": "",
          "finalize": "",
          "libs": [],
          "x": 530,
          "y": 200,
          "wires": [
            [
              "5f63740b66af3386"
            ]
          ]
        },
        {
          "id": "4b78cbdea5e3258c",
          "type": "inject",
          "z": "95fce448fdd43b47",
          "name": "Turbine Simulator",
          "props": [
            {
              "p": "payload.timestamp",
              "v": "",
              "vt": "date"
            },
            {
              "p": "payload.quality",
              "v": "GOOD",
              "vt": "str"
            },
            {
              "p": "payload.value",
              "v": "$$random()",
              "vt": "jsonata"
            },
            {
              "p": "payload.name",
              "v": "/Renton/WindFarm/Turbine/WindSpeed",
              "vt": "str"
            }
          ],
          "repeat": "1",
          "crontab": "",
          "once": false,
          "onceDelay": "",
          "topic": "",
          "x": 270,
          "y": 200,
          "wires": [
            [
              "8f2eb590d596679b"
            ]
          ]
        },
        {
          "id": "b658bf337ea2e316",
          "type": "influxdb out",
          "z": "95fce448fdd43b47",
          "influxdb": "2f1c38495035d2e4",
          "name": "Store data in InfluxDB",
          "measurement": "TurbineData",
          "precision": "",
          "retentionPolicy": "",
          "database": "",
          "retentionPolicyV18Flux": "",
          "org": "iot-sitewise-edge",
          "bucket": "WindFarmData",
          "x": 840,
          "y": 340,
          "wires": []
        },
        {
          "id": "9432d39af35b202f",
          "type": "function",
          "z": "95fce448fdd43b47",
          "name": "Translate to InfluxDB payload",
          "func": "let data = msg.payload;\n\nlet timeInSeconds = data.propertyValues[0].timestamp.timeInSeconds;\nlet offsetInNanos = data.propertyValues[0].timestamp.offsetInNanos;\nlet timestampInMilliseconds = (timeInSeconds * 1000) + (offsetInNanos / 1000000);\n\nmsg.payload = [\n    {\n        \"timestamp(milliseconds_since_epoch)\": timestampInMilliseconds,\n        \"value\": data.propertyValues[0].value.doubleValue\n    },\n    {\n        \"name\": data.propertyAlias,\n        \"quality\": data.propertyValues[0].quality\n    }\n]\n\nreturn msg",
          "outputs": 1,
          "timeout": "",
          "noerr": 0,
          "initialize": "",
          "finalize": "",
          "libs": [],
          "x": 560,
          "y": 340,
          "wires": [
            [
              "b658bf337ea2e316"
            ]
          ]
        },
        {
          "id": "b689403d2c80816b",
          "type": "mqtt in",
          "z": "95fce448fdd43b47",
          "name": "Subscribe to MQTT broker",
          "topic": "/Renton/WindFarm/Turbine/WindSpeed",
          "qos": "1",
          "datatype": "auto-detect",
          "broker": "5744207557fa19be",
          "nl": false,
          "rap": true,
          "rh": 0,
          "inputs": 0,
          "x": 290,
          "y": 340,
          "wires": [
            [
              "9432d39af35b202f"
            ]
          ]
        },
        {
          "id": "4f59bed8e829fc35",
          "type": "comment",
          "z": "95fce448fdd43b47",
          "name": "Data Publish Flow",
          "info": "dfgh",
          "x": 270,
          "y": 160,
          "wires": []
        },
        {
          "id": "b218c7fc58c8b6e7",
          "type": "comment",
          "z": "95fce448fdd43b47",
          "name": "Data Retention flow",
          "info": "",
          "x": 270,
          "y": 300,
          "wires": []
        },
        {
          "id": "5744207557fa19be",
          "type": "mqtt-broker",
          "name": "emqx",
          "broker": "emqx",
          "port": "1883",
          "clientid": "",
          "autoConnect": true,
          "usetls": false,
          "protocolVersion": "5",
          "keepalive": 15,
          "cleansession": true,
          "autoUnsubscribe": true,
          "birthTopic": "",
          "birthQos": "0",
          "birthPayload": "",
          "birthMsg": {},
          "closeTopic": "",
          "closePayload": "",
          "closeMsg": {},
          "willTopic": "",
          "willQos": "0",
          "willPayload": "",
          "willMsg": {},
          "userProps": "",
          "sessionExpiry": ""
        },
        {
          "id": "2f1c38495035d2e4",
          "type": "influxdb",
          "hostname": "influxdb",
          "port": 8086,
          "protocol": "http",
          "database": "",
          "name": "InfluxDB",
          "usetls": false,
          "tls": "",
          "influxdbVersion": "2.0",
          "url": "http://influxdb:8086",
          "timeout": "",
          "rejectUnauthorized": false
        }
      ]

  nodered_flows_cred:
    content: |
      {
        "2f1c38495035d2e4": {
          "token": "${INFLUXDB_TOKEN}"
        }
      }

  nodered_settings:
    content: |
      module.exports = {
        flowFile: 'flows.json',
        credentialSecret: false,
        adminAuth: null,
        editorTheme: {
          projects: {
            enabled: false
          }
        }
      }
```

### 更新边 SiteWise 缘部署
<a name="w2aac17c19c19c26c27b7c11"></a>

1. 导航到 [AWS IoT 控制台](https://console.aws.amazon.com/iot/)

1. ****在 “管理” **部分下的左侧导航菜单中选择 Greengrass** 设备，然后选择 “核心设备”。****

1. 选择连接到 SiteWise Edge 网关的核心设备。

1. 选择 “部**署**” 选项卡，然后选择 “部**署 ID**” 值。

1. 选择 “**操作**”，然后选择 “**修订**”。

1. 阅读弹出消息，然后选择 “**修订部署**”。

1. 在**步骤 2-选择组件中**，选择以下组件，然后选择**下一步**。
   + `aws.greengrass.clientdevices.mqtt.EMQX`
   + `aws.iot.SiteWiseEdgePublisher`

1. 在**步骤 3-配置组件**中，选择`aws.greengrass.clientdevices.mqtt.EMQX`组件值并添加以下网络配置：

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "allow"
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               }
           }
       },
       "authMode": "bypass",
       "dockerOptions": "-p 127.0.0.1:1883:1883 --network=SiteWiseEdgeNodeRedDemoNetwork",
       "requiresPrivilege": "true"
   }
   ```

1. 选择**下一步**。

1. 在**步骤 4-配置高级设置中**，选择**下一步**。

1. 选择**部署**

### 启动服务
<a name="linux-docker-launch"></a>

1. 使用 Docker 撰写文件启动服务。在包含该`compose.yaml`文件的目录下运行以下命令。

   ```
   docker compose up -d
   ```

1. 创建 SSH 隧道以访问服务：

   ```
   ssh -i path_to_your_ssh_key -L 1880:127.0.0.1:1880 -L 3000:127.0.0.1:3000 -L 8086:127.0.0.1:8086 username@gateway_ip_address
   ```

此部署在中创建了以下服务`SiteWiseEdgeNodeRedDemoNetwork network`：

**InfluxDB v2（端口 8086）**  
包括预先配置的组织 (iot-sitewise-edge)、 WindFarmData InfluxDB 存储桶和管理员凭证

**Node-red（端口 1880）**  
包括 InfluxDB 节点和用于集成的预配置流程 AWS IoT SiteWise 

**Grafana（端口 3000）**  
包括管理员用户、InfluxDB 数据源和监控控制面板

### 访问服务
<a name="linux-docker-access-services"></a>

部署后，使用以下内容 URLs 和凭据访问服务：

**注意**  
您可以从主机或网关计算机访问每项服务。


**服务访问详情**  

| 服务 | URL | 凭据 | 
| --- | --- | --- | 
| Node-RED | [http://127.0.0.1:1880](http://127.0.0.1:1880) | 无需凭证 | 
| InfluxDB | [http://127.0.0.1:8086](http://127.0.0.1:8086) |  用户名：管理员 密码：\$1INFLUXDB\$1PASSWORD  | 
| Grafana | [http://127.0.0.1:3000](http://127.0.0.1:3000) |  用户名：管理员 密码：\$1GRAFANA\$1PASSWORD  | 

## 验证部署
<a name="linux-docker-verify-deployment"></a>

为确保部署成功，请执行以下检查：

1. 对于 Node-RED，请验证是否存在两个预加载的流：
   + 数据发布流程
   + 数据保留流程

1. 对于 AWS IoT SiteWise，在 AWS IoT SiteWise 控制台中，使用别名确认是否存在数据流`/Renton/WindFarm/Turbine/WindSpeed`。

1. 对于 InfluxDB，使用数据资源管理器验证存储桶内`TurbineData`测量中的数据存储。`WindFarmData`

1. 对于 Grafana，请查看控制面板以确认显示从 Node-RED 生成的时间序列数据。

# 处理开源集成的数据
<a name="open-source-data-processing-open-source"></a>

可以使用不同的工具在不同的阶段处理数据（例如转换或聚合），每种工具都满足不同的监控要求。

## 使用 Node-red 节点处理数据
<a name="open-source-nodered-nodes"></a>

使用 Node-RED® 内置处理节点实时转换数据。通过 Node-RED 控制台配置这些节点以创建您的数据管道。

### 数据转换节点
<a name="open-source-data-transformation-nodes"></a>

使用以下节点变换单个数据点 AWS IoT SiteWise，类似于中的变换：
+ **更改节点**-对数据执行简单的值修改。
+ **函数节点**-为复杂的数据处理启用自定义 JavaScript转换。

### 指标计算节点
<a name="open-source-metrics-calculation-nodes"></a>

使用以下节点，将多个数据点合并成单个输出，类似于中的 AWS IoT SiteWise Metrics：
+ **batch 节点**-将多条消息分组以进行批处理。
+ **join node**-将多个数据流合并为一个输出。
+ **聚合器节点**-计算来自多个数据点的聚合指标。

有关其他节点选项，请参阅 [Node-red 库](https://flows.nodered.org/)。

## 创建 InfluxDB 任务
<a name="open-source-influxdb-tasks"></a>

虽然 Node-RED 擅长通过快速设置进行基本数据处理，但在基于流程的编程中，复杂的度量计算可能会变得具有挑战性。InfluxDB® Tasks 通过计划的 Flux 脚本提供了一种替代方案，以满足高级处理需求。

使用 InfluxDB 任务执行以下操作：
+ 跨大型数据集的统计聚合
+ 对多个属性的数学运算
+ 来自多个来源的测量结果

### 任务功能
<a name="open-source-task-features"></a>
+ **计划执行**-基于 cron 表达式运行任务
+ **Batch** Processing-优化时间序列数据的操作
+ **错误恢复**-自动重试失败的操作
+ **监控**-通过详细日志跟踪执行情况

通过 InfluxDB 用户界面、API 或 CLI 管理任务。有关更多信息，请参阅[使用 InfluxDB 任务处理数据](https://docs.influxdata.com/influxdb/cloud/process-data/)。

## 使用 Grafana 变换
<a name="open-source-grafana-transformations"></a>

在 Grafana® 中转换数据可视化，无需修改 InfluxDB 中的源数据。Grafana 转换仅适用于可视化层。
+ **Visual Builder**-无需编写代码即可创建转换
+ **实时预览**-实时查看转换结果
+ **多源**-处理来自多个数据库源的数据
+ **存储效率高**-在可视化时转换数据，无需存储中间结果

有关更多信息，请参阅[转换数据](https://grafana.com/docs/grafana/latest/panels/transform-data/)。

## 开源集成疑难解答
<a name="open-source-troubleshoot"></a>

有关与 SiteWise Edge 网关开源集成相关的疑难解答主题的更多信息，请参阅[边缘开源集成疑难解答](troubleshooting-gateway.md#open-source-troubleshooting)。