

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

# FreeRTOS 演示
<a name="freertos-next-steps"></a>

FreeRTOS 将一些演示应用程序包含在主 FreeRTOS 目录下的 `demos` 文件夹中。可由 FreeRTOS 执行的所有示例均显示在 `demos` 下的 `common` 文件夹中。对于每个符合 FreeRTOS 条件的平台，`demos` 文件夹下还有一个文件夹。

尝试演示应用程序之前，建议您完成 [开始使用 FreeRTOS](freertos-getting-started.md)中的教程。它会介绍如何设置和运行 coreMQTT 代理演示。

## 运行 FreeRTOS 演示
<a name="running-demos"></a>

以下主题介绍如何设置和运行 FreeRTOS 演示：
+ [低功耗蓝牙演示应用程序](ble-demo.md)
+ [Microchip Curiosity PIC32MZEF 的演示启动加载程序](microchip-bootloader.md)
+ [AWS IoT Device Defender 演示](dd-demo.md)
+ [AWS IoT Greengrass V1 发现演示应用程序](gg-demov1.md)
+ [AWS IoT GreengrassV2](gg-demov2.md)
+ [coreHTTP 演示](core-http-demo.md)
+ [AWS IoT Jobs 库演示](freertos-jobs-demo.md)
+ [coreMQTT 演示](mqtt-demo.md)
+ [Over-the-air 更新演示应用程序](ota-demo.md)
+ [安全套接字 Echo 客户端演示](secure-sockets-demo.md)
+ [AWS IoT Device Shadow 演示应用程序](shadow-demo.md)

`DEMO_RUNNER_RunDemos` 函数位于 `freertos/demos/demo_runner/iot_demo_runner.c` 文件中，用于初始化一个分离的线程，该线程上运行单个演示应用程序。默认情况下，`DEMO_RUNNER_RunDemos` 仅调用和启动 coreMQTT 代理演示。根据您在下载 FreeRTOS 时选择的配置，以及从哪个位置下载 FreeRTOS，其他示例运行程序函数可能会默认启动。要启用演示应用程序，请打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h` 文件，然后定义要运行的演示。

**注意**  
并非所有示例组合在一起都有效。根据组合，由于内存约束，软件可能无法在所选目标上运行。建议您一次运行一个演示。

## 配置演示
<a name="configuring-demos"></a>

为您配置了演示，以便快速开始。您可能希望更改项目的一些配置，以创建在您平台上运行的版本。您可在 `vendors/vendor/boards/board/aws_demos/config_files` 中找到配置文件。

# 低功耗蓝牙演示应用程序
<a name="ble-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 概述
<a name="ble-demo-overview"></a>

FreeRTOS 低功耗蓝牙包括三个演示应用程序：
+ [低功耗蓝牙 MQTT](#ble-demo-mqtt) 演示 

  此应用程序演示如何使用低功耗蓝牙 MQTT 服务。
+ [Wi-Fi 预置](#ble-demo-wifi) 演示

  此应用程序演示如何使用低功耗蓝牙预置服务。
+ [通用属性服务器](#ble-demo-server) 演示

  此应用程序演示如何使用 FreeRTOS 低功耗蓝牙 APIs 中间件来创建简单的 GATT 服务器。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 先决条件
<a name="ble-demo-prereqs"></a>

要按照这些演示练习，您的微控制器需要具备低功耗蓝牙功能。您还需要 [适用于 FreeRTOS 蓝牙设备的 iOS 开发工具包](freertos-ble-mobile.md#freertos-ble-ios) 或 [适用于 FreeRTOS 蓝牙设备的 Android 开发工具包](freertos-ble-mobile.md#freertos-ble-android)。

### 为 FreeRTOS 低功耗蓝牙设置 AWS IoT 和 Amazon Cognito
<a name="set-up-ble-demo-aws"></a>

要通过 MQTT 将您的设备连接到 AWS IoT ，您需要设置 AWS IoT 和 Amazon Cognito。

**要设置 AWS IoT**

1. 在 [https://aws.amazon.com/](https://aws.amazon.com/)上 AWS 开设一个账户。

1. 打开 [AWS IoT 控制台](https://console.aws.amazon.com/iot/)，从导航窗格中，依次选择**管理**和**事物**。

1. 选择**创建**，然后选择**创建单个事物**。

1. 输入您设备的名称，然后选择**下一步**。

1. 如果您通过移动设备将微控制器连接到云中，请选择**创建没有证书的事物**。由于移动设备 SDKs 使用 Amazon Cognito 进行设备身份验证，因此您无需为使用低功耗蓝牙的演示创建设备证书。

   如果您直接通过 Wi-Fi 将微控制器连接到云中，请依次选择**创建证书**和**激活**，然后下载事物的证书、公有密钥和私有密钥。

1. 从已注册事物列表中选择您刚刚创建的事物，然后从事物的页面中选择**交互**。记下 AWS IoT REST API 端点。

有关设置的更多信息，请参阅《[入门》 AWS IoT](https://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html)。

**创建 Amazon Cognito 用户群体**

1. 打开 Amazon Cognito 控制台，然后选择**管理用户群体**。

1. 选择**创建用户池**。

1. 指定用户池名称，然后选择**查看默认值**。

1. 在导航窗格中，选择**应用程序客户端**，然后选择**添加应用程序客户端**。

1. 输入应用程序客户端的名称，然后选择**创建应用程序客户端**。

1. 在导航窗格中，选择 **审核**，然后选择 **创建池**。

   记录在您用户池的**常规设置**页面中显示的池 ID。

1. 在导航窗格中，选择**应用程序客户端**，然后选择**显示详细信息**。记录应用程序客户端 ID 和应用程序客户端密钥。

**创建 Amazon Cognito 身份池**

1. 打开 Amazon Cognito 控制台，然后选择**管理身份池**。

1. 为身份池输入一个名称。

1. 展开**身份验证提供商**，选择 **Cognito** 选项卡，然后输入您的用户池 ID 和应用程序客户端 ID。

1. 选择**创建池**。

1. 展开**查看详细信息**，记下两个 IAM 角色名称。要访问 Amazon Cognito，请选择**允许**，以便为经过身份验证和未经过身份验证的身份创建 IAM 角色。

1. 选择**编辑身份池**。记录身份池 ID。其格式应为 `us-west-2:12345678-1234-1234-1234-123456789012`。

有关设置 Amazon Cognito 的更多信息，请参阅 [Amazon Cognito 入门](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-getting-started.html)。

**创建 IAM policy 并将其附加到经过身份验证的身份**

1. 打开 IAM 控制台，然后在导航窗格中选择**角色**。

1. 查找并选择您的经过身份验证的角色，然后依次选择**附加策略**和**添加内联策略**。

1. 选择 **JSON** 选项卡，然后粘贴以下 JSON：

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement":[
         {
            "Effect":"Allow",
            "Action":[
               "iot:AttachPolicy",
               "iot:AttachPrincipalPolicy",
               "iot:Connect",
               "iot:Publish",
               "iot:Subscribe",
               "iot:Receive",
               "iot:GetThingShadow",
               "iot:UpdateThingShadow",
               "iot:DeleteThingShadow"
            ],
            "Resource":[
               "*"
            ]
         }
      ]
   }
   ```

------

1. 选择**查看策略**，输入策略的名称，然后选择**创建策略**。

请随身携 AWS IoT 带您和亚马逊 Cognito 的信息。您需要端点并使用 AWS 云端 IDs 对您的移动应用程序进行身份验证。

### 为低功耗蓝牙设置 FreeRTOS 环境
<a name="ble-demo-set-up"></a>

要设置环境，您需要在微控制器下载包含[低功耗蓝牙库](freertos-ble-library.md) 的 FreeRTOS，并在移动设备上下载和配置适用于 FreeRTOS 蓝牙设备的移动开发工具包。

**在微控制器环境中设置 FreeRTOS 低功耗蓝牙**

1. 从中下载或克隆 FreeRTOS。[GitHub](https://github.com/aws/amazon-freertos)有关说明，请参阅 [README.md](https://github.com/aws/amazon-freertos/blob/main/README.md) 文件。

1. 在微控制器上设置 FreeRTOS。

   有关在符合 FreeRTOS 条件的微控制器上开始使用 FreeRTOS 的信息，请参阅 [FreeRTOS 入门](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-getting-started.html)中有关您主板的指南。
**注意**  
您可在任何已启用低功耗蓝牙且具有 FreeRTOS 和移植的 FreeRTOS 低功耗蓝牙库的微控制器上运行演示。目前，FreeRTOS [低功耗蓝牙 MQTT](#ble-demo-mqtt) 演示项目已完全移植到以下启用低功耗蓝牙的设备：  
[Espressif ESP32-DevKit C 和 the ESP-WROVER-KIT](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html)
[Nordic n RF52840-DK](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_nordic.html)

## 常见组件
<a name="ble-demo-common"></a>

FreeRTOS 演示应用程序有两个常见组件：
+ Network Manager
+ 低功耗蓝牙移动开发工具包演示应用程序

### Network Manager
<a name="ble-demo-network-manager"></a>

网络管理器管理微控制器的网络连接。它位于您的 FreeRTOS 目录中，路径为：`demos/network_manager/aws_iot_network_manager.c`。如果为 Wi-Fi 和低功耗蓝牙均启用了网络管理器，则默认情况下通过低功耗蓝牙启动演示。如果低功耗蓝牙连接中断，而您的主板已中断 Wi-Fi-enabled，则网络管理器会切换到可用的 Wi-Fi 连接，以防止您断开与网络的连接。

要在 Network Manager 中启用网络连接类型，请将网络连接类型添加到中的`configENABLED_NETWORKS`参数中`vendors/vendor/boards/board/aws_demos/config_files/aws_iot_network_config.h`（其中，*board*是供应商名称，是您用于运行演示的主板的名称）。*vendor*

例如，如果您同时启用了低功耗蓝牙和 Wi-Fi，则 `aws_iot_network_config.h` 中以 `#define configENABLED_NETWORKS` 开头的一行应如下所示：

```
#define  configENABLED_NETWORKS  ( AWSIOT_NETWORK_TYPE_BLE | AWSIOT_NETWORK_TYPE_WIFI )
```

要获取当前支持的网络连接类型列表，请查看 `aws_iot_network.h` 中以 `#define AWSIOT_NETWORK_TYPE` 开头的行。

### FreeRTOS 低功耗蓝牙移动开发工具包演示应用程序
<a name="ble-sdk-app"></a>

FreeRTOS 低功耗蓝牙移动 SDK 演示应用程序位于 FreeRTOS 蓝牙设备的 Android [SDK 下，FreeRTOS 蓝牙](https://github.com/aws/amazon-freertos-ble-android-sdk)设备`amazon-freertos-ble-android-sdk/app`的 [iOS](https://github.com/aws/amazon-freertos-ble-ios-sdk) SDK 位于 GitHub 下方。`amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo`在本示例中，我们使用 iOS 版本的演示移动应用程序的屏幕截图。

**注意**  
如果您使用的是 iOS 设备，则需要 Xcode 来构建演示移动应用程序。如果您使用的是 Android 设备，则可使用 Android Studio 来构建演示移动应用程序。

**配置 iOS 开发工具包演示应用程序**

当您定义配置变量时，使用在配置文件中提供的占位符值的格式。

1. 确认已安装 [适用于 FreeRTOS 蓝牙设备的 iOS 开发工具包](freertos-ble-mobile.md#freertos-ble-ios)。

1. 从 `amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo/` 发布以下命令：

   ```
   $ pod install
   ```

1. 打开具有 Xcode 的 `amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo/AmazonFreeRTOSDemo.xcworkspace` 项目，将签名开发人员账户更改为您的账户。

1. 在您所在的地区创建 AWS IoT 政策（如果您还没有）。
**注意**  
此策略不同于为经过 Amazon Cognito 身份验证的身份创建的 IAM policy。

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

   1. 在导航窗格中依次选择**安全**、**策略**和**创建**。输入用于标识您的策略的名称。在**添加语句**部分中，选择**高级模式**。将以下 JSON 复制并粘贴到策略编辑器窗口中。*aws-account*用您的 AWS 地区*aws-region*和账户 ID 替换和。

   1. 选择**创建**。

1. 打开 `amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo/AmazonFreeRTOSDemo/Amazon/AmazonConstants.swift` 并重新定义以下变量：
   + `region`: 您所在 AWS 的地区。
   + `iotPolicyName`: 您的 AWS IoT 保单名称。
   + `mqttCustomTopic`：您要发布到的 MQTT 主题。

1. 打开 `amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo/AmazonFreeRTOSDemo/Support/awsconfiguration.json`。

   在 `CognitoIdentity` 下，重新定义以下变量：
   + `PoolId`：您的 Amazon Cognito 身份池 ID。
   + `Region`: 您所在 AWS 的地区。

   在 `CognitoUserPool` 下，重新定义以下变量：
   + `PoolId`：您的 Amazon Cognito 用户群体 ID。
   + `AppClientId`：您的应用程序客户端 ID。
   + `AppClientSecret`：您的应用程序客户端密钥。
   + `Region`: 您所在 AWS 的地区。

**配置 Android 开发工具包演示应用程序**

当您定义配置变量时，使用在配置文件中提供的占位符值的格式。

1. 确认已安装 [适用于 FreeRTOS 蓝牙设备的 Android 开发工具包](freertos-ble-mobile.md#freertos-ble-android)。

1. 在您所在的地区创建 AWS IoT 政策（如果您还没有）。
**注意**  
此策略不同于为经过 Amazon Cognito 身份验证的身份创建的 IAM policy。

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

   1. 在导航窗格中依次选择**安全**、**策略**和**创建**。输入用于标识您的策略的名称。在**添加语句**部分中，选择**高级模式**。将以下 JSON 复制并粘贴到策略编辑器窗口中。*aws-account*用您的 AWS 地区*aws-region*和账户 ID 替换和。

   1. 选择**创建**。

1. 打开 [ https://github.com/aws/amazon-freertos-ble-android-sdk/blob/master/app/src/main/java/software/amazon/freertos/demo/DemoConstants .java](https://github.com/aws/amazon-freertos-ble-android-sdk/blob/master/app/src/main/java/software/amazon/freertos/demo/DemoConstants.java) 并重新定义以下变量：
   + `AWS_IOT_POLICY_NAME`: 您的 AWS IoT 保单名称。
   + `AWS_IOT_REGION`: 您所在 AWS 的地区。

1. 打开 [ https://github.com/aws/amazon-freertos-ble-android-sdk/blob/master/app/src/main/res/raw/awsconfiguration .json。](https://github.com/aws/amazon-freertos-ble-android-sdk/blob/master/app/src/main/res/raw/awsconfiguration.json)

   在 `CognitoIdentity` 下，重新定义以下变量：
   + `PoolId`：您的 Amazon Cognito 身份池 ID。
   + `Region`: 您所在 AWS 的地区。

   在 `CognitoUserPool` 下，重新定义以下变量：
   + `PoolId`：您的 Amazon Cognito 用户群体 ID。
   + `AppClientId`：您的应用程序客户端 ID。
   + `AppClientSecret`：您的应用程序客户端密钥。
   + `Region`: 您所在 AWS 的地区。

**通过低功耗蓝牙发现微控制器并建立安全连接**

1. 为了将您的微控制器和移动设备安全配对（步骤 6），您需要一个同时具有输入和输出功能的串行终端仿真器（例如 TeraTerm）。将终端配置为通过串行连接来连接到主板，如[安装终端仿真器](gsg-troubleshooting.md#uart-term)中所述。

1. 在您的微控制器上运行低功耗蓝牙演示项目。

1. 在移动设备上运行低功耗蓝牙移动开发工具包演示应用程序。

   要在 Android 开发工具包中从命令行启动演示应用程序，请运行以下命令：

   ```
   $ ./gradlew installDebug
   ```

1. 确认您的微控制器显示在低功耗蓝牙移动开发工具包演示应用程序的 **Devices (设备)** 下。  
![\[显示设备及其唯一标识符的 ESP32 设备管理页面。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list1.png)
**注意**  
处于范围内的所有具有 FreeRTOS 的设备以及设备信息服务 (`freertos/.../device_information`) 均会显示在列表中。

1. 从设备列表中选择您的微控制器。应用程序与主板建立连接，在已连接设备的旁边会显示一根绿色线条。  
![\[ESP32 显示了设备 ID。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list2.png)

   您可以通过将线条拖动到左侧，从微控制器上断开连接。  
![\[显示设备 ID 和另一个 ESP32 设备 ID 的设备页面。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list3.png)

1. 如果出现提示，请将您的微控制器和移动设备进行配对。  
![\[控制台输出，展示了 BLE 设备断开连接、MQTT 服务断开连接、广告启动、与远程设备的 BLE 连接以及数字比较提示。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/pairing-board.png)  
![\[设备 “” ESP32 的蓝牙配对请求对话框显示代码 “465520”，需要在 “” 上进行确认。ESP32\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/pairing-mobile.png)

   如果两个设备上用于比较数字的代码相同，则配对这两个设备。

**注意**  
低功耗蓝牙移动开发工具包演示应用程序使用 Amazon Cognito 进行用户身份验证。确保您已设置 Amazon Cognito 用户和身份池，并且将 IAM policy 附加到了通过身份验证的身份。

## 低功耗蓝牙 MQTT
<a name="ble-demo-mqtt"></a>

在 MQTT 低功耗蓝牙演示中，您的微控制器通过 MQTT 代理向 AWS 云端发布消息。

**订阅演示 MQTT 主题**

1. 登录 AWS IoT 控制台。

1. 在导航窗格中选择**测试**，然后选择 **MQTT 测试客户端**，以便打开 MQTT 客户端。

1. 在 **Subscription topic (订阅主题)**中，输入 ***thing-name*/example/topic1**，然后选择 **Subscribe to topic (订阅主题)**。

如果您使用低功耗蓝牙将微控制器与移动设备配对，则通过您移动设备上的低功耗蓝牙移动开发工具包演示应用程序来路由 MQTT 消息。

**通过低功耗蓝牙启用演示**

1. 打开 `vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h` 并定义 `CONFIG_MQTT_BLE_TRANSPORT_DEMO_ENABLED`。

1. 打开`demos/include/aws_clientcredential.h`，然后`clientcredentialMQTT_BROKER_ENDPOINT`使用 AWS IoT 代理端点进行配置。使用 BLE 微控制器设备的事物名称配置 `clientcredentialIOT_THING_NAME`。 AWS IoT 代理端点可以通过在 AWS IoT 控制台左侧导航窗格中选择 **“设置**” 获取，也可以通过 CLI 运行命令获取：`aws iot describe-endpoint --endpoint-type=iot:Data-ATS`。
**注意**  
 AWS IoT 代理端点和事物名称必须位于配置 cognito 身份和用户池的同一区域。

**运行演示**

1. 在微控制器上生成并运行演示项目。

1. 确保您已使用 [FreeRTOS 低功耗蓝牙移动开发工具包演示应用程序](#ble-sdk-app)将主板与移动设备配对。

1. 从演示移动应用程序的 **Devices (设备)** 列表中，选择您的微控制器，然后选择 **MQTT Proxy (MQTT 代理)** 以打开 MQTT 代理设置。  
![\[三 ESP32 台设备清单，下面有 MQTT 代理 IDs、Network Config 和 Custom GATT MQTT 选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list4.png)

1. 在启用 MQTT 代理之后，MQTT 消息将显示在 `thing-name/example/topic1` 主题上，并且数据将输出到 UART 终端。

## Wi-Fi 预置
<a name="ble-demo-wifi"></a>

Wi-Fi 预置是一项 FreeRTOS 低功耗蓝牙服务，让您可以安全地将 Wi-Fi 网络凭证通过低功耗蓝牙从移动设备发送到微控制器。Wi-Fi 预置服务的源代码位于 `freertos/.../wifi_provisioning`。

**注意**  
Espressi ESP32 f-C 目前支持 Wi-Fi 配置演示 DevKit

**启用演示**

1. 启用 Wi-Fi 预置服务。打开`vendors/vendor/boards/board/aws_demos/config_files/iot_ble_config.h`，然后设置`#define IOT_BLE_ENABLE_WIFI_PROVISIONING`为`1`（其中*vendor*是供应商的名称，*board*是您用来运行演示的主板的名称）。
**注意**  
默认情况下禁用 Wi-Fi 预置服务。

1. 配置 [Network Manager](#ble-demo-network-manager) 以启用低功耗蓝牙和 Wi-Fi。

**运行演示**

1. 在微控制器上生成并运行演示项目。

1. 确保您已使用 [FreeRTOS 低功耗蓝牙移动开发工具包演示应用程序](#ble-sdk-app)将微控制器与移动设备配对。

1. 从演示移动应用程序的 **Devices (设备)** 列表中，选择您的微控制器，然后选择 **Network Config (网络配置)** 以打开网络配置设置。  
![\[三 ESP32 台设备清单，下面有 MQTT 代理 IDs、Network Config 和 Custom GATT MQTT 选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list4.png)

1. 在为主板选择 **Network Config (网络配置)** 之后，微控制器会将附近的网络列表发送到移动设备。可用 Wi-Fi 网络显示在 **Scanned Networks (扫描到的网络)** 下的列表中。  
![\[ESP32 设备管理界面显示未保存的网络，两个已扫描的开放Wi-Fi网络，一个 WPA2 安全性和 RSSI 为 -29，另一个具有开放安全性，RSSI 为 -50。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-network-config1.png)

   从 **Scanned Networks (扫描到的网络)** 列表中选择网络，然后输入 SSID 和密码（如果需要）。  
![\[Wi-Fi 网络密码输入对话框，其中包含空的密码字段、“取消”按钮和“保存”按钮。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-wifi-password.png)

   该微控制器连接到网络并保存网络信息。网络显示在 **Saved Networks (已保存网络)** 下。  
![\[网络界面显示已保存和扫描的 WiFi 网络，一个由网络保护 WPA2，另一个处于打开状态，并带有信号强度指示器。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-network-config2.png)

您可以在演示移动应用程序中保存多个网络。在您重新启动应用程序和演示时，微控制器会连接到 **Saved Networks (已保存网络)** 列表中自上而下的第一个可用的已保存网络。

要更改网络优先级顺序或者删除网络，请在 **Network Configuration (网络配置)** 页面上选择 **Editing Mode (编辑模式)**。要更改网络优先级顺序，请选择您要重排优先级的网络的右侧，然后向上或向下拖动网络。要删除网络，请选择待删除网络左侧的红色按钮。

![\[Wifi 网络设置屏幕，展示了已保存的网络、用于删除或更改优先级的编辑选项以及扫描到的网络。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-network-editing.png)


## 通用属性服务器
<a name="ble-demo-server"></a>

在本示例中，您的微控制器上的演示通用属性 (GATT) 服务器应用程序发送简单的计数值到 [FreeRTOS 低功耗蓝牙移动开发工具包演示应用程序](#ble-sdk-app)。

使用低功耗蓝牙手机 SDKs，您可以为移动设备创建自己的 GATT 客户端，该客户端通过微控制器连接到 GATT 服务器，并与演示移动应用程序并行运行。

**启用演示**

1. 启用低功耗蓝牙 GATT 演示。在`vendors/vendor/boards/board/aws_demos/config_files/iot_ble_config.h`（其中*vendor*是供应商的名称，*board*是您用来运行演示的主板的名称）中，添加`#define IOT_BLE_ADD_CUSTOM_SERVICES ( 1 )`到 define 语句列表中。
**注意**  
低功耗蓝牙 GATT 演示在默认情况下处于禁用状态。

1. 打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_BLE_GATT_SERVER_DEMO_ENABLED`。

**运行演示**

1. 在微控制器上生成并运行演示项目。

1. 确保您已使用 [FreeRTOS 低功耗蓝牙移动开发工具包演示应用程序](#ble-sdk-app)将主板与移动设备配对。

1. 从应用程序的 **Devices (设备)** 列表中，选择您的主板，然后选择 **MQTT Proxy (MQTT 代理)** 以打开 MQTT 代理选项。  
![\[三 ESP32 台设备清单，下面有 MQTT 代理 IDs、Network Config 和 Custom GATT MQTT 选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/ble-device-list4.png)

1. 返回到 **Devices (设备)** 列表，选择您的主板，然后选择 **Custom GATT MQTT (自定义 GATT MQTT)** 以打开自定义 GATT 服务选项。

1. 选择 **Start Counter (启动计数器)** 以开始将数据发布到 ***your-thing-name*/example/topic** MQTT 主题。

   在启用 MQTT 代理之后，Hello World 和递增计数消息将显示在 `your-thing-name/example/topic` 主题上。

# Microchip Curiosity PIC32MZEF 的演示启动加载程序
<a name="microchip-bootloader"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

**注意**  
经 Microchip 同意，我们将从 FreeRTOS 参考集成存储库主分支中移除 Curiosity PIC32MZEF (DM320104)，并且在新版本中将不再使用包含此开发主板。Microchip 已发布[官方通知](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/DM320104)，建议不要继续在新设计中使用 PIC32MZEF (DM320104)。PIC32MZEF 项目和源代码仍然可以通过之前的版本标签进行访问。Microchip 建议客户使用 Curiosity [ PIC32MZ-EF-2.0 开发主板 (DM320209)](https://devices.amazonaws.com/detail/a3G0h0000077I69EAE/Curiosity-PIC32MZ-EF-2-0-Development-Board) 进行新设计。PIC32MZv1 平台仍然可以在 FreeRTOS 参考集成存储库的 [v202012.00](https://github.com/aws/amazon-freertos/tree/202012.00) 中找到。但是，FreeRTOS 参考的 [v202107.00](https://github.com/aws/amazon-freertos/tree/202107.00) 不再支持该平台。

 此演示启动加载程序实施固件版本检查、加密签名验证和应用程序自我测试。这些功能支持适用于 FreeRTOS 的空中下载 (OTA) 固件更新。

固件验证包括验证无线接收的新固件的真实性和完整性。在启动之前，启动加载程序验证应用程序的加密签名。该演示在 SHA-256 之上使用了椭圆曲线数字签名算法 (ECDSA)。提供的实用程序可用于生成签名的应用程序，该应用程序可刷写设备。

启动加载程序支持 OTA 需要的以下功能：
+ 在设备上维护应用程序映像，并在这些映像之间切换。
+ 允许对收到的 OTA 映像执行自行测试并在出现故障时回退。
+ 检查 OTA 更新映像的签名和版本。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 启动加载程序状态
<a name="bootloader-states"></a>

以下状态机中显示启动加载程序进程。

![\[启动引导加载程序状态机，展示了初始化、验证、执行状态和带有“通知错误”选项的错误状态。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/bootloader-states.png)


下表介绍了启动加载程序状态。


| 启动加载程序状态 | 描述 | 
| --- | --- | 
|  初始化  |  启动加载程序处于初始化状态。  | 
|  验证  |  启动加载程序正在验证设备上存在的映像。  | 
|  执行映像  |  启动加载程序正在启动所选映像。  | 
|  执行默认映像  |  启动加载程序正在启动默认映像。  | 
|  错误  |  启动加载程序处于出错状态。  | 

在前面的示意图中，`Execute Image` 和 `Execute Default` 都显示为 `Execution` 状态。

**启动加载程序执行状态**  
启动加载程序处于 `Execution` 状态，已准备好启动经过验证的选定映像。如果要启动的映像位于较高的库中，则在执行映像之前交换库，因为应用程序始终针对较低的库生成。

**启动加载程序默认执行状态**  
如果启动默认映像的配置选项已启用，则启动加载程序将从默认执行地址启动应用程序。除了在调试期间，否则应禁用此选项。

**启动加载程序出错状态**  
启动加载程序处于出错状态，设备上没有有效的映像。启动加载程序必须通知用户。默认实施发送日志消息到控制台，并无限期快速闪烁主板上的 LED。

## 闪存设备
<a name="flash-device"></a>

Microchip Curiosity PIC32MZEF 平台包含 2 MB 的内部程序闪存，划分为两个库。它支持这两个库之间的内存交换映射和实时更新。演示启动加载程序在单独的较低引导闪存区域中编程。

![\[内存布局图，展示了分别映射到引导加载程序、应用程序库 0 和应用程序库 1 的低位引导闪存区域、1 MB 的低位程序闪存区域和 2 MB 区域的高位程序闪存区域。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/flash-device.png)


## 应用程序映像结构
<a name="application-image-structure"></a>

![\[OTA 映像结构，展示了标头、描述符、应用程序二进制文件（由签署者服务签署），以及带有幻码、序列号、起始和结束地址、执行地址、硬件 ID 等字段的后缀部分。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/application-image-structure.png)


该图显示存储在设备的各个库中应用程序映像的主要组件。


| 组件 | 大小（字节） | 
| --- | --- | 
|  映像标头  |  8 字节  | 
|  映像描述符  |  24 字节  | 
|  应用程序二进制文件  |   < 1 MB - (324)  | 
|  Trailer  |  292 字节  | 

## 映像标头
<a name="image-header"></a>

设备上的应用程序映像必须以由幻码和映像标志组成的标头为开头。


| 标头字段 | 大小（字节） | 
| --- | --- | 
|  幻码  |  7 字节  | 
|  映像标志  |  1 字节  | 

### 幻码
<a name="magic-code"></a>

闪存设备上的映像必须以幻码开头。默认幻码为 `@AFRTOS`。启动加载程序在启动映像之前检查是否存在有效的幻码。这是验证的第一步。

### 映像标志
<a name="image-flags"></a>

映像标志用于存储应用程序映像的状态。标志在 OTA 过程中使用。两个库的映像标志确定了设备的状态。如果正在执行的映像标记为等待提交，这意味着设备处于 OTA 自我测试阶段。即使设备上的映像标记为有效，在每次启动时也会经过相同的验证步骤。如果某个映像被标记为新的，则启动加载程序会将其标记为等待提交，并在验证之后启动它进行自我测试。引导加载程序还会初始化并启动监视程序计时器，以便在新的 OTA 映像自我测试失败时重启设备，此时引导加载程序擦除无效映像来拒绝该映像，并执行之前有效的映像。

设备只能有一个有效的映像。其他映像可以是新 OTA 映像或等待提交（自我测试）。OTA 更新成功后，将从设备上擦除旧映像。


| 状态 | 值 | 描述 | 
| --- | --- | --- | 
|  新映像  |  0xFF  |  应用程序映像是新的，从未执行。  | 
|  等待提交  |  0xFE  |  标记应用程序映像供测试执行。  | 
|  有效  |  0xFC  |  应用程序映像标记为有效且已提交。  | 
|  无效  |  0xF8  |  应用程序映像标记为无效。  | 

## 映像描述符
<a name="image-descriptor"></a>

闪存设备上的应用程序映像必须在映像标头之后包含映像描述符。映像描述符由构建后实用工具生成，该实用工具使用配置文件 (`ota-descriptor.config`) 生成相应的描述符并添加到应用程序二进制文件前面。此构建后步骤的输出是可用于 OTA 的二进制映像。


| 描述符字段 | 大小（字节） | 
| --- | --- | 
|  序列号  |  4 字节  | 
|  开始地址  |  4 字节  | 
|  结束地址  |  4 字节  | 
|  执行地址  |  4 字节  | 
|  硬件 ID  |  4 字节  | 
|  预留  |  4 字节  | 

**序列号**  
序列号必须在生成新 OTA 映像之前递增。请参阅 `ota-descriptor.config` 文件。启动加载程序使用此编号来确定要启动的映像。有效值介于 1 到 4294967295 之间。

**开始地址**  
设备上应用程序映像的开始地址。由于映像描述符附加到应用程序二进制文件的前面，此地址是映像描述符的开头。

**结束地址**  
设备上应用程序映像的结束地址，不包括映像的后缀部分。

**执行地址**  
映像的执行地址。

**硬件 ID**  
启动加载程序用于验证为正确的平台生成了 OTA 映像的唯一硬件 ID。

**预留**  
此项保留供将来使用。

## 映像后缀
<a name="image-trailer"></a>

映像后缀附加到应用程序二进制文件。其中包含签名类型字符串、签名大小和映像的签名。


| 后缀字段 | 大小（字节） | 
| --- | --- | 
|  签名类型  |  32 字节  | 
|  签名大小  |  4 字节  | 
|  Signature  |  256 字节  | 

**签名类型**  
签名类型是一个字符串，表示使用的加密算法，并用作后缀的标记。启动加载程序支持椭圆曲线数字签名算法 (ECDSA)。默认值为 sig-sha256-ecdsa。

**签名大小**  
加密签名的大小，以字节为单位。

**Signature**  
随映像描述符一起附加的应用程序二进制文件加密签名。

## 启动加载程序配置
<a name="bootloader-configuration"></a>

基本启动加载程序配置选项在 `freertos/vendors/microchip/boards/curiosity_pic32mzef/bootloader/config_files/aws_boot_config.h` 中提供。一些选项仅提供用于调试目的。

**启用默认启动**  
从默认地址启用应用程序的执行，并且只能为调试启用。映像从默认地址执行而不经过任何验证。

**启用加密签名验证**  
在启动时启用加密签名验证。失败的映像从设备中擦除。此选项仅提供用于调试用途，并且必须在生产中保持启用。

**擦除无效映像**  
如果库上的映像验证失败，则启用该库的完整擦除。此选项仅提供用于调试，并且必须在生产中保持启用。

**启用硬件 ID 验证**  
对在 OTA 映像描述符中的硬件 ID 以及在启动加载程序内编程的硬件 ID 启用验证。此项可选，如果无需硬件 ID 验证，则可以禁用。

**启用地址验证**  
在 OTA 映像的描述符中启用开始地址、结束地址和执行地址的验证。建议您保持启用此选项。

## 构建启动加载程序
<a name="building-bootloader"></a>

该演示引导加载程序作为可加载项目，包含在位于 FreeRTOS 源代码存储库的 `freertos/vendors/microchip/boards/curiosity_pic32mzef/aws_demos/mplab/` 中的 `aws_demos` 项目中。生成 `aws_demos` 项目时，它先生成引导加载程序，然后生成应用程序。最终输出是一个统一的十六进制映像，包括启动加载程序和应用程序。提供 `factory_image_generator.py` 实用程序用于生成具有加密签名的统一十六进制映像。启动加载程序实用程序脚本位于 `freertos/demos/ota/bootloader/utility/` 中。

### 启动加载程序构建前步骤
<a name="bootloader-pre-build"></a>

此构建前步骤执行名为 `codesigner_cert_utility.py` 的实用工具脚本，该脚本从代码签名证书中提取公有密钥，并生成包含采用抽象语法表示法 1 (ASN.1) 编码格式公有密钥的 C 标头文件。此标头编译到启动加载程序项目中。生成的标头包含两个常量：公有密钥以及密钥长度的数组。也可以不带 `aws_demos` 生成启动加载程序项目，并作为普通应用程序进行调试。

# AWS IoT Device Defender 演示
<a name="dd-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="dd-demo-introduction"></a>

此演示展示了如何使用 AWS IoT Device Defender 库连接 [AWS IoT Device Defender](https://docs.aws.amazon.com/iot/latest/developerguide/device-defender.html)。此演示使用 coreMQTT 库通过 TLS（双向身份验证）建立与 AWS IoT Device Defender MQTT 代理和 coreJSON 库的 MQTT 连接，以便验证和解析从 AWS IoT 服务收到的响应。此演示展示了如何使用从设备收集的指标来构造 JSON 格式的报告，以及如何将构造的报告提交给 AWS IoT Device Defender 服务。此演示还展示了如何在 coreMQTT 库中注册回调函数，以便处理来自 AWS IoT Device Defender 服务的响应，从而确认是接受还是拒绝了已发送的报告。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 功能
<a name="dd-demo-functionality"></a>

此演示会创建一个应用程序任务，演示如何收集指标、构造 JSON 格式的 Device Defender 报告，以及如何通过与 AWS IoT MQTT 代理的安全 MQTT 连接将其提交给 AWS IoT Device Defender 服务。此演示包括标准网络指标和自定义指标。对于自定义指标，此演示包括：
+ 一个名为“`task_numbers`”的指标，它是 FreeRTOS 任务 ID 的列表。该指标的类型是“数字列表”。
+ 一个名为“`stack_high_water_mark`”的指标，它是演示应用程序任务的堆栈高级别水印。该指标的类型是“数字”。

我们如何收集网络指标取决于所使用的 TCP/IP 堆栈。对于 Freertos\$1TCP 和支持的 LWIP 配置，我们提供了指标收集实现，可用于从设备收集真实指标并在 AWS IoT Device Defender 报告中提交。您可以在 GitHub 上找到 [Freertos\$1TCP](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/metrics_collector/freertos_plus_tcp/metrics_collector.c) 和 [lwIP](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/metrics_collector/lwip/metrics_collector.c) 的实现。

对于使用任何其他 TCP/IP 堆栈的主板，我们提供了指标收集函数的存根定义，这些函数会为所有网络指标返回零。在 `freertos/demos/device_defender_for_aws/metrics_collector/stub/metrics_collector.c` 中为网络实现函数以发送真实指标。该文件也可在 [GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/metrics_collector/stub/metrics_collector.c) 网站上找到。

对于 ESP32，默认 lwIP 配置不使用核心锁定，因此演示将使用存根指标。如果要使用参考 lwIP 指标收集实现，请在 `lwiopts.h` 中定义以下宏：

```
#define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 0
#define LWIP_TCPIP_CORE_LOCKING         1
#define LWIP_STATS                      1
#define MIB2_STATS                      1
```

下面是运行演示时的一个输出示例。

![\[控制台日志输出，展示了针对 DemoThing 应用程序的 MQTT 连接、发布和内存使用事件。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/Defender_p4_supported.png)


如果您的主板未使用 FreeRTOS\$1TCP 或支持的 lwIP 配置，则输出将如下所示。

![\[日志消息，展示了针对演示应用程序的 MQTT 连接建立、主题订阅尝试、发布有效负载和数据包处理。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/Defender_p4_unsupported.png)


该演示的源代码位于您的下载目录 `freertos/demos/device_defender_for_aws/` 中或 [GitHub](https://github.com/aws/amazon-freertos/tree/main/demos/device_defender_for_aws) 网站上。

### 订阅 AWS IoT Device Defender 主题
<a name="dd-demo-subscribing"></a>

[subscribeToDefenderTopics](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/defender_demo.c#L514-L530) 函数订阅 MQTT 主题，从而收到对已发布的 Device Defender 报告的响应。它使用宏 `DEFENDER_API_JSON_ACCEPTED` 来构造主题字符串，根据该字符串接收接受的 Device Defender 报告的响应。它使用宏 `DEFENDER_API_JSON_REJECTED` 来构造主题字符串，根据该字符串接收拒绝的 Device Defender 报告的响应。

### 收集设备指标
<a name="dd-demo-collecting-metrics"></a>

[collectDeviceMetrics](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/defender_demo.c#L376-L511) 函数使用在 `metrics_collector.h` 中定义的函数收集网络指标。收集的指标包括发送和接收的字节数和数据包数、开放的 TCP 端口数、开放的 UDP 端口数以及建立的 TCP 连接数。

### 生成 AWS IoT Device Defender 报告
<a name="dd-demo-generating-report"></a>

[generateDeviceMetricsReport](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/defender_demo.c#L552-L581) 函数使用在 `report_builder.h` 中定义的函数生成 Device Defender 报告。该函数用于获取网络指标和缓冲区，按照 AWS IoT Device Defender 预期的格式创建一个 JSON 文档，然后将其写入提供的缓冲区。AWS IoT Device Defender 期望的 JSON 文档的格式在《AWS IoT 开发人员指南》的[设备端指标](https://docs.aws.amazon.com/iot/latest/developerguide/detect-device-side-metrics.html)中指定。**

### 发布 AWS IoT Device Defender 报告
<a name="dd-demo-publishing-report"></a>

AWS IoT Device Defender 报告以 MQTT 主题发布，用于发布 JSON AWS IoT Device Defender 报告。该报告是使用宏 `DEFENDER_API_JSON_PUBLISH` 构造，如 GitHub 网站上的此[代码片段](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/defender_demo.c#L691-L695)所示。

### 处理回复的回调
<a name="dd-demo-callback-handling"></a>

[publishCallback](https://github.com/aws/amazon-freertos/blob/main/demos/device_defender_for_aws/defender_demo.c#L302-L373) 函数处理传入的 MQTT 发布消息。它使用 AWS IoT Device Defender 库中的 `Defender_MatchTopic` API 来检查传入的 MQTT 消息是否来自 AWS IoT Device Defender 服务。如果消息来自 AWS IoT Device Defender 服务，则会解析收到的 JSON 响应并在响应中提取报告 ID。然后验证报告 ID 是否与报告中发送的 ID 相同。

# AWS IoT Greengrass V1 发现演示应用程序
<a name="gg-demov1"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

为 FreeRTOS 运行 AWS IoT Greengrass Discovery 演示之前，您需要设置 AWS、AWS IoT Greengrass 和 AWS IoT。要设置 AWS，请遵循 [设置您的AWS账户和权限](freertos-prereqs.md#freertos-account-and-permissions) 中的说明。要设置 AWS IoT Greengrass，您需要创建一个 Greengrass 组，然后添加一个 Greengrass 核心。有关设置 AWS IoT Greengrass 的更多信息，请参阅 [AWS IoT Greengrass 入门](https://docs.aws.amazon.com/greengrass/latest/developerguide/gg-gs.html)。

设置 AWS 和 AWS IoT Greengrass 之后，您需要为 AWS IoT Greengrass 配置一些其他权限。

**设置 AWS IoT Greengrass 权限**

1. 转到 [IAM 控制台](https://console.aws.amazon.com/iam/home)。

1. 从导航窗格中，选择 **Roles (角色)**，然后查找并选择 **Greengrass\$1ServiceRole**。

1. 选择 **Attach policies (附加策略)**，选择 **AmazonS3FullAccess** 和 **AWSIoTFullAccess**，然后选择 **Attach policy (附加策略)**。

1. 浏览至 [AWS IoT 控制台](https://console.aws.amazon.com/iotv2/)。

1. 在导航窗格中，选择 **Greengrass**，选择 **Groups (组)**，然后选择之前创建的 Greengrass 组。

1. 选择 **Settings (设置)**，然后选择 **Add role (添加角色)**。

1. 选择 **Greengrass\$1ServiceRole**，然后选择 **Save (保存)**。

将主板连接到 AWS IoT 并配置 FreeRTOS 演示。

1. [注册您的 MCU 主板 AWS IoT](freertos-prereqs.md#get-started-freertos-thing)

   注册主板后，您需要创建新的 Greengrass 策略并将其附加到设备证书。

**创建新的 AWS IoT Greengrass 策略**

   1. 浏览至 [AWS IoT 控制台](https://console.aws.amazon.com/iotv2/)。

   1. 在导航窗格中依次选择**安全**、**策略**和**创建**。

   1. 输入用于标识您的策略的名称。

   1. 在**添加语句**部分中，选择**高级模式**。将以下 JSON 复制并粘贴到策略编辑器窗口中：

      ```
      {
            "Effect": "Allow",
            "Action": [
              "greengrass:*"
            ],
            "Resource": "*"
      }
      ```

      此策略向所有资源授予 AWS IoT Greengrass 权限。

   1. 选择**创建**。

**将 AWS IoT Greengrass 策略附加到设备证书**

   1. 浏览至 [AWS IoT 控制台](https://console.aws.amazon.com/iotv2/)。

   1. 在导航窗格中，选择 **Manage (管理)**，选择 **Things (事物)**，然后选择之前创建的事物。

   1. 选择 **Security (安全性)**，然后选择附加到设备的证书。

   1. 选择 **Policies (策略)**，选择 **Actions (操作)**，然后选择 **Attach Policy (附加策略)**。

   1. 查找并选择之前创建的 Greengrass 策略，然后选择 **Attach (附加)**。

1. [下载 FreeRTOS](freertos-prereqs.md#freertos-download)
**注意**  
如果要从 FreeRTOS 控制台下载 FreeRTOS，请选择**连接到 AWS IoT Greengrass- *平台***，而不是**连接到 AWS IoT- *平台***。

1. [配置 FreeRTOS 演示](freertos-prereqs.md#freertos-configure).

   打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_GREENGRASS_DISCOVERY_DEMO_ENABLED`。

设置 AWS IoT 和 AWS IoT Greengrass 以及下载和配置 FreeRTOS 后，您可以在设备上构建、刷写并运行 Greengrass 演示。要设置主板的硬件和软件开发环境，请遵循[主板特定的入门指南](getting-started-guides.md)中的说明。

该 Greengrass 演示向 Greengrass 核心和 AWS IoT MQTT 客户端发布一系列消息。要查看 AWS IoT MQTT 客户端中的消息，请打开 [AWS IoT 控制台](https://console.aws.amazon.com/iotv2/)，选择**测试**，选择 **MQTT 测试客户端**，然后向 `freertos/demos/ggd` 添加订阅。

在 MQTT 客户端中，您应看到下列字符串：

```
Message from Thing to Greengrass Core: Hello world msg #1!
Message from Thing to Greengrass Core: Hello world msg #0!
Message from Thing to Greengrass Core: Address of Greengrass Core found! 123456789012.us-west-2.compute.amazonaws.com
```

## 使用 Amazon EC2 实例
<a name="gg-demo-ec2"></a>

**在使用 Amazon EC2 实例的情况下**

1. 查找与您的 Amazon EC2 实例关联的公有 DNS (IPv4) — 转至 Amazon EC2 控制台，然后在左侧导航面板中选择**实例**。选择您的 Amazon EC2 实例，然后选择**描述**面板。查找并记下**公有 DNS (IPv4)** 的条目。

1. 查找**安全组**的条目，然后选择附加到您的 Amazon EC2 实例的安全组。

1. 选择**入站规则**选项卡，然后选择**编辑入站规则**并添加以下规则。  
**入站规则**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/gg-demov1.html)

1. 在 AWS IoT 控制台中，选择 **Greengrass**，选择 **组**，然后选择先前创建的 Greengrass 组。选择**设置**。将**本地连接检测**更改为**手动管理连接信息**。

1. 在导航窗格中，选择**核心**，然后选择您的组核心。

1. 选择**连接**，并确保您只有一个核心终端节点（删除其余所有终端节点），并且它不是 IP 地址（因为它可能会发生更改）。最佳选择是使用您在第一步中记下的公有 DNS (IPv4)。

1. 将您创建的 FreeRTOS IoT 物品添加到 GG 组。

   1. 选择返回箭头以返回 AWS IoT Greengrass 组页面。在导航窗格中，选择**设备**，然后选择**添加设备**。

   1. 选择**选择 IoT 物品**。选择您的设备，然后选择**完成**。

1. 添加必要的订阅 — 在 **Greengrass 组**页面上，选择**订阅**，然后选择**添加订阅**并输入信息，如下所示。  
**订阅**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/gg-demov1.html)

   其中“来源”是在注册主板时为 AWS IoT 控制台中创建的 AWS IoT 事务提供的名称，在本示例中为“TIGG1”。

1. 启动 AWS IoT Greengrass 组的部署，并确保该部署成功。现在，您应能够成功运行 AWS IoT Greengrass 发现演示。

# AWS IoT GreengrassV2
<a name="gg-demov2"></a>

## 与 AWS IoT Greengrass V2 设备的兼容性
<a name="ggv2-compatibility"></a>

 AWS IoT Greengrass V2 对客户端设备的支持向后兼容 AWS IoT Greengrass V1。您无需更改应用程序代码即可将 FreeRTOS 客户端设备连接到 V2 核心设备。要使客户端设备能够连接到 V2 核心设备，请执行以下操作。
+  将 Greengrass 软件部署到 Greengrass 核心设备上。请参阅[将客户端设备连接到核心设备](https://docs.aws.amazon.com//greengrass/v2/developerguide/connect-client-devices.html)，从而将设备连接到 AWS IoT Greengrass V2。
+  要在客户端设备、AWS IoT Core 云服务和 Greengrass 组件之间中继消息（包括 Lambda 函数），请部署和配置 [MQTT 桥接组件](https://docs.aws.amazon.com//greengrass/v2/developerguide/mqtt-bridge-component.html)。
+ 部署 [IP 探测器组件](https://docs.aws.amazon.com//greengrass/v2/developerguide/ip-detector-component.html)以自动检测连接信息，或手动管理端点。
+ 有关更多信息，请参阅[与本地 AWS IoT 设备交互](https://docs.aws.amazon.com//greengrass/v2/developerguide/interact-with-local-iot-devices.html)。

有关更多详细信息，请参阅有关[在 AWS IoT Greengrass V2 上运行 AWS IoT Greengrass V1 应用程序AWS](https://docs.aws.amazon.com//greengrass/v2/developerguide/migrate-from-v1.html#connect-v1-greengrass-devices)的文档。

# coreHTTP 演示
<a name="core-http-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

这些演示可以帮助您学习如何使用 coreHTTP 库。

**Topics**
+ [coreHTTP 双向身份验证演示](core-http-ma-demo.md)
+ [coreHTTP 基本 Amazon S3 上传演示](core-http-s3-upload-demo.md)
+ [coreHTTP 基本 S3 下载演示](core-http-s3-download-demo.md)
+ [coreHTTP 基本多线程演示](core-http-bmt-demo.md)

# coreHTTP 双向身份验证演示
<a name="core-http-ma-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="core-http-ma-demo-intro"></a>

coreMQTT（双向身份验证）演示项目展示了如何使用在客户端与服务器之间具有双向身份验证的 TLS 建立与 HTTP 服务器的连接。此演示使用基于 mbedTLS 的传输接口实现来建立经过服务器和客户端身份验证的 TLS 连接，并演示了 HTTP 中的请求响应工作流程。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 功能
<a name="core-http-ma-demo-functionality"></a>

此演示创建一个应用程序任务，其示例演示如何完成以下操作：
+ 连接到 AWS IoT 终端上的 HTTP 服务器。
+ 发送 POST 请求。
+ 接收响应。
+ 断开与服务器的连接。

完成这些步骤后，演示将生成类似于以下屏幕截图的输出。

![\[显示 AWS IoT 演示初始化、TLS 会话建立、HTTP POST 请求和表示成功完成演示的内存指标的日志输出。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/coreHTTP.output.png)


 AWS IoT 控制台生成类似于以下屏幕截图的输出。

![\[AWS IoT 控制台显示世界标准时间 2020 年 11 月 20 日 19:09:09 向某个主题发布的 “来自 AWS IoT 控制台的你好” 消息。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/coreHTTP.console.png)


## 源代码组织
<a name="core-http-s3-ma-demo-source-code-organization"></a>

演示源文件已命名`http_demo_mutual_auth.c`，可以在`freertos/demos/coreHTTP/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_mutual_auth.c)网站上找到。

## 正在连接到 AWS IoT HTTP 服务器
<a name="core-http-ma-demo-connecting"></a>

该[ connectToServerWithBackoffRetries](https://github.com/aws/amazon-freertos/blob/main/demos/common/http_demo_helpers/http_demo_utils.c#L131-L170)函数尝试与 AWS IoT HTTP 服务器建立相互身份验证的 TLS 连接。如果连接失败，则会在超时后重试。超时值呈指数级增长，直到达到最大尝试次数或达到最大超时值。`RetryUtils_BackoffAndSleep` 函数提供指数级增长的超时值，并在达到最大尝试次数时返回 `RetryUtilsRetriesExhausted`。如果在配置的尝试次数后仍无法建立与代理的 TLS 连接，则 `connectToServerWithBackoffRetries` 函数将返回失败状态。

## 发送 HTTP 请求和接收响应
<a name="core-http-ma-demo-send-receive"></a>

[ prvSendHttp请求](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_mutual_auth.c#L402-L507)函数演示如何向 AWS IoT HTTP 服务器发送 POST 请求。有关向 REST API 发出请求的更多信息 AWS IoT，请参阅[设备通信协议-HTTPS](https://docs.aws.amazon.com/iot/latest/developerguide/http.html)。响应是通过相同的 CoreHTTP API 调用 `HTTPClient_Send` 接收。

# coreHTTP 基本 Amazon S3 上传演示
<a name="core-http-s3-upload-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="core-http-s3-upload-demo-intro"></a>

此示例演示如何将 PUT 请求发送到 Amazon Simple Storage Service (Amazon S3) HTTP 服务器以及上传一个小文件。完成上传后，它还会执行 GET 请求来验证文件大小。此示例使用一个[网络传输接口](https://freertos.org/network-interface.html)，该接口使用 mbedTLS 在运行 coreHTTP 的 IoT 设备客户端与 Amazon S3 HTTP 服务器之间建立双向身份验证的连接。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

### 单线程与多线程
<a name="core-http-s3-upload-demo-threads"></a>

coreMQTT 有两种使用模式，即*单线程*和*多线程*（多任务处理）。尽管本节中的演示在线程中运行 HTTP 库，但它实际上演示了如何在单线程环境中使用 coreHTTP。此演示中只有一个任务使用 HTTP API。尽管单线程应用程序必须重复调用 HTTP 库，但多线程应用程序可以在后台的代理（或进程守护程序）任务中发送 HTTP 请求。

## 源代码组织
<a name="core-http-s3-upload-demo-source-code-organization"></a>

演示源文件已命名`http_demo_s3_upload.c`，可以在`freertos/demos/coreHTTP/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_upload.c)网站上找到。

## 配置 Amazon S3 HTTP 服务器连接
<a name="core-http-s3-upload-demo-configure-server"></a>

此演示使用预签名 URL 连接到 Amazon S3 HTTP 服务器并授权访问要下载的对象。Amazon S3 HTTP 服务器的 TLS 连接仅使用服务器身份验证。在应用程序级别，使用预签名 URL 查询中的参数对对象的访问进行身份验证。请按照以下步骤配置与 AWS的连接。

1. 设置 AWS 账户：

   1. 如果您还没有，[请创建一个 AWS 账户](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)。

   1. 账户和权限是使用 AWS Identity and Access Management (IAM) 设置的。您可以使用 IAM 来管理账户中各用户的权限。默认情况下，用户只有在根所有者授予权限后才拥有权限。

      1. 要向您的 AWS 账户添加用户，请参阅 [IAM 用户指南](https://docs.aws.amazon.com/IAM/latest/UserGuide/)。

      1. 向您的 AWS 账户授予访问FreeRTOS的权限， AWS IoT 并通过添加此政策：
         + 亚马逊 3 FullAccess

1. 按照*《Amazon Simple Storage Service 用户指南》*的[如何创建 S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-bucket.html)中的步骤，在 Amazon S3 中创建一个存储桶。

1. 按照[如何将文件和文件夹上传至 S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/upload-objects.html)中的步骤，将文件上传到 Amazon S3 存储桶。

1. 使用 `FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/Common/presigned_url_generator/presigned_urls_gen.py` 文件中的脚本生成预签名 URL。

   有关使用说明，请参阅 `FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/Common/presigned_url_generator/README.md` 文件。

## 功能
<a name="core-http-s3-upload-demo-functionality"></a>

首先，此演示使用 TLS 服务器身份验证连接到 Amazon S3 HTTP 服务器。然后，它会创建一个 HTTP 请求来上传在 `democonfigDEMO_HTTP_UPLOAD_DATA` 中指定的数据。上传文件后，它会通过请求文件的大小来检查文件是否上传成功。该演示的源代码可以在[GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_upload.c)网站上找到。

### 连接到 Amazon S3 HTTP 服务器
<a name="core-http-s3-upload-demo-connecting"></a>

该[ connectToServerWithBackoffRetries](https://github.com/aws/amazon-freertos/blob/main/demos/common/http_demo_helpers/http_demo_utils.c#L131-L170)函数尝试与 HTTP 服务器建立 TCP 连接。如果连接失败，则会在超时后重试。超时值呈指数级增长，直到达到最大尝试次数或最大超时值。如果在配置的尝试次数后仍无法建立与服务器的 TCP 连接，则 `connectToServerWithBackoffRetries` 函数将返回失败状态。

`prvConnectToServer` 函数演示如何仅使用服务器身份验证来建立与 Amazon S3 HTTP 服务器的连接。它使用在 `FreeRTOS-Plus/Source/Application-Protocols/network_transport/freertos_plus_tcp/using_mbedtls/using_mbedtls.c` 文件中实现的基于 mbedTLS 的传输接口。的定义`prvConnectToServer`可以在[GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_upload.c#L306-L366)网站上找到。

### 上传数据
<a name="core-http-s3-upload-demo-upload-data"></a>

`prvUploadS3ObjectFile` 函数演示如何创建 PUT 请求和指定要上传的文件。上传文件的 Amazon S3 存储桶和要上传的文件名在预签名 URL 中指定。为了节省内存，请求标头和接收响应使用相同的缓冲区。使用 `HTTPClient_Send` API 函数同步接收响应。Amazon S3 HTTP 服务器需要一个 `200 OK` 响应状态代码。任何其他状态代码均为错误。

的源代码`prvUploadS3ObjectFile()`可以在[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_upload.c#L539-L632)网站上找到。

### 验证上传
<a name="core-http-s3-upload-demo-verifying-data"></a>

`prvVerifyS3ObjectFileSize` 函数调用 `prvGetS3ObjectFileSize` 来检索 S3 存储桶中对象的大小。目前，Amazon S3 HTTP 服务器不支持使用预签名 URL 的 HEAD 请求，因此请求第 0 个字节。文件的大小包含在响应的 `Content-Range` 标头字段中。服务器的预期响应为 `206 Partial Content`。任何其他响应状态代码均为错误。

的源代码`prvGetS3ObjectFileSize()`可以在[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_upload.c#L370-L535)网站上找到。

# coreHTTP 基本 S3 下载演示
<a name="core-http-s3-download-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="core-http-s3-download-demo-intro"></a>

此演示展示了如何使用[范围请求](https://tools.ietf.org/html/rfc7233)来从 Amazon S3 HTTP 服务器下载文件。当您使用 `HTTPClient_AddRangeHeader` 创建 HTTP 请求时，coreHTTP API 原生支持范围请求。对于微控制器环境，强烈建议使用范围要求。通过在不同的范围内下载大文件（而不是在单个请求中下载），可以在不阻塞网络套接字的情况下处理文件的各个部分。范围请求降低了丢弃数据包的风险（而丢弃的数据包要求在 TCP 连接上重新传输），因此可以改善设备的功耗。

此示例使用一个[网络传输接口](https://freertos.org/network-interface.html)，该接口使用 mbedTL 在运行 CoreHTTP 的 IoT 设备客户端与 Amazon S3 HTTP 服务器之间建立双向身份验证的连接。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

### 单线程与多线程
<a name="core-http-s3-download-demo-threads"></a>

coreHTTP 有两种使用模式，即*单线程*和*多线程*（多任务处理）。尽管本节中的演示在线程中运行 HTTP 库，但它实际上演示了如何在单线程环境中使用 coreHTTP（演示中只有一个任务使用 HTTP API）。尽管单线程应用程序必须重复调用 HTTP 库，但多线程应用程序可以在后台的代理（或进程守护程序）任务中发送 HTTP 请求。

## 源代码组织
<a name="core-http-s3-download-demo-source-code"></a>

演示项目已命名`http_demo_s3_download.c`，可以在`freertos/demos/coreHTTP/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download.c)网站上找到。

## 配置 Amazon S3 HTTP 服务器连接
<a name="core-http-s3-download-demo-configure-server"></a>

此演示使用预签名 URL 连接到 Amazon S3 HTTP 服务器并授权访问要下载的对象。Amazon S3 HTTP 服务器的 TLS 连接仅使用服务器身份验证。在应用程序级别，使用预签名 URL 查询中的参数对对象的访问进行身份验证。请按照以下步骤配置与 AWS的连接。

1. 设置 AWS 账户：

   1. 如果您还没有，请[创建并激活一个 AWS 帐户](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)。

   1. 账户和权限是使用 AWS Identity and Access Management (IAM) 设置的。您可以使用 IAM 来管理账户中各用户的权限。默认情况下，用户只有在根所有者授予权限后才拥有权限。

      1. 要向您的 AWS 账户添加用户，请参阅 [IAM 用户指南](https://docs.aws.amazon.com/IAM/latest/UserGuide/)。

      1. 向您的 AWS 账户授予访问FreeRTOS的权限， AWS IoT 并添加以下政策：
         + 亚马逊 3 FullAccess

1. 按照*《Amazon Simple Storage Service 控制台用户指南》*的[如何创建 S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-bucket.html)中的步骤，在 S3 中创建一个存储桶。

1. 按照[如何将文件和文件夹上传至 S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/upload-objects.html)中的步骤，将文件上传到 S3。

1. 使用 `FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/Common/presigned_url_generator/presigned_urls_gen.py` 中的脚本生成预签名 URL。有关使用说明，请参阅`FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/Common/presigned_url_generator/README.md`。

## 功能
<a name="core-http-s3-download-demo-functionality"></a>

首先，该演示检索文件的大小。然后，它会在循环中按顺序请求每个字节范围，范围大小为 `democonfigRANGE_REQUEST_LENGTH`。

该演示的源代码可以在[GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download.c)网站上找到。

### 连接到 Amazon S3 HTTP 服务器
<a name="core-http-s3-download-demo-connecting"></a>

函数 [ connectToServerWithBackoffRetries()](https://github.com/aws/amazon-freertos/blob/main/demos/common/http_demo_helpers/http_demo_utils.c#L131-L170) 尝试与 HTTP 服务器建立 TCP 连接。如果连接失败，则会在超时后重试。超时值呈指数级增长，直到达到最大尝试次数或最大超时值。如果在配置的尝试次数后仍无法建立与服务器的 TCP 连接，则 `connectToServerWithBackoffRetries()` 函数将返回失败状态。

`prvConnectToServer()` 函数演示如何仅使用服务器身份验证来建立与 Amazon S3 HTTP 服务器的连接。[它使用基于 mbedtls 的传输接口，该接口在 freeRTOS-\$1mbedtls.c 文件中实现。Plus/Source/Application-Protocols/network\$1transport/freertos\$1plus\$1tcp/using\$1mbedtls/using](https://github.com/FreeRTOS/FreeRTOS/blob/202012.00/FreeRTOS-Plus/Source/Application-Protocols/network_transport/freertos_plus_tcp/using_mbedtls/using_mbedtls.c)

的源代码`prvConnectToServer()`可以在上找到[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download.c#L273-L333)。

### 创建范围请求
<a name="core-http-s3-download-demo-creating-range-request"></a>

API 函数 `HTTPClient_AddRangeHeader()` 支持将字节范围序列化为 HTTP 请求标头以构建范围请求。此演示使用范围请求来检索文件大小并请求文件的各个部分。

`prvGetS3ObjectFileSize()` 函数检索 S3 存储桶中文件的大小。`Connection: keep-alive` 标头已添加到 Amazon S3 的第一个请求中，以便在发送响应后保持连接畅通。目前，S3 HTTP 服务器不支持使用预签名 URL 的 HEAD 请求，因此请求第 0 个字节。文件的大小包含在响应的 `Content-Range` 标头字段中。服务器的预期响应为 `206 Partial Content`；收到任何其他响应状态代码均为错误。

的源代码`prvGetS3ObjectFileSize()`可以在上找到[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download.c#L337-L502)。

检索文件大小后，此演示会为要下载的文件的每个字节范围创建一个新的范围请求。对于文件的每个部分，它都会使用 `HTTPClient_AddRangeHeader()`。

### 发送范围请求和接收响应
<a name="core-http-s3-download-demo-send-request"></a>

函数 `prvDownloadS3ObjectFile()` 循环发送范围请求，直到整个文件下载完成。API 函数 `HTTPClient_Send()` 同步发送请求并接收响应。当函数返回时，响应在 `xResponse` 中接收。然后验证状态代码是否为 `206 Partial Content`，并且目前已下载的字节数按 `Content-Length` 标头值递增。

的源代码`prvDownloadS3ObjectFile()`可以在上找到[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download.c#L506-L651)。

# coreHTTP 基本多线程演示
<a name="core-http-bmt-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="core-http-bmt-demo-intro"></a>

此演示使用 [FreeRTOS 的线程安全队列](https://freertos.org/a00018.html)来保存待处理的请求和响应。此演示中有三个任务需要注意。
+ 主任务等待请求出现在请求队列中。它将通过网络发送这些请求，然后将响应放入响应队列中。
+ 请求任务创建要发送到服务器的 HTTP 库请求对象，并将它们放入请求队列中。每个请求对象都指定了应用程序为下载配置的 S3 文件的字节范围。
+ 响应任务等待响应出现在响应队列中。它会记录收到的每一个响应。

该基本多线程演示配置为使用仅具有服务器身份验证的 TLS 连接，这是 Amazon S3 HTTP 服务器所必需的。应用程序层身份验证使用[预签名 URL查询](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)中的[签名版本 4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 参数完成。

## 源代码组织
<a name="core-http-bmt-demo-source"></a>

演示项目已命名`http_demo_s3_download_multithreaded.c`，可以在`freertos/demos/coreHTTP/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download_multithreaded.c)网站上找到。

## 构建演示项目
<a name="core-http-bmt-demo-building"></a>

该演示项目使用 [Visual Studio 的免费社区版本](https://visualstudio.microsoft.com/vs/community/)。构建演示：

1. 在 Visual Studio IDE 中打开 `mqtt_multitask_demo.sln` Visual Studio 解决方案文件。

1. 从 IDE 的**构建**菜单中选择**构建解决方案**。

**注意**  
如果你使用的是 Microsoft Visual Studio 2017 或更早版本，则必须选择与你的版本兼容的**平台工具集**：**项目-> RTOSDemos 属性-> 平台工具**集。

## 配置演示项目
<a name="core-http-bmt-demo-configuring"></a>

该演示使用 [freerTOS\$1TCP TCP/IP 堆栈](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/index.html)，因此请按照为 TCP[/](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html)IP 入门项目提供的说明进行以下操作：

1. 安装[必备组件](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#prerequisites)（例如 WinPCap）。

1. （可选）[设置静态或动态 IP 地址、网关地址和网络掩码](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#static-dynamic)。

1. （可选）[设置 MAC 地址](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#mac-addr)。

1. 在主机上[选择一个以太网网络接口](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#network-interface)。

1. **重要的是**，在尝试运行 HTTP 演示之前，请先[测试您的网络连接](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#connectivity-test)。

## 配置 Amazon S3 HTTP 服务器连接
<a name="core-http-bmt-demo-configuring-connection"></a>

按照 *coreHTTP 基本下载演示*中有关[配置 Amazon S3 HTTP 服务器连接](core-http-s3-download-demo.md#core-http-s3-download-demo-configure-server)的说明进行操作。

## 功能
<a name="core-http-bmt-demo-functionality"></a>

此演示共创建三个任务：
+ 其一是通过网络发送请求和接收响应。
+ 其二是创建要发送的请求。
+ 其三是处理收到的响应。

在此演示中，主要任务：

1. 创建请求和响应队列。

1. 创建与服务器的连接。

1. 创建请求和响应任务。

1. 等待请求队列通过网络发送请求。

1. 将通过网络收到的响应放入响应队列中。

请求任务：

1. 创建每个范围请求。

响应任务：

1. 处理收到的每个响应。

## Typedefs
<a name="core-http-bmt-demo-typedefs"></a>

此演示定义以下结构来支持多线程。

**请求项目**

以下结构定义了要放入请求队列的请求项目。创建 HTTP 请求后，请求任务会将请求项目复制到队列中。

```
/**
 * @brief Data type for the request queue.
 *
 * Contains the request header struct and its corresponding buffer, to be
 * populated and enqueued by the request task, and read by the main task. The
 * buffer is included to avoid pointer inaccuracy during queue copy operations.
 */
typedef struct RequestItem
{
    HTTPRequestHeaders_t xRequestHeaders;
    uint8_t ucHeaderBuffer[ democonfigUSER_BUFFER_LENGTH ];
} RequestItem_t;
```

**响应项目**

以下结构定义了要放入响应队列的响应项目。通过网络收到响应后，主 HTTP 任务会将响应项目复制到队列中。

```
/**
 * @brief Data type for the response queue.
 *
 * Contains the response data type and its corresponding buffer, to be enqueued
 * by the main task, and interpreted by the response task. The buffer is
 * included to avoid pointer inaccuracy during queue copy operations.
 */
typedef struct ResponseItem
{
    HTTPResponse_t xResponse;
    uint8_t ucResponseBuffer[ democonfigUSER_BUFFER_LENGTH ];
} ResponseItem_t;
```

## 主要 HTTP 发送任务
<a name="core-http-bmt-demo-main-task"></a>

主要应用程序任务：

1. 解析主机地址的预签名 URL 以建立与 Amazon S3 HTTP 服务器的连接。

1. 解析 S3 存储桶中的对象路径的预签名 URL。

1. 使用 TLS 服务器身份验证连接到 Amazon S3 HTTP 服务器。

1. 创建请求和响应队列。

1. 创建请求和响应任务。

`prvHTTPDemoTask()` 函数会进行此设置，并提供演示状态。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L451-L650) 上找到。

在函数 `prvDownloadLoop()` 中，主任务会阻止并等待来自请求队列的请求。收到请求时，它会使用 API 函数 `HTTPClient_Send()` 发送请求。如果 API 函数成功，则会将响应放入响应队列中。

`prvDownloadLoop()` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L1071-L1174) 上找到。

## HTTP 请求任务
<a name="core-http-bmt-demo-request-task"></a>

请求任务在函数 `prvRequestTask` 中指定。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L778-L876) 上找到。

请求任务检索 Amazon S3 存储桶中文件的大小。这在函数 `prvGetS3ObjectFileSize` 中完成。将“Connection: keep-alive”标头添加到 Amazon S3 的此请求中，以便在发送响应后保持连接畅通。目前，Amazon S3 HTTP 服务器不支持使用预签名 URL 的 HEAD 请求，因此请求第 0 个字节。文件的大小包含在响应的 `Content-Range` 标头字段中。服务器的预期响应为 `206 Partial Content`；收到任何其他响应状态代码均为错误。

`prvGetS3ObjectFileSize` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L757-L774) 上找到。

检索文件大小后，请求任务会继续请求文件的各个范围。将每个范围请求放入请求队列中，以供主任务发送。文件范围由演示用户在宏 `democonfigRANGE_REQUEST_LENGTH` 中配置。使用函数 `HTTPClient_AddRangeHeader`，HTTP 客户端库 API 原生支持范围请求。函数 `prvRequestS3ObjectRange` 演示如何使用 `HTTPClient_AddRangeHeader()`。

函数 `prvRequestS3ObjectRange` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L694-L753) 上找到。

## HTTP 响应任务
<a name="core-http-bmt-demo-response-task"></a>

响应任务在响应队列中等待通过网络收到的响应。当主任务成功收到 HTTP 响应时，它会填充响应队列。此任务通过记录状态代码、标头和正文来处理响应。例如，现实世界中的应用程序可以通过将响应正文写入闪存来处理响应。如果响应状态代码不是 `206 partial content`，则该任务会通知主任务：演示应失败。响应任务在函数 `prvResponseTask` 中指定。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L961-L1047) 上找到。

# AWS IoT Jobs 库演示
<a name="freertos-jobs-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="freertos-jobs-demo-introduction"></a>

AWS IoT Jobs 库演示展示了如何通过 MQTT 连接连接到 [AWS IoT Jobs 服务](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html)、从 AWS IoT 设备检索作业以及在设备上处理作业。AWS IoT Jobs 演示项目使用 [FreeRTOS Windows 端口](https://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html)，因此可以在 Windows 上使用 [Visual Studio 社区](https://visualstudio.microsoft.com/vs/community/)版本进行构建和评估。无需微控制器硬件。该演示使用 TLS 与 AWS IoT MQTT 代理建立安全连接，其方式与 [coreMQTT 双向身份验证演示](mqtt-demo-ma.md)相同。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 源代码组织
<a name="freertos-jobs-demo-source-code-org"></a>

演示代码位于 `jobs_demo.c` 文件中，可在 [GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/jobs_for_aws/jobs_demo.c) 网站或 `freertos/demos/jobs_for_aws/` 目录中找到。

## 配置 AWS IoT MQTT 代理连接
<a name="freertos-jobs-demo-configure-mqtt-broker"></a>

在本演示中，您将使用与 MQTT 代理的 AWS IoT MQTT 连接。此连接的配置方式与 [coreMQTT 双向身份验证演示](mqtt-demo-ma.md)相同。

## 功能
<a name="freertos-jobs-demo-functionality"></a>

该演示展示了用于从 AWS IoT 接收任务并在设备上处理这些任务的工作流程。该演示是交互式的，需要您使用 AWS IoT 控制台或 AWS Command Line Interface (AWS CLI) 来创建作业。有关创建作业的更多信息，请参阅 *AWS CLI 命令参考*中的 [create-job](https://docs.aws.amazon.com/cli/latest/reference/iot/create-job.html)。该演示要求将作业文档的 `action` 键设置为 `print` 才能将消息输出到控制台。

请参阅此作业文档的以下格式。

```
{
    "action": "print",
    "message": "ADD_MESSAGE_HERE"
}
```

您可以使用 AWS CLI 创建作业，如以下示例命令所示。

```
aws iot create-job \
    --job-id t12 \
    --targets arn:aws:iot:region:123456789012:thing/device1 \
    --document '{"action":"print","message":"hello world!"}'
```

该演示还使用将 `action` 键设置为 `publish` 的作业文档来将消息重新发布到主题。请参阅此作业文档的以下格式。

```
{
    "action": "publish",
    "message": "ADD_MESSAGE_HERE",
    "topic": "topic/name/here"
}
```

该演示会循环执行，直到收到一个将 `action` 键设置为 `exit` 的作业文档才会退出。作业文档的格式如下所示。

```
{
    "action: "exit"
}
```

### Jobs 演示的入口点
<a name="freertos-jobs-demo-functionality-entry-point"></a>

Jobs 演示入口点函数的源代码可以在 [GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/jobs_for_aws/jobs_demo.c#L773-L967) 上找到。该函数执行以下操作：

1. 使用 `mqtt_demo_helpers.c` 中的帮助程序函数建立 MQTT 连接。

1. 使用 `mqtt_demo_helpers.c` 中的帮助程序函数为 `NextJobExecutionChanged` API 订阅 MQTT 主题。主题字符串是之前使用 AWS IoT Jobs 库定义的宏汇编而成的。

1. 使用 `mqtt_demo_helpers.c` 中的帮助程序函数为 `StartNextPendingJobExecution` API 发布 MQTT 主题。主题字符串是之前使用 AWS IoT Jobs 库定义的宏汇编而成的。

1. 反复调用 `MQTT_ProcessLoop` 以接收传入的消息，这些消息将交给 `prvEventCallback` 进行处理。

1. 演示收到退出操作后，使用文件中的帮助程序函数取消订阅 MQTT 主题并断开连接。`mqtt_demo_helpers.c`

### 收到的 MQTT 消息的回调
<a name="freertos-jobs-demo-functionality-callback"></a>

[prvEventCallback](https://github.com/aws/amazon-freertos/blob/main/demos/jobs_for_aws/jobs_demo.c#L674-L769) 函数从 AWS IoT Jobs 库调用 `Jobs_MatchTopic`，以便对传入的 MQTT 消息进行分类。如果消息类型对应于新作业，则会调用 `prvNextJobHandler()`。

[prvNextJobHandler](https://github.com/aws/amazon-freertos/blob/main/demos/jobs_for_aws/jobs_demo.c#L601-L670) 函数及其调用的函数从 JSON 格式的消息中解析作业文档，然后运行作业指定的操作。`prvSendUpdateForJob` 函数非常让人感兴趣。

### 为正在运行的作业发送更新
<a name="freertos-jobs-demo-functionality-send-update"></a>

函数 [prvSendUpdateForJob()](https://github.com/aws/amazon-freertos/blob/main/demos/jobs_for_aws/jobs_demo.c#L413-L457) 从 Jobs 库调用 `Jobs_Update()`，以便填充在紧随其后的 MQTT 发布操作中使用的主题字符串。

# coreMQTT 演示
<a name="mqtt-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

这些演示可帮助您学习如何使用 coreMQTT 库。

**Topics**
+ [coreMQTT 双向身份验证演示](mqtt-demo-ma.md)
+ [coreMQTT 代理连接共享演示](mqtt-demo-cs.md)

# coreMQTT 双向身份验证演示
<a name="mqtt-demo-ma"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="mqtt-demo-ma-introduction"></a>

coreMQTT 双向身份验证演示项目展示了如何使用在客户端与服务器之间具有双向身份验证的 TLS 建立与 MQTT 代理的连接。此演示使用基于 mbedTLS 的传输接口实现来建立经过服务器和客户端身份验证的 TLS 连接，并演示了 [QoS 1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180914) 级别的 MQTT 订阅发布工作流程。它会订阅主题筛选条件，然后发布到与筛选条件匹配的主题，并等待从 QoS 1 级别收到服务器发回的消息。这种向代理发布消息并从代理接收相同消息的循环过程会无限期地重复。本演示中的消息按照 QoS 1 发送，这样可以保证至少有一次按照 MQTT 规范传递。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 源代码
<a name="mqtt-demo-ma-source-code"></a>

演示源文件已命名`mqtt_demo_mutual_auth.c`，可以在`freertos/demos/coreMQTT/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c)网站上找到。

## 功能
<a name="mqtt-demo-ma-functionality"></a>

该演示创建了一个应用程序任务，该任务循环访问一组示例，这些示例演示如何连接代理、订阅代理上的主题、发布到代理上的主题，最后断开与代理的连接。该演示应用程序会订阅一个主题的消息，也会向同一个主题发布消息。每次演示向 MQTT 代理发布消息时，代理都会向演示应用程序发送相同的消息。

成功完成演示将生成类似于以下图像的输出。

![\[MQTT 演示终端在成功完成后的输出\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/coremqtt-mad-output.png)


 AWS IoT 控制台将生成类似于下图的输出。

![\[MQTT 演示控制台在成功完成后的输出\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/coremqtt-mad-console.png)


## 使用指数回退和抖动重试逻辑
<a name="mqtt-demo-ma-retry-logic"></a>

[ prvBackoffFor重试](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L671-L717)函数显示如何通过指数退避和抖动重试服务器失败的网络操作（例如 TLS 连接或 MQTT 订阅请求）。该函数可计算下一次重试尝试的回退周期，如果重试尝试未用完，则执行回退延迟。由于计算退避周期需要生成随机数，因此该函数使用 PKCS11 模块生成随机数。如果供应商平台支持，则使用该 PKCS11 模块允许访问真随机数生成器 (TRNG)。我们建议您在随机数生成器中加入特定于设备的熵源，这样可以降低设备在连接重试过程中发生冲突的可能性。

## 连接到 MQTT 代理
<a name="mqtt-demo-ma-connecting"></a>

该[ prvConnectToServerWithBackoffRetries](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L721-L782)函数尝试与 MQTT 代理建立相互身份验证的 TLS 连接。如果连接失败，则会在回退周期后重试。回退周期将呈指数级增长，直到达到最大尝试次数或达到最大回退周期。`BackoffAlgorithm_GetNextBackoff` 函数提供指数级增长的回退值，并在达到最大尝试次数后返回 `RetryUtilsRetriesExhausted`。如果在配置的尝试次数后仍无法建立与代理的 TLS 连接，则 `prvConnectToServerWithBackoffRetries` 函数将返回失败状态。

[prvCreate MQTTConnection WithBroker](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L785-L848) 函数演示了如何通过干净的会话与 MQTT 代理建立 MQTT 连接。它使用 TLS 传输接口，该接口在 `FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c` 文件中实现。请记住，我们正在 `xConnectInfo` 中为代理设置保持活动状态的秒数。

下一个函数展示了如何使用 `MQTT_Init` 函数在 MQTT 环境中设置 TLS 传输接口和时间函数，还展示了事件回调函数指针 (`prvEventCallback`) 是如何设置的。该回调用于报告传入的消息。

## 订阅 MQTT 主题
<a name="mqtt-demo-ma-subscribing"></a>

p [rv MQTTSubscribe WithBackoffRetries](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L871-L969) 函数演示如何在 MQTT 代理上订阅主题过滤器。该示例演示了如何订阅一个主题筛选条件，还可以在同一个订阅 API 调用中传递主题筛选条件列表来订阅多个主题筛选条件。此外，对于 `RETRY_MAX_ATTEMPTS`，如果 MQTT 代理拒绝订阅请求，则订阅将以指数回退的方式重试。

## 向主题发布
<a name="mqtt-demo-ma-publishing"></a>

p [rv MQTTPublish ToTopic](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L972-L1004) 函数演示如何在 MQTT 代理上发布到某个主题。

## 接收传入的消息
<a name="mqtt-demo-ma-receiving"></a>

如前所述，该应用程序会在连接到代理之前注册一个事件回调函数。`prvMQTTDemoTask` 函数调用 `MQTT_ProcessLoop` 函数来接收传入的消息。当收到传入的 MQTT 消息时，它会调用应用程序注册的事件回调函数。该[ prvEventCallback](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L1139-L1154)函数就是这样一个事件回调函数的示例。 `prvEventCallback`检查传入的数据包类型并调用相应的处理程序。在下面的示例中，该函数要么调用 `prvMQTTProcessIncomingPublish()` 来处理传入的发布消息，要么调用 `prvMQTTProcessResponse()` 来处理确认消息 (ACK)。

## 处理传入的 MQTT 发布数据包
<a name="mqtt-demo-ma-processing"></a>

[prv MQTTProcess IncomingPublish](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L1108-L1135) 函数演示如何处理来自 MQTT 代理的发布数据包。

## 取消订阅主题
<a name="mqtt-demo-ma-unsubscribing"></a>

该工作流程的最后一步是取消订阅主题，这样代理就不会从 `mqttexampleTOPIC` 发送任何已发布的消息。这是函数 [prv MQTTUnsubscribe FromTopic](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT/mqtt_demo_mutual_auth.c#L1007-L1043) 的定义。

## 更改演示中使用的根 CA
<a name="mqtt-demo-ma-root-ca"></a>

默认情况下，FreeRTOS 演示使用 Amazon Root CA 1 证书（RSA 2048 位密钥）向服务器进行身份验证。 AWS IoT Core 您可以使用其他 [CA 证书来进行服务器身份验证](https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs)，包括 Amazon Root CA 3 证书（ECC 256 位密钥）。要更改 coreMQTT 双向身份验证演示的根 CA，请执行以下操作：

1. 在文本编辑器中，打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/mqtt_demo_mutual_auth_config.h`文件。

1. 在文件中找到以下行。

   ```
    * #define democonfigROOT_CA_PEM    "...insert here..." 
   ```

   取消注释此行，如有必要，将其移到注释块末尾的 ` */` 之后。

1. 复制要使用的 CA 证书，然后将其粘贴到文本 `"...insert here..."` 处。结果应该类似以下示例。

   ```
   #define democonfigROOT_CA_PEM   "-----BEGIN CERTIFICATE-----\n"\
   "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n"\
   "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n"\
   "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n"\
   "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n"\
   "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n"\
   "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n"\
   "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n"\
   "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n"\
   "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n"\
   "YyRIHN8wfdVoOw==\n"\
   "-----END CERTIFICATE-----\n"
   ```

1. （可选）您可以更改其他演示的根 CA。对每个 `freertos/vendors/vendor/boards/board/aws_demos/config_files/demo-name_config.h` 文件重复步骤 1 到 3。

# coreMQTT 代理连接共享演示
<a name="mqtt-demo-cs"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="mqtt-demo-cs-introduction"></a>

CoreMQTT 连接共享演示项目向您展示了如何使用多线程应用程序通过 TLS 建立与 AWS MQTT 代理的连接，并在客户端和服务器之间进行相互身份验证。此演示使用基于 mbedTLS 的传输接口实现来建立经过服务器和客户端身份验证的 TLS 连接，并演示了 [QoS 1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180914) 级别的 MQTT 订阅发布工作流程。该演示订阅主题筛选条件，发布与筛选条件匹配的主题，然后等待从 QoS 1 级别的服务器接收这些消息。对于每个创建的任务，这种向代理发布消息并从代理接收相同消息的循环过程会无限期地重复。本演示中的消息按照 QoS 1 发送，这样可以保证至少有一次按照 MQTT 规范传递。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

此演示使用线程安全队列来保存与 MQTT API 交互的命令。此演示中有两个任务需要注意。
+ MQTT 代理（主）任务处理命令队列中的命令，而其他任务则将它们排入队列。此任务会进入循环，它会在此期间处理命令队列中的命令。如果收到终止命令，则此任务将退出循环。
+ 演示 subpub 任务会创建对 MQTT 主题的订阅，然后创建发布操作并将其推送到命令队列中。然后，这些发布操作由 MQTT 代理任务运行。演示 subpub 任务会等待发布完成（通过执行命令完成回调来指示），然后在开始下一次发布之前进入短暂的延迟。此任务展示了应用程序任务如何使用 coreMQTT 代理 API 的示例。

对于传入的发布消息，coreMQTT 代理会调用单个回调函数。此演示还包括一个订阅管理器，它允许任务指定一个回调，以便为它们已订阅的主题的传入发布消息进行调用。在此演示中，代理的传入发布回调会调用订阅管理器，将发布分散到任何已注册订阅的任务中。

此演示使用具有双向身份验证的 TLS 连接到 AWS。如果网络在演示过程中意外断开连接，则客户端会尝试使用指数回退逻辑重新连接。如果客户端重新连接成功，但代理无法恢复之前的会话，则客户端将重新订阅与上一个会话相同的主题。

### 单线程与多线程
<a name="mqtt-demo-cs-single-vs-multi"></a>

coreMQTT 有两种使用模式，即单线程和多线程（多任务处理）。单线程模型使用来自仅一个线程的 coreMQTT 库，并要求您在 MQTT 库中重复进行显式调用。多线程使用案例可以在代理（或进程守护程序）任务的后台运行 MQTT 协议，如此处记录的演示所示。在代理任务中运行 MQTT 协议时，无需显式管理任何 MQTT 状态或调用 `MQTT_ProcessLoop` API 函数。此外，如果您使用代理任务，则多个应用程序任务可共享单个 MQTT 连接，而无需同步原语（例如，互斥锁）。

## 源代码
<a name="mqtt-demo-cs-source-code"></a>

演示源文件已命名`mqtt_agent_task.c`，可以在`freertos/demos/coreMQTT_Agent/`目录和[GitHub](https://github.com/aws/amazon-freertos/tree/main/demos/coreMQTT_Agent/)网站上找到。`simple_sub_pub_demo.c`

## 功能
<a name="mqtt-demo-cs-functionality"></a>

此演示至少创建两个任务：一个用于处理 MQTT API 调用请求的主要任务，以及用于创建这些请求的可配置子任务数量。在此演示中，主任务会创建子任务，调用处理循环，然后进行清理。主任务创建与代理的单个 MQTT 连接，该连接在子任务之间共享。子任务通过代理创建 MQTT 订阅，然后向其发布消息。每个子任务的发布都使用唯一的主题。

## 主任务
<a name="mqtt-demo-cs-main-task"></a>

主应用程序任务 [ RunCoreMQTTAgentDemo](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/mqtt_agent_task.c#L435-L480) 建立 MQTT 会话、创建子任务并运行处理循环 [ MQTTAgent\$1](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/mqtt_agent_task.c#L856)，CommandLoop直到收到终止命令。如果网络意外断开连接，演示将在后台重新连接到代理，并与代理重新建立订阅。处理循环终止后，它会断开与代理的连接。

### 命令
<a name="mqtt-demo-cs-main-task-commands"></a>

当您调用 coreMQTT 代理 API 时，它会创建一个发送到代理任务队列的命令，然后在 `MQTTAgent_CommandLoop()` 中进行处理。在创建命令时，可以传递可选的完成回调和上下文参数。相应的命令完成后，将使用传递的上下文以及作为命令的结果创建的任何返回值来调用完成回调。完成回调的签名如下：

```
typedef void (* MQTTAgentCommandCallback_t )( void * pCmdCallbackContext,
                                              MQTTAgentReturnInfo_t * pReturnInfo );
```

命令完成上下文是用户定义的；对于这个演示，它是：[struct。 MQTTAgent CommandContext](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/simple_sub_pub_demo.c#L105-L115)

在以下情况下即认为命令已完成：
+ 订阅、取消订阅和发布 (QoS > 0)：收到相应的确认数据包后。
+ 所有其他操作：调用相应的 coreMQTT API 后。

命令使用的任何结构（包括发布信息、订阅信息和完成上下文）都必须保持在作用范围内，直到命令完成。在调用完成回调之前，调用任务不得重用命令的任何结构。请注意，由于完成回调由 MQTT 代理调用，因此，它将使用代理任务的线程上下文运行，而不是创建命令的任务。进程间通信机制（例如，任务通知或队列）可用于向调用任务发出命令完成的信号。

### 运行命令循环
<a name="mqtt-demo-cs-command-loop"></a>

命令在`MQTTAgent_CommandLoop()` 中持续处理。如果没有要处理的命令，则循环将等待向队列中添加一个命令的最长等待时间 `MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME`；如果未添加任何命令，则循环将运行 `MQTT_ProcessLoop()` 的一次迭代。这样既可确保管理 MQTT Keep-Alive，又可确保即使队列中没有命令，也能收到传入的发布。

在以下原因下，命令循环函数将返回：
+ 命令返回除 `MQTTSuccess` 之外的任何状态代码。命令循环返回错误状态，因此您可以决定如何处理。在此演示中，重新建立了 TCP 连接并尝试重新连接。如果出现任何错误，则可以在后台进行重新连接，而没有其他使用 MQTT 的任务产生的任何干预。
+ 处理了断开连接命令 (`MQTTAgent_Disconnect`)。退出了命令循环，以便断开 TCP 连接。
+ 处理了终止命令 (`MQTTAgent_Terminate`)。此命令还将任何仍在队列中或正在等待确认数据包的命令标记为错误，返回代码为 `MQTTRecvFailed`。

### 订阅管理器
<a name="mqtt-demo-cs-subscription-manager"></a>

由于该演示使用多个主题，因此，订阅管理器是将订阅的主题与唯一的回调或任务相关联的便捷方式。此演示中的订阅管理器是单线程的，因此不应同时用于多个任务。在此演示中，订阅管理器函数只能从传递给 MQTT 代理的回调函数中调用，并且只能在代理任务的线程上下文中运行。

## 简单的订阅-发布任务
<a name="mqtt-demo-cs-sub-pub"></a>

的每个实例都会[ prvSimpleSubscribePublishTask](https://github.com/aws/amazon-freertos/blob/main/demos/coreMQTT_Agent/simple_sub_pub_demo.c#L447-L569)创建对 MQTT 主题的订阅，并为该主题创建发布操作。为了演示多种发布类型，偶数编号的任务使用 QoS 0（发送发布数据包后即完成），奇数任务使用 QoS 1（收到 PUBACK 数据包后即完成）。

# Over-the-air 更新演示应用程序
<a name="ota-demo"></a>

FreeRTOS 包含一个演示应用程序，用于演示 (OTA) 库 over-the-air的功能。OTA 演示应用程序位于 `freertos/demos/ota/ota_demo_core_mqtt/ota_demo_core_mqtt.c` 或 `freertos/demos/ota/ota_demo_core_http/ota_demo_core_http.c` 文件中。

OTA 演示应用程序执行以下操作：

1. 初始化 FreeRTOS 网络堆栈和 MQTT 缓冲池。

1. 使用 `vRunOTAUpdateDemo()` 创建任务来执行 OTA 库。

1. 使用 `_establishMqttConnection()` 创建 MQTT 客户端。

1. 使用连接到 AWS IoT MQTT 代理`IotMqtt_Connect()`并注册 MQTT 断开连接回调:。`prvNetworkDisconnectCallback`

1. 调用 `OTA_AgentInit()` 创建 OTA 任务，并注册在 OTA 任务完成时使用的回调。

1. 使用 `xOTAConnectionCtx.pvControlClient = _mqttConnection;` 重用 MQTT 连接。

1. 如果 MQTT 断开连接，应用程序将暂停 OTA 代理，尝试使用带有抖动的指数延迟重新连接，然后恢复 OTA 代理。

在使用 OTA 更新之前，请完成 [FreeRTOS 更新 Over-the-Air](freertos-ota-dev.md) 中的所有先决条件

在完成 OTA 更新的设置后，在支持 OTA 功能的平台上下载、构建、刷写并运行 FreeRTOS OTA 演示。设备特定的演示说明可用于以下取得 FreeRTOS 认证的设备：
+ [德州仪器 CC3220 SF-LAUNCHXL](download-ota-ti.md)
+ [微芯片好奇号 PIC32 MZEF](download-ota-mchip.md)
+ [Espressif ESP32](download-ota-esp.md)
+ [在瑞萨 N 上下载、构建、刷新并运行 FreeRTOS OTA 演示 RX65](download-rx65n-ota.md)

在设备上构建、刷新和运行 OTA 演示应用程序后，您可以使用 AWS IoT 控制台或创建 OTA 更新任务。 AWS CLI 在您创建 OTA 更新任务之后，连接到终端仿真器以查看 OTA 更新的进度。记下此过程中生成的任何错误。

成功 OTA 更新作业会显示类似以下内容的输出。为简便起见，在本示例中，我们删除了列表中的一些行。

```
    249 21207 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    250 21247 [MQTT Agent Task] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=601.
    251 21247 [MQTT Agent Task] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
    252 21248 [MQTT Agent Task] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPubAckSend.
    253 21249 [MQTT Agent Task] [ota_demo_core_mqtt.c:976] [INFO] [MQTT] Received job message callback, size 548.
    254 21252 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobId: AFR_OTA-9702f1a3-b747-4c3e-a0eb-a3b0cf83ddbb]
    255 21253 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.streamname: AFR_OTA-945d320b-a18b-441b-b435-4a18d4e7671f]
    256 21255 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.protocols: ["MQTT"]]
    257 21256 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[filepath: aws_demos.bin]
    258 21257 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[filesize: 1164016]
    259 21258 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[fileid: 0]
    260 21259 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[certfile: ecdsa-sha256-signer.crt.pem]
    261 21260 [OTA Agent Task] [ota.c:1575] [INFO] [OTA] Extracted parameter [ sig-sha256-ecdsa: MEQCIE1SFkIHHiZAvkPpu6McJtx7SYoD... ]
    262 21261 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[fileType: 0]
    263 21262 [OTA Agent Task] [ota.c:2199] [INFO] [OTA] Job document was accepted. Attempting to begin the update.
    264 21263 [OTA Agent Task] [ota.c:2323] [INFO] [OTA] Job parsing success: OtaJobParseErr_t=OtaJobParseErrNone, Job name=AFR_OTA-9702f1a3-b747-4c3e-a0eb-a3b0cf83ddbb
    265 21318 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    266 21418 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    267 21469 [OTA Agent Task] [ota.c:938] [INFO] [OTA] Setting OTA data interface.
    268 21470 [OTA Agent Task] [ota.c:2839] [INFO] [OTA] Current State=[CreatingFile], Event=[ReceivedJobDocument], New state=[CreatingFile]
    269 21482 [MQTT Agent Task] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=3.
    270 21483 [OTA Agent Task] [ota_demo_core_mqtt.c:1503] [INFO] [MQTT] SUBSCRIBED to topic $aws/things/__test_infra_thing71/streams/AFR_OTA-945d320b-a18b-441b-b435-4a18d4e7671f/data/cbor to bro
    271 21484 [OTA Agent Task] [ota.c:2839] [INFO] [OTA] Current State=[RequestingFileBlock], Event=[CreateFile], New state=[RequestingFileBlock]
    272 21518 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    273 21532 [MQTT Agent Task] [core_mqtt_agent_command_functions.c:76] [INFO] [MQTT] Publishing message to $aws/things/__test_infra_thing71/streams/AFR_OTA-945d320b-a18b-441b-b435-4a18d4e7671f/
    274 21534 [OTA Agent Task] [ota_demo_core_mqtt.c:1553] [INFO] [MQTT] Sent PUBLISH packet to broker $aws/things/__test_infra_thing71/streams/AFR_OTA-945d320b-a18b-441b-b435-4a18d4e7671f/get/cbor
    275 21534 [OTA Agent Task] [ota_mqtt.c:1112] [INFO] [OTA] Published to MQTT topic to request the next block: topic=$aws/things/__test_infra_thing71/streams/AFR_OTA-945d320b-a18b-441b-b435-4a1
    276 21537 [OTA Agent Task] [ota.c:2839] [INFO] [OTA] Current State=[WaitingForFileBlock], Event=[RequestFileBlock], New state=[WaitingForFileBlock]
    277 21558 [MQTT Agent Task] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=4217.
    278 21559 [MQTT Agent Task] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
    279 21560 [MQTT Agent Task] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPublishDone.
    280 21561 [MQTT Agent Task] [ota_demo_core_mqtt.c:1026] [INFO] [MQTT] Received data message callback, size 4120.
    281 21563 [OTA Agent Task] [ota.c:2464] [INFO] [OTA] Received valid file block: Block index=0, Size=4096
    282 21566 [OTA Agent Task] [ota.c:2683] [INFO] [OTA] Number of blocks remaining: 284
     
    ... // Output removed for brevity
     
    3672 42745 [OTA Agent Task] [ota.c:2464] [INFO] [OTA] Received valid file block: Block index=284, Size=752
    3673 42747 [OTA Agent Task] [ota.c:2633] [INFO] [OTA] Received final block of the update.
    (428298) ota_pal: No such certificate file: ecdsa-sha256-signer.crt.pem. Using certificate in ota_demo_config.h.
    3674 42818 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 285   Queued: 285   Processed: 284   Dropped: 0
    3675 42918 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 285   Queued: 285   Processed: 284   Dropped: 0
     
    ... // Output removed for brevity
     
    3678 43197 [OTA Agent Task] [ota.c:2654] [INFO] [OTA] Received entire update and validated the signature.
    3685 43215 [OTA Agent Task] [ota_demo_core_mqtt.c:862] [INFO] [MQTT] Received OtaJobEventActivate callback from OTA Agent.
     
    ... // Output removed for brevity
     
    2 39 [iot_thread] [INFO ][DEMO][390] ---------STARTING DEMO---------
     
    [0;32mI (3633) WIFI: WIFI_EVENT_STA_CONNECTED
    [0;32mI (4373) WIFI: SYSTEM_EVENT_STA_GOT_IP
     
    ... // Output removed for brevity 
     
    4 351 [sys_evt] [INFO ][DEMO][3510] Connected to WiFi access point, ip address: 255.255.255.0.
    5 351 [iot_thread] [INFO ][DEMO][3510] Successfully initialized the demo. Network type for the demo: 1
    6 351 [iot_thread] [ota_demo_core_mqtt.c:1902] [INFO] [MQTT] OTA over MQTT demo, Application version 0.9.1
    7 351 [iot_thread] [ota_demo_core_mqtt.c:1323] [INFO] [MQTT] Creating a TLS connection to <endpoint>-ats.iot.us-west-2.amazonaws.com:8883.
    9 718 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
    10 718 [iot_thread] [core_mqtt_serializer.c:970] [INFO] [MQTT] CONNACK session present bit not set.
    11 718 [iot_thread] [core_mqtt_serializer.c:912] [INFO] [MQTT] Connection accepted.
     
    ... // Output removed for brevity
     
    17 736 [OTA Agent Task] [ota_demo_core_mqtt.c:1503] [INFO] [MQTT] SUBSCRIBED to topic $aws/things/__test_infra_thing71/jobs/notify-next to broker.
    18 737 [OTA Agent Task] [ota_mqtt.c:381] [INFO] [OTA] Subscribed to MQTT topic: $aws/things/__test_infra_thing71/jobs/notify-next
    30 818 [iot_thread] [ota_demo_core_mqtt.c:1850] [INFO] [MQTT]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    31 819 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobId: AFR_OTA-9702f1a3-b747-4c3e-a0eb-a3b0cf83ddbb]
    32 820 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[execution.statusDetails.updatedBy: 589824]
    33 822 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.streamname: AFR_OTA-945d320b-a18b-441b-b435-4a18d4e7671f]
    34 823 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.protocols: ["MQTT"]]
    35 824 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[filepath: aws_demos.bin]
    36 825 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[filesize: 1164016]
    37 826 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[fileid: 0]
    38 827 [OTA Agent Task] [ota.c:1645] [INFO] [OTA] Extracted parameter: [key: value]=[certfile: ecdsa-sha256-signer.crt.pem]
    39 828 [OTA Agent Task] [ota.c:1575] [INFO] [OTA] Extracted parameter [ sig-sha256-ecdsa: MEQCIE1SFkIHHiZAvkPpu6McJtx7SYoD... ]
    40 829 [OTA Agent Task] [ota.c:1684] [INFO] [OTA] Extracted parameter: [key: value]=[fileType: 0]
    41 830 [OTA Agent Task] [ota.c:2102] [INFO] [OTA] In self test mode.
    42 830 [OTA Agent Task] [ota.c:1936] [INFO] [OTA] New image has a higher version number than the current image: New image version=0.9.1, Previous image version=0.9.0
    43 832 [OTA Agent Task] [ota.c:2120] [INFO] [OTA] Image version is valid: Begin testing file: File ID=0
    53 896 [OTA Agent Task] [ota.c:794] [INFO] [OTA] Beginning self-test.
    62 971 [OTA Agent Task] [ota_demo_core_mqtt.c:1553] [INFO] [MQTT] Sent PUBLISH packet to broker $aws/things/__test_infra_thing71/jobs/AFR_OTA-9702f1a3-b747-4c3e-a0eb-a3b0cf83ddbb/update to br63 971 [MQTT Agent Task] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
    65 973 [MQTT Agent Task] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPublishDone.
    64 973 [OTA Agent Task] [ota_demo_core_mqtt.c:902] [INFO] [MQTT] Successfully updated with the new image.
```

# Over-the-air 演示配置
<a name="ota-demo-specific-config"></a>

OTA 演示配置是在 `aws_iot_ota_update_demo.c` 中提供的特定于演示的配置选项。这些配置与在 OTA 库配置文件中提供的 OTA 库配置不同。

**OTA\$1DEMO\$1KEEP\$1ALIVE\$1SECONDS**  
对于 MQTT 客户端，此配置是从完成一个控制数据包的传输到开始发送下一个控制数据包之间可能经过的最大时间间隔。如果没有控制数据包，则发送 PINGREQ。如果时间达到此保持活动时间间隔的一倍半而内未发送消息或 PINGREQ 数据包，则代理必须断开客户端。请根据应用程序的要求调整此配置。

**OTA\$1DEMO\$1CONN\$1RETRY\$1BASE\$1INTERVAL\$1SECONDS**  
重试网络连接之前的基本间隔（以秒为单位）。OTA 演示将在此基本间隔后尝试重新连接。每次尝试失败后，间隔都会增加一倍。间隔中还会添加一个随机延迟，最高为该基本延迟的最大值。

**OTA\$1DEMO\$1CONN\$1RETRY\$1MAX\$1INTERVAL\$1SECONDS**  
重试网络连接之前的最大间隔（以秒为单位）。每次尝试失败时，重新连接延迟都会增加一倍，但最多只能达到这一最大值加同一间隔的抖动。

# 在德州仪器 SF-LAUNCHXL 上下载、构建、刷新和运行 FreeRTOS OTA 演示 CC3220
<a name="download-ota-ti"></a>

**重要**  <a name="deprecation-message"></a>
该参考集成托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。<a name="download-demo"></a>

**下载 FreeRTOS 和 OTA 演示代码**
+ 你可以在 [https://github.com/FreeRTOS/FreeRTOS GitHub ](https://github.com/FreeRTOS/FreeRTOS) 网站上下载源代码。<a name="build-demo"></a>

**构建演示应用程序**

1. 按照中的[开始使用 FreeRTOS](freertos-getting-started.md)说明将`aws_demos`项目导入 Code Composer Studio，配置您的 AWS IoT 终端节点、Wi-Fi SSID 和密码以及主板的私钥和证书。

1.  打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

1. 构建解决方案，并确保其构建没有错误。

1. 启动终端模拟器，并使用以下设置连接到主板：
   + 波特率：115200
   + 数据位：8
   + 奇偶校验：无
   + 停止位：1

1. 在主板上运行项目，确认它可以连接到 Wi-Fi 和 AWS IoT MQTT 消息代理。

终端模拟器在运行时应当显示类似以下内容的文本：

```
    0 1000 [Tmr Svc] Simple Link task created
    Device came up in Station mode
    1 2534 [Tmr Svc] Write certificate...
    2 5486 [Tmr Svc] [ERROR] Failed to destroy object. PKCS11_PAL_DestroyObject failed.
    3 5486 [Tmr Svc] Write certificate...
    4 5776 [Tmr Svc] Security alert threshold = 15
    5 5776 [Tmr Svc] Current number of alerts = 1
    6 5778 [Tmr Svc] Running Demos.
    7 5779 [iot_thread] [INFO ][DEMO][5779] ---------STARTING DEMO---------
    8 5779 [iot_thread] [INFO ][INIT][5779] SDK successfully initialized.
    Device came up in Station mode
    [WLAN EVENT] STA Connected to the AP: afrlab-pepper , BSSID: 74:83:c2:b4:46:27
    [NETAPP EVENT] IP acquired by the device
    Device has connected to afrlab-pepper
    Device IP Address is 192.168.36.176 
    9 8283 [iot_thread] [INFO ][DEMO][8282] Successfully initialized the demo. Network type for the demo: 1
    10 8283 [iot_thread] [INFO] OTA over MQTT demo, Application version 0.9.0
    11 8283 [iot_thread] [INFO] Creating a TLS connection to <endpoint>-ats.iot.us-west-2.amazonaws.com:8883.
    12 8852 [iot_thread] [INFO] Creating an MQTT connection to <endpoint>-ats.iot.us-west-2.amazonaws.com.
    13 8914 [iot_thread] [INFO] Packet received. ReceivedBytes=2.
    14 8914 [iot_thread] [INFO] CONNACK session present bit not set.
    15 8914 [iot_thread] [INFO] Connection accepted.
    16 8914 [iot_thread] [INFO] Received MQTT CONNACK successfully from broker.
    17 8914 [iot_thread] [INFO] MQTT connection established with the broker.
    18 8915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    19 8953 [OTA Agent T] [INFO] Current State=[RequestingJob], Event=[Start], New state=[RequestingJob]
    20 9008 [MQTT Agent ] [INFO] Packet received. ReceivedBytes=3.
    21 9015 [OTA Agent T] [INFO] SUBSCRIBED to topic $aws/things/__test_infra_thing73/jobs/notify-next to broker.
    22 9015 [OTA Agent T] [INFO] Subscribed to MQTT topic: $aws/things/__test_infra_thing73/jobs/notify-next
    23 9504 [MQTT Agent ] [INFO] Publishing message to $aws/things/__test_infra_thing73/jobs/$next/get.
    24 9535 [MQTT Agent ] [INFO] Packet received. ReceivedBytes=2.
    25 9535 [MQTT Agent ] [INFO] Ack packet deserialized with result: MQTTSuccess.
    26 9536 [MQTT Agent ] [INFO] State record updated. New state=MQTTPublishDone.
    27 9537 [OTA Agent T] [INFO] Sent PUBLISH packet to broker $aws/things/__test_infra_thing73/jobs/$next/get to broker.
    28 9537 [OTA Agent T] [WARN] OTA Timer handle NULL for Timerid=0, can't stop.
    29 9537 [OTA Agent T] [INFO] Current State=[WaitingForJob], Event=[RequestJobDocument], New state=[WaitingForJob]
    30 9539 [MQTT Agent ] [INFO] Packet received. ReceivedBytes=120.
    31 9539 [MQTT Agent ] [INFO] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
    32 9540 [MQTT Agent ] [INFO] State record updated. New state=MQTTPublishDone.
    33 9540 [MQTT Agent ] [INFO] Received job message callback, size 62.
    34 9616 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution
    35 9616 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution.jobId
    36 9617 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution.jobDocument
    37 9617 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution.jobDocument.afr_ota
    38 9617 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution.jobDocument.afr_ota.protocols
    39 9618 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=execution.jobDocument.afr_ota.files
    40 9618 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=filesize
    41 9618 [OTA Agent T] [INFO] Failed job document content check: Required job document parameter was not extracted: parameter=fileid
    42 9619 [OTA Agent T] [INFO] Failed to parse JSON document as AFR_OTA job: DocParseErr_t=7
    43 9619 [OTA Agent T] [INFO] No active job available in received job document: OtaJobParseErr_t=OtaJobParseErrNoActiveJobs
    44 9619 [OTA Agent T] [ERROR] Failed to execute state transition handler: Handler returned error: OtaErr_t=OtaErrJobParserError
    45 9620 [OTA Agent T] [INFO] Current State=[WaitingForJob], Event=[ReceivedJobDocument], New state=[CreatingFile]
    46 9915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    47 10915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    48 11915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    49 12915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    50 13915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
    51 14915 [iot_thread] [INFO]  Received: 0   Queued: 0   Processed: 0   Dropped: 0
```

# 在 Microchip Curiosity MZEF 上下载、构建、刷新和运行 FreeRTOS OTA 演示 PIC32
<a name="download-ota-mchip"></a>

**重要**  <a name="deprecation-message"></a>
该参考集成托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

**注意**  
根据Microchip的协议，我们将从FreeRTOS参考集成存储库主分支中删除好奇号 PIC32 MZEF (DM320104)，并且将在新版本中不再使用它。Microchip已发布[官方通知](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/DM320104)，不再建议将 PIC32 MZEF (DM320104) 用于新设计。 PIC32MZEF 项目和源代码仍然可以通过之前的版本标签进行访问。Microchip 建议客户使用好奇号 [ PIC32MZ-EF-2.0 开发板 () DM320209](https://devices.amazonaws.com/detail/a3G0h0000077I69EAE/Curiosity-PIC32MZ-EF-2-0-Development-Board) 进行新设计。该 PIC32MZv1 平台仍然可以在 FreeRTOS 参考集成存储库的 [v202012.](https://github.com/aws/amazon-freertos/tree/202012.00) 00 中找到。但是，FreeRTOS 参考的 [v202107.00](https://github.com/aws/amazon-freertos/tree/202107.00) 不再支持该平台。<a name="mch-dowload-demo"></a>

**下载 FreeRTOS OTA 演示代码**
+ 你可以在 [https://github.com/FreeRTOS/FreeRTOS GitHub ](https://github.com/FreeRTOS/FreeRTOS) 网站上下载源代码。<a name="mch-build-demo"></a>

**构建 OTA 更新演示应用程序**

1. 按照中的[开始使用 FreeRTOS](freertos-getting-started.md)说明将`aws_demos`项目导入 MPLAB X IDE，配置您的 AWS IoT 端点、Wi-Fi SSID 和密码以及主板的私钥和证书。

1. 打开 `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` 文件，然后输入您的证书。

   ```
   [] = "your-certificate-key";
   ```

1. 将代码签名证书的内容粘贴到此处：

   ```
   #define otapalconfigCODE_SIGNING_CERTIFICATE [] = "your-certificate-key";
   ```

   采用与 `aws_clientcredential_keys.h` 相同的格式，每一行必须以换行符 ('\$1n') 结束，并用引号括起来。

   例如，证书看起来应当如下所示：

   ```
   "-----BEGIN CERTIFICATE-----\n"
   "MIIBXTCCAQOgAwIBAgIJAM4DeybZcTwKMAoGCCqGSM49BAMCMCExHzAdBgNVBAMM\n"
   "FnRlc3Rf62lnbmVyQGFtYXpvbi5jb20wHhcNMTcxMTAzMTkxODM1WhcNMTgxMTAz\n"
   "MTkxODM2WjAhMR8wHQYDVQBBZZZ0ZXN0X3NpZ25lckBhbWF6b24uY29tMFkwEwYH\n"
   "KoZIzj0CAQYIKoZIzj0DAQcDQgAERavZfvwL1X+E4dIF7dbkVMUn4IrJ1CAsFkc8\n"
   "gZxPzn683H40XMKltDZPEwr9ng78w9+QYQg7ygnr2stz8yhh06MkMCIwCwYDVR0P\n"
   "BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMAoGCCqGSM49BAMCA0gAMEUCIF0R\n"
   "r5cb7rEUNtWOvGd05MacrgOABfSoVYvBOK9fP63WAqt5h3BaS123coKSGg84twlq\n"
   "TkO/pV/xEmyZmZdV+HxV/OM=\n"
   "-----END CERTIFICATE-----\n";
   ```

1. 安装 [Python 3](https://www.python.org/downloads/) 或更高版本。

1. 运行 `pip install pyopenssl` 来安装 `pyOpenSSL`。

1. 复制路径 `demos/ota/bootloader/utility/codesigner_cert_utility/` 下 .pem 格式的代码签名证书。重命名证书文件 `aws_ota_codesigner_certificate.pem`。

1.  打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

1. 构建解决方案，并确保其构建没有错误。

1. 启动终端模拟器，并使用以下设置连接到主板：
   + 波特率：115200
   + 数据位：8
   + 奇偶校验：无
   + 停止位：1

1. 从开发板上拔下调试器，然后在主板上运行项目，确认它可以连接到 Wi-Fi 和 AWS IoT MQTT 消息代理。

运行项目时，MPLAB X IDE 应当打开输出窗口。确保选中该**ICD4**选项卡。您应当看到如下输出。

```
Bootloader version 00.09.00
[prvBOOT_Init] Watchdog timer initialized.
[prvBOOT_Init] Crypto initialized.

[prvValidateImage] Validating image at Bank : 0
[prvValidateImage] No application image or magic code present at: 0xbd000000
[prvBOOT_ValidateImages] Validation failed for image at 0xbd000000

[prvValidateImage] Validating image at Bank : 1
[prvValidateImage] No application image or magic code present at: 0xbd100000
[prvBOOT_ValidateImages] Validation failed for image at 0xbd100000

[prvBOOT_ValidateImages] Booting default image.


>0 36246 [IP-task] vDHCPProcess: offer ac140a0eip
                                                 1 36297 [IP-task] vDHCPProcess: offer ac140a0eip
                 2 36297 [IP-task]

IP Address: 172.20.10.14
3 36297 [IP-task] Subnet Mask: 255.255.255.240
4 36297 [IP-task] Gateway Address: 172.20.10.1
5 36297 [IP-task] DNS Server Address: 172.20.10.1


6 36299 [OTA] OTA demo version 0.9.2
7 36299 [OTA] Creating MQTT Client...
8 36299 [OTA] Connecting to broker...
9 38673 [OTA] Connected to broker.
10 38793 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/devthingota/jobs/$next/get/accepted
11 38863 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/devthingota/jobs/notify-next
12 38863 [OTA Task] [OTA_CheckForUpdate] Request #0
13 38964 [OTA] [OTA_AgentInit] Ready.
14 38973 [OTA Task] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:devthingota ]
15 38973 [OTA Task] [prvParseJSONbyModel] parameter not present: execution
16 38973 [OTA Task] [prvParseJSONbyModel] parameter not present: jobId
17 38973 [OTA Task] [prvParseJSONbyModel] parameter not present: jobDocument
18 38973 [OTA Task] [prvParseJSONbyModel] parameter not present: streamname
19 38973 [OTA Task] [prvParseJSONbyModel] parameter not present: files
20 38975 [OTA Task] [prvParseJSONbyModel] parameter not present: filepath
21 38975 [OTA Task] [prvParseJSONbyModel] parameter not present: filesize
22 38975 [OTA Task] [prvParseJSONbyModel] parameter not present: fileid
23 38975 [OTA Task] [prvParseJSONbyModel] parameter not present: certfile
24 38975 [OTA Task] [prvParseJSONbyModel] parameter not present: sig-sha256-ecdsa
25 38975 [OTA Task] [prvParseJobDoc] Ignoring job without ID.
26 38975 [OTA Task] [prvOTA_Close] Context->0x8003b620
27 38975 [OTA Task] [prvPAL_Abort] Abort - OK
28 39964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
29 40964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
30 41964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
31 42964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
32 43964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
33 44964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
34 45964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
35 46964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
36 47964 [OTA] State: Ready  Received: 1   Queued: 1   Processed: 1   Dropped: 0
```

终端模拟器应当显示类似以下内容的文本：

```
AWS Validate: no valid signature in descr: 0xbd000000
AWS Validate: no valid signature in descr: 0xbd100000


>AWS Launch:  No Map performed. Running directly from address: 0x9d000020?
AWS Launch:  wait for app at: 0x9d000020
WILC1000: Initializing...
0 0 

>[None] Seed for randomizer: 1172751941
1 0 [None] Random numbers: 00004272 00003B34 00000602 00002DE3
Chip ID 1503a0

[spi_cmd_rsp][356][nmi spi]: Failed cmd response read, bus error...

[spi_read_reg][1086][nmi spi]: Failed cmd response, read reg (0000108c)...

[spi_read_reg][1116]Reset and retry 10 108c

Firmware ver. : 4.2.1

Min driver ver : 4.2.1

Curr driver ver: 4.2.1

WILC1000: Initialization successful!

Start Wi-Fi Connection...
Wi-Fi Connected
2 7219 [IP-task] vDHCPProcess: offer c0a804beip
3 7230 [IP-task] vDHCPProcess: offer c0a804beip
4 7230 [IP-task] 

IP Address: 192.168.4.190
5 7230 [IP-task] Subnet Mask: 255.255.240.0
6 7230 [IP-task] Gateway Address: 192.168.0.1
7 7230 [IP-task] DNS Server Address: 208.67.222.222


8 7232 [OTA] OTA demo version 0.9.0
9 7232 [OTA] Creating MQTT Client...
10 7232 [OTA] Connecting to broker...
11 7232 [OTA] Sending command to MQTT task.
12 7232 [MQTT] Received message 10000 from queue.
13 8501 [IP-task] Socket sending wakeup to MQTT task.
14 10207 [MQTT] Received message 0 from queue.
15 10256 [IP-task] Socket sending wakeup to MQTT task.
16 10256 [MQTT] Received message 0 from queue.
17 10256 [MQTT] MQTT Connect was accepted. Connection established.
18 10256 [MQTT] Notifying task.
19 10257 [OTA] Command sent to MQTT task passed.
20 10257 [OTA] Connected to broker.
21 10258 [OTA Task] Sending command to MQTT task.
22 10258 [MQTT] Received message 20000 from queue.
23 10306 [IP-task] Socket sending wakeup to MQTT task.
24 10306 [MQTT] Received message 0 from queue.
25 10306 [MQTT] MQTT Subscribe was accepted. Subscribed.
26 10306 [MQTT] Notifying task.
27 10307 [OTA Task] Command sent to MQTT task passed.
28 10307 [OTA Task] [OTA] Subscribed to topic: $aws/things/Microchip/jobs/$next/get/accepted

29 10307 [OTA Task] Sending command to MQTT task.
30 10307 [MQTT] Received message 30000 from queue.
31 10336 [IP-task] Socket sending wakeup to MQTT task.
32 10336 [MQTT] Received message 0 from queue.
33 10336 [MQTT] MQTT Subscribe was accepted. Subscribed.
34 10336 [MQTT] Notifying task.
35 10336 [OTA Task] Command sent to MQTT task passed.
36 10336 [OTA Task] [OTA] Subscribed to topic: $aws/things/Microchip/jobs/notify-next

37 10336 [OTA Task] [OTA] Check For Update #0
38 10336 [OTA Task] Sending command to MQTT task.
39 10336 [MQTT] Received message 40000 from queue.
40 10366 [IP-task] Socket sending wakeup to MQTT task.
41 10366 [MQTT] Received message 0 from queue.
42 10366 [MQTT] MQTT Publish was successful.
43 10366 [MQTT] Notifying task.
44 10366 [OTA Task] Command sent to MQTT task passed.
45 10376 [IP-task] Socket sending wakeup to MQTT task.
46 10376 [MQTT] Received message 0 from queue.
47 10376 [OTA Task] [OTA] Set job doc parameter [ clientToken: 0:Microchip ]
48 10376 [OTA Task] [OTA] Missing job parameter: execution
49 10376 [OTA Task] [OTA] Missing job parameter: jobId
50 10376 [OTA Task] [OTA] Missing job parameter: jobDocument
51 10378 [OTA Task] [OTA] Missing job parameter: ts_ota
52 10378 [OTA Task] [OTA] Missing job parameter: files
53 10378 [OTA Task] [OTA] Missing job parameter: streamname
54 10378 [OTA Task] [OTA] Missing job parameter: certfile
55 10378 [OTA Task] [OTA] Missing job parameter: filepath
56 10378 [OTA Task] [OTA] Missing job parameter: filesize
57 10378 [OTA Task] [OTA] Missing job parameter: sig-sha256-ecdsa
58 10378 [OTA Task] [OTA] Missing job parameter: fileid
59 10378 [OTA Task] [OTA] Missing job parameter: attr
60 10378 [OTA Task] [OTA] Returned buffer to MQTT Client.
61 11367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
62 12367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
63 13367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
64 14367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
65 15367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
66 16367 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
```

此输出显示 Microchip Curi PIC32 osity MZEF 可以连接 AWS IoT 和订阅 OTA 更新所需的 MQTT 主题。出现 `Missing job parameter` 消息在预料之中，因为没有待处理的 OTA 更新作业。

# 在 Espressif 上下载、构建、刷新和运行 FreeRTOS OTA 演示 ESP32
<a name="download-ota-esp"></a>

**重要**  <a name="deprecation-message"></a>
该参考集成托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

1. 从中下载 FreeRTOS 源代码。[GitHub](https://github.com/aws/amazon-freertos)有关说明，请参阅 [README.md](https://github.com/aws/amazon-freertos/blob/main/README.md) 文件。在 IDE 中创建一个项目，其中包含所有所需的源和库。

1. 按照 [Espressif 入门](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html)中的说明，设置所需的基于 GCC 的工具链。

1. 打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

1. 在 `vendors/espressif/boards/esp32/aws_demos` 目录中运行 `make`，构建演示项目。您可以按照 [Espressif 入门](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html)中所述，刷写演示程序并通过运行 `make flash monitor` 来验证其输出。

1. 运行 OTA 更新演示之前：
   + 打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。
   + 打开 `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` 并在下面复制您的 SHA-256/ECDSA 代码签名证书：

     ```
     #define otapalconfigCODE_SIGNING_CERTIFICATE [] = "your-certificate-key";
     ```

# 在瑞萨 N 上下载、构建、刷新并运行 FreeRTOS OTA 演示 RX65
<a name="download-rx65n-ota"></a>

**重要**  <a name="deprecation-message"></a>
该参考集成托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

本章向您展示如何在瑞萨 N 上下载、构建、刷新和运行 FreeRTOS OTA 演示应用程序。 RX65

**Topics**
+ [设置操作环境](#download-rx65n-ota-environment)
+ [设置您的 AWS 资源](#download-rx65n-ota-setup)
+ [导入、配置头文件并构建 aws\$1demos 和 boot\$1loader](#download-rx65n-ota-import-configure)

## 设置操作环境
<a name="download-rx65n-ota-environment"></a>

在本节中，此过程使用以下环境：
+ **IDE**：e2 studio 7.8.0、e2 studio 2020-07
+ **工具链**：CCRX Compiler v3.0.1
+ **目标设备**： RSKRX65N-2MB
+ **调试程序**：E2、E2 Lite 模拟器
+ **软件**：Renesas Flash Programmer、Renesas Secure Flash Programmer.exe、Tera Term

**设置硬件**

1. 将 E 2 Lite 仿真器和 USB 串行端口连接到 RX65 N 主板和电脑。

1. 将电源连接到 RX65 N。

## 设置您的 AWS 资源
<a name="download-rx65n-ota-setup"></a>

1. 要运行 FreeRTOS 演示，您必须拥有 AWS 一个拥有有权访问服务的 IAM 用户的账户。 AWS IoT 如果尚未执行此操作，请按照[设置您的AWS账户和权限](freertos-prereqs.md#freertos-account-and-permissions)中的步骤操作。

1. 要设置 OTA 更新，请按照 [OTA 更新先决条件](ota-prereqs.md)中的步骤操作。特别是，请按照[使用 MQTT 的 OTA 更新的先决条件](ota-mqtt-freertos.md)中的步骤操作。

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

1. 在左侧导航窗格中选择**管理**，然后选择**事物**，以便创建事物。

   事物是 AWS IoT中的特定设备或逻辑实体的表示形式。它可以是物理设备或传感器（例如，灯泡或墙壁上的开关）。它也可以是一个逻辑实体，例如应用程序或物理实体的实例 AWS IoT，它不连接但与连接的设备相关（例如，带有发动机传感器或控制面板的汽车）。 AWS IoT 提供了一个事物注册表，可帮助您管理事物。

   1. 选择**创建**，然后选择**创建单个事物**。

   1. 输入事物的**名称**，然后选择**下一步**。

   1. 选择**创建证书**。

   1. 下载创建的三个文件，然后选择**激活**。

   1. 选择**附加策略**。  
![\[显示要下载的文件的控制台屏幕\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/download-these-files-rx65n.png)

   1. 选择在 [设备策略](ota-mqtt-freertos.md#ota-mqtt-freertos-device-policy) 中创建的策略。

      每台使用 MQTT 接收 OTA 更新的设备都必须注册为事物， AWS IoT 并且该设备必须具有与列出的策略类似的附加策略。您可以在 [AWS IoT 核心策略操作](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policy-actions.html)和 [AWS IoT 核心操作资源](https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html)中找到有关 `"Action"` 和 `"Resource"` 对象中项目的更多信息。

**注意**
      + 这些`iot:Connect`权限允许您的设备通过 MQTT AWS IoT 进行连接。
      + 利用 AWS IoT 作业 (`.../jobs/*`) 主题的 `iot:Subscribe` 和 `iot:Publish` 权限，连接的设备能够接收作业通知和作业文档，并发布作业执行的完成状态。
      +  AWS IoT OTA 直播主题的`iot:Subscribe`和`iot:Publish`权限 (`.../streams/*`) 允许连接的设备从中获取 OTA 更新数据 AWS IoT。在通过 MQTT 执行固件更新时，需要这些权限。
      + 这些`iot:Receive`权限 AWS IoT Core 允许将有关这些主题的消息发布到连接的设备。每次传输 MQTT 消息时，都将检查此权限。您可以使用此权限，撤消对当前订阅主题的客户端的访问权限。

1. 创建代码签名配置文件并在上注册代码签名证书。 AWS

   1. 要创建密钥和认证，请参阅[瑞](https://www.renesas.com/us/en/document/apn/renesas-mcu-firmware-update-design-policy)萨微控制器固件更新设计政策中的第 7.3 节 “使用 OpenSSL 生成 ECDSA-SHA256 密钥对”。

   1. 打开 [AWS IoT 控制台](https://console.aws.amazon.com/iot/home)。在左导航窗格中，选择**管理**，然后选择**作业**。选择**创建作业**，然后选择**创建 OTA 更新作业**。

   1. 在**选择要更新的设备**下，选择**选择**，然后选择之前创建的事物。选择**下一步**。

   1. 在**创建 FreeRTOS OTA 更新作业**页面上，执行以下操作：

      1. 在**选择固件映像传输协议**中，选择 **MQTT**。

      1. 对于**选择并签署固件映像**，选择**为我签署一个新的固件映像**。

      1. 对于**代码签名配置文件**，选择**创建**。

      1. 在**创建代码签名配置文件**窗口中，输入**配置文件名称**。对于**设备硬件平台**，选择 **Windows 模拟器**。对于**代码签名证书**，选择**导入**。

      1. 浏览以选择证书 (`secp256r1.crt`)、证书私钥 (`secp256r1.key`) 和证书链 (`ca.crt`)。

      1. 输入**设备上代码签名证书的路径名**。然后选择**创建**。

1. 要授予对的代码签名的访问权限 AWS IoT，请按照中的步骤操作[授予对代码签名的访问权限 AWS IoT](code-sign-policy.md)。

如果你的电脑上没有安装 Tera Term，你可以从 [https://ttssh2.osdn.jp/index.html.en](https://ttssh2.osdn.jp/index.html.en) 下载并按此处所示进行设置。确保将设备的 USB 串行端口插入 PC。

![\[Tera Term 串行端口设置窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/tera-team-rx65n.png)


## 导入、配置头文件并构建 aws\$1demos 和 boot\$1loader
<a name="download-rx65n-ota-import-configure"></a>

首先，您需要选择最新版本的 FreeRTOS 软件包，该软件包将 GitHub 从项目中下载并自动导入到项目中。这样，您就可以专注于配置 FreeRTOS 和编写应用程序代码。

1. 启动 e2 Studio。

1. 选择**文件**，然后选择**导入…**。

1. 选择**瑞萨电子 FreeRTO GitHub S（含物联网库）项目。**  
![\[e-squared studio 导入窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/import-renesas-project-rx65n.png)

1. 选择**查看更多版本…**以显示下载对话框。  
![\[e-squared studio 下载对话框窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/check-more-version-rx65n.png)

1. 选择最新的程序包。  
![\[e-squared studio 模块下载对话框窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/choose-latest-version-rx65n.png)

1. 选择**同意**以接受最终用户许可协议。  
![\[e-squared studio EULA 对话框\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/eula-rx65n.png)

1. 等待下载完成。  
![\[下载进度条\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/downloading-rx65n.png)

1. 选择 **aws\$1demos** 和 **boot\$1loader** 项目，然后选择**完成**以将其导入。  
![\[导入项目窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/import-projects-rx65n.png)

1. 对于这两个项目，打开项目属性。在导航窗格中，选择**工具链编辑器**。

   1. 选择**当前工具链**。

   1. 选择**当前生成器**。  
![\[e-squared studio 属性窗口\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/project-properties-rx65n.png)

1. 在导航窗格中，选择**设置**。选择**工具链**选项卡，然后选择工具链**版本**。  
![\[Renesas CCRX 版本 v3.01.00 的工具链集成设置，其中包含更改工具链的选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/project-properties-toolchain-rx65n.png)

   选择**工具设置**选项卡，展开**转换器**，然后选择**输出**。在主窗口中，确保选中**输出十六进制文件**，然后选择**输出文件类型**。  
![\[C/C++ 构建配置设置窗口，展示了编译器和链接器选项（如输出 hex 文件、输出文件类型、输出目录和文件拆分选项）。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/project-properties-settings-rx65n.png)  
![\[界面设置树，其中包含“对战分析”、“工具链编辑器”、“C/C++ 常规”、“MCU”、“项目参考”等选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/project-properties-settings-2-rx65n.png)

1. 在引导加载程序项目中，打开 `projects\renesas\rx65n-rsk\e2studio\boot_loader\src\key\code_signer_public_key.h` 并输入公钥。[有关如何创建公钥的信息，请参阅[如何在 N 上使用 Amazon Web Services 实现 FreeRTOS OTA](https://www.renesas.com/us/en/document/apn/rx-family-how-implement-freertos-ota-using-amazon-web-services-rx65n) 和瑞萨 MCU 固件更新设计政策中的第 7.3 节 “使用 OpenSSL 生成 ECDSA-SHA256 密钥对”。 RX65](https://www.renesas.com/us/en/document/apn/renesas-mcu-firmware-update-design-policy)  
![\[代码编辑器，展示了一个 C 表头文件，其中包含 CODE_SIGNER_PUBLIC_KEY 的定义以及一个 PEM 编码的代码签署者公钥变量。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/open-bootloader-project-rx65n.png)

   然后构建项目以创建 `boot_loader.mot`。

1. 打开 `aws_demos` 项目。

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

   1. 在左侧导航窗格中，选择**设置**。在**设备数据端点**文本框中记下自定义端点。

   1. 选择**管理**，然后选择**事物**。记下你的棋盘上的 AWS IoT 事物名称。

   1. 在 `aws_demos` 项目中，打开 `demos/include/aws_clientcredential.h` 并指定以下值。

      ```
      #define clientcredentialMQTT_BROKER_ENDPOINT[] = "Your AWS IoT endpoint";
      #define clientcredentialIOT_THING_NAME "The AWS IoT thing name of your board"
      ```  
![\[显示 AWS IoT 事物名称和代理端点配置设置的代码片段。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/client-credential-rx65n.png)

   1. 打开 `tools/certificate_configuration/CertificateConfigurator.html` 文件。

   1. 导入之前下载的证书 PEM 文件和私钥 PEM 文件。

   1. 选择**生成并保存 aws\$1clientcredential\$1keys.h**，并在 `demos/include/` 目录下替换此文件。  
![\[证书配置工具，其中包含用于从 AWS IoT 控制台提供客户端证书和私钥 PEM 文件的字段，以及一个用于生成和保存 aws_clientcredial_keys.h 文件的按钮。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/certificate-config-tool-rx65n.png)

   1. 打开 `vendors/renesas/boards/rx65n-rsk/aws_demos/config_files/ota_demo_config.h` 文件，并指定这些值。

      ```
      #define otapalconfigCODE_SIGNING_CERTIFICATE [] = "your-certificate-key";
      ```

      文件中的*your-certificate-key*值在哪里`secp256r1.crt`。记得在证书的每一行后面加上“\$1”。[有关创建`secp256r1.crt`文件的更多信息，请参阅[如何在 N 上使用 Amazon Web Services 实现 FreeRTOS OTA](https://www.renesas.com/us/en/document/apn/rx-family-how-implement-freertos-ota-using-amazon-web-services-rx65n) 和瑞萨 MCU 固件更新设计政策中的第 7.3 节 “使用 OpenSSL 生成 ECDSA-SHA256 密钥对”。 RX65](https://www.renesas.com/us/en/document/apn/renesas-mcu-firmware-update-design-policy)  
![\[源代码文件，展示了一段 C 代码，该代码定义了 PEM 编码的代码签署者证书常量字符串，证书数据已被编辑。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/codesigner-cert-rx65n.png)

1. **任务 A：安装固件的初始版本**

   1. 打开 `vendors/renesas/boards/board/aws_demos/config_files/aws_demo_config.h` 文件，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED`，然后定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

   1. 打开 `demos/include/ aws_application_version.h` 文件，并将固件的初始版本设置为 `0.9.2`。  
![\[代码片段，展示了应用程序的版本定义，包括主版本号、次要版本号和构建版本号的宏。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/firmware-version-rx65n.png)

   1. 在**部分查看器**中更改以下设置。  
![\[段查看器窗口，展示了内存地址、段名称（如 SU 和 SI）寄存器和接口组件（如网络缓冲区、异常和操作按钮）。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/section-viewer-rx65n.png)

   1. 选择**构建**以创建 `aws_demos.mot` 文件。

1. 使用 Renesas Secure Flash Programmer 创建文件 `userprog.mot`。`userprog.mot` 是 `aws_demos.mot` 和 `boot_loader.mot` 的组合。您可以将此文件刷新到 RX65 N-RSK 以安装初始固件。

   1. 下载[ https://github.com/renesas/亚马逊 FreerTOS-Too](https://github.com/renesas/Amazon-FreeRTOS-Tools) ls 并打开。`Renesas Secure Flash Programmer.exe`

   1. 选择**初始固件**选项，然后设置以下参数：
      + **私钥路径** – `secp256r1.privatekey` 的位置。
      + **引导加载程序文件路径** – `boot_loader.mot` (`projects\renesas\rx65n-rsk\e2studio\boot_loader\HardwareDebug`) 的位置。
      + **文件路径** – `aws_demos.mot` (`projects\renesas\rx65n-rsk\e2studio\aws_demos\HardwareDebug`) 的位置。  
![\[Renesas 安全闪存编程器窗口，其中包含 MCU、固件验证、序列号、AES 密钥路径和文件路径字段。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/secure-flash-rx65n.png)

   1. 创建一个名为 `init_firmware` 的目录，生成 `userprog.mot`，并将其保存到 `init_firmware` 目录中。验证生成是否成功。

1. 在 RX65 N-RSK 上刷新初始固件。

   1. 从 [ https://www.renesas.com/tw/en/products/software-tools/tools/programmer/renesas-flash-programmer-programming-gui](https://www.renesas.com/tw/en/products/software-tools/tools/programmer/renesas-flash-programmer-programming-gui.html) .html 下载最新版本的瑞萨 Flash Programmer（编程 GUI）。

   1. 打开 `vendors\renesas\rx_mcu_boards\boards\rx65n-rsk\aws_demos\flash_project\erase_from_bank\ erase.rpj` 文件以擦除库中的数据。

   1. 选择**开始**以擦除库。  
![\[Renesas 闪存编程器窗口，展示了 RX 系列微控制器项目详细信息、文件路径和闪存操作选项（如“擦除”、“程序”和“验证”），以及“启动”和“确定”按钮。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/flash-programmer-erasing-rx65n.png)

   1. 要刷写 `userprog.mot`，请选择**浏览...**，导航到 `init_firmware` 目录，选择 `userprog.mot` 文件，然后选择**开始**。  
![\[Renesas 闪存编程器窗口，展示了“擦除”操作设置，包括微控制器 RX 系列、浏览程序文件的选项、“擦除”和“启动”按钮以及要擦除的选定块的状态详细信息。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/flash-programmer-complete-rx65n.png)

1. 固件的 0.9.2 版（初始版本）已安装到您 RX65的 N-RSK 上。 RX65N-RSK 董事会现在正在监听 OTA 更新。如果您在 PC 上打开 Tera Term，则当初始固件运行时，您会看到类似以下的内容。

   ```
   -------------------------------------------------
   RX65N secure boot program
   -------------------------------------------------
   Checking flash ROM status.
   bank 0 status = 0xff [LIFECYCLE_STATE_BLANK]
   bank 1 status = 0xfc [LIFECYCLE_STATE_INSTALLING]
   bank info = 1. (start bank = 0)
   start installing user program.
   copy secure boot (part1) from bank0 to bank1...OK
   copy secure boot (part2) from bank0 to bank1...OK
   update LIFECYCLE_STATE from [LIFECYCLE_STATE_INSTALLING] to [LIFECYCLE_STATE_VALID]
   bank1(temporary area) block0 erase (to update LIFECYCLE_STATE)...OK
   bank1(temporary area) block0 write (to update LIFECYCLE_STATE)...OK
   swap bank...
   -------------------------------------------------
   RX65N secure boot program
   -------------------------------------------------
   Checking flash ROM status.
   bank 0 status = 0xf8 [LIFECYCLE_STATE_VALID]
   bank 1 status = 0xff [LIFECYCLE_STATE_BLANK]
   bank info = 0. (start bank = 1)
   integrity check scheme = sig-sha256-ecdsa
   bank0(execute area) on code flash integrity check...OK
   jump to user program
   0 1 [ETHER_RECEI] Deferred Interrupt Handler Task started
   1 1 [ETHER_RECEI] Network buffers: 3 lowest 3
   2 1 [ETHER_RECEI] Heap: current 234192 lowest 234192
   3 1 [ETHER_RECEI] Queue space: lowest 8
   4 1 [IP-task] InitializeNetwork returns OK
   5 1 [IP-task] xNetworkInterfaceInitialise returns 0
   6 101 [ETHER_RECEI] Heap: current 234592 lowest 233392
   7 2102 [ETHER_RECEI] prvEMACHandlerTask: PHY LS now 1
   8 3001 [IP-task] xNetworkInterfaceInitialise returns 1
   9 3092 [ETHER_RECEI] Network buffers: 2 lowest 2
   10 3092 [ETHER_RECEI] Queue space: lowest 7
   11 3092 [ETHER_RECEI] Heap: current 233320 lowest 233320
   12 3193 [ETHER_RECEI] Heap: current 233816 lowest 233120
   13 3593 [IP-task] vDHCPProcess: offer c0a80a09ip
   14 3597 [ETHER_RECEI] Heap: current 233200 lowest 233000
   15 3597 [IP-task] vDHCPProcess: offer c0a80a09ip
   16 3597 [IP-task] IP Address: 192.168.10.9
   17 3597 [IP-task] Subnet Mask: 255.255.255.0
   18 3597 [IP-task] Gateway Address: 192.168.10.1
   19 3597 [IP-task] DNS Server Address: 192.168.10.1
   20 3600 [Tmr Svc] The network is up and running
   21 3622 [Tmr Svc] Write certificate...
   22 3697 [ETHER_RECEI] Heap: current 232320 lowest 230904
   23 4497 [ETHER_RECEI] Heap: current 226344 lowest 225944
   24 5317 [iot_thread] [INFO ][DEMO][5317] ---------STARTING DEMO---------
   
   25 5317 [iot_thread] [INFO ][INIT][5317] SDK successfully initialized.
   26 5317 [iot_thread] [INFO ][DEMO][5317] Successfully initialized the demo. Network type for the demo: 4
   27 5317 [iot_thread] [INFO ][MQTT][5317] MQTT library successfully initialized.
   28 5317 [iot_thread] [INFO ][DEMO][5317] OTA demo version 0.9.2
   
   29 5317 [iot_thread] [INFO ][DEMO][5317] Connecting to broker...
   
   30 5317 [iot_thread] [INFO ][DEMO][5317] MQTT demo client identifier is rx65n-gr-rose (length 13).
   31 5325 [ETHER_RECEI] Heap: current 206944 lowest 206504
   32 5325 [ETHER_RECEI] Heap: current 206440 lowest 206440
   33 5325 [ETHER_RECEI] Heap: current 206240 lowest 206240
   38 5334 [ETHER_RECEI] Heap: current 190288 lowest 190288
   39 5334 [ETHER_RECEI] Heap: current 190088 lowest 190088
   40 5361 [ETHER_RECEI] Heap: current 158512 lowest 158168
   41 5363 [ETHER_RECEI] Heap: current 158032 lowest 158032
   42 5364 [ETHER_RECEI] Network buffers: 1 lowest 1
   43 5364 [ETHER_RECEI] Heap: current 156856 lowest 156856
   44 5364 [ETHER_RECEI] Heap: current 156656 lowest 156656
   46 5374 [ETHER_RECEI] Heap: current 153016 lowest 152040
   47 5492 [ETHER_RECEI] Heap: current 141464 lowest 139016
   48 5751 [ETHER_RECEI] Heap: current 140160 lowest 138680
   49 5917 [ETHER_RECEI] Heap: current 138280 lowest 138168
   59 7361 [iot_thread] [INFO ][MQTT][7361] Establishing new MQTT connection.
   62 7428 [iot_thread] [INFO ][MQTT][7428] (MQTT connection 81cfc8, CONNECT operation 81d0e8) Wait complete with result SUCCESS.
   63 7428 [iot_thread] [INFO ][MQTT][7428] New MQTT connection 4e8c established.
   64 7430 [iot_thread] [OTA_AgentInit_internal] OTA Task is Ready.
   65 7430 [OTA Agent T] [prvOTAAgentTask] Called handler. Current State [Ready] Event [Start] New state [RequestingJob]
   66 7431 [OTA Agent T] [INFO ][MQTT][7431] (MQTT connection 81cfc8) SUBSCRIBE operation scheduled.
   67 7431 [OTA Agent T] [INFO ][MQTT][7431] (MQTT connection 81cfc8, SUBSCRIBE operation 818c48) Waiting for operation completion.
   68 7436 [ETHER_RECEI] Heap: current 128248 lowest 127992
   69 7480 [OTA Agent T] [INFO ][MQTT][7480] (MQTT connection 81cfc8, SUBSCRIBE operation 818c48) Wait complete with result SUCCESS.
   70 7480 [OTA Agent T] [prvSubscribeToJobNotificationTopics] OK: $aws/things/rx65n-gr-rose/jobs/$next/get/accepted
   71 7481 [OTA Agent T] [INFO ][MQTT][7481] (MQTT connection 81cfc8) SUBSCRIBE operation scheduled.
   72 7481 [OTA Agent T] [INFO ][MQTT][7481] (MQTT connection 81cfc8, SUBSCRIBE operation 818c48) Waiting for operation completion.
   73 7530 [OTA Agent T] [INFO ][MQTT][7530] (MQTT connection 81cfc8, SUBSCRIBE operation 818c48) Wait complete with result SUCCESS.
   74 7530 [OTA Agent T] [prvSubscribeToJobNotificationTopics] OK: $aws/things/rx65n-gr-rose/jobs/notify-next
   75 7530 [OTA Agent T] [prvRequestJob_Mqtt] Request #0
   76 7532 [OTA Agent T] [INFO ][MQTT][7532] (MQTT connection 81cfc8) MQTT PUBLISH operation queued.
   77 7532 [OTA Agent T] [INFO ][MQTT][7532] (MQTT connection 81cfc8, PUBLISH operation 818b80) Waiting for operation completion.
   78 7552 [OTA Agent T] [INFO ][MQTT][7552] (MQTT connection 81cfc8, PUBLISH operation 818b80) Wait complete with result SUCCESS.
   79 7552 [OTA Agent T] [prvOTAAgentTask] Called handler. Current State [RequestingJob] Event [RequestJobDocument] New state [WaitingForJob]
   80 7552 [OTA Agent T] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:rx65n-gr-rose ]
   81 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: execution
   82 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: jobId
   83 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: jobDocument
   84 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: afr_ota
   85 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: protocols
   86 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: files
   87 7552 [OTA Agent T] [prvParseJSONbyModel] parameter not present: filepath
   99 7651 [ETHER_RECEI] Heap: current 129720 lowest 127304
   100 8430 [iot_thread] [INFO ][DEMO][8430] State: Ready  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   101 9430 [iot_thread] [INFO ][DEMO][9430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   102 10430 [iot_thread] [INFO ][DEMO][10430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   103 11430 [iot_thread] [INFO ][DEMO][11430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   104 12430 [iot_thread] [INFO ][DEMO][12430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   105 13430 [iot_thread] [INFO ][DEMO][13430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   106 14430 [iot_thread] [INFO ][DEMO][14430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   107 15430 [iot_thread] [INFO ][DEMO][15430] State: WaitingForJob  Received: 1   Queued: 0   Processed: 0   Dropped: 0
   ```

1. **任务 B：更新固件版本**

   1. 打开 `demos/include/aws_application_version.h` 文件并将 `APP_VERSION_BUILD` 令牌值增加至 `0.9.3`。

   1. 重新构建项目。

1. 使用 Renesas Secure Flash Programmer 创建 `userprog.rsu` 文件以更新固件版本。

   1. 打开 `Amazon-FreeRTOS-Tools\Renesas Secure Flash Programmer.exe` 文件。

   1. 选择**更新固件**选项卡并设置以下参数：
      + **文件路径** – `aws_demos.mot` 文件 (`projects\renesas\rx65n-rsk\e2studio\aws_demos\HardwareDebug`) 的位置。

   1. 创建一个名为 `update _firmware` 的目录。生成 `userprog.rsu` 并将其保存到 `update_firmware` 目录。验证生成是否成功。  
![\[Renesas 安全闪存编程器窗口，其中包含 MCU 选择、固件验证类型、序列号、AES MAC 密钥字段以及用于生成安全的固件的文件路径输入。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/update-firmware-rx65n.png)

1. 如[创建 Amazon S3 存储桶以存储更新](dg-ota-bucket.md)中所述，将固件更新 `userproj.rsu` 上传到 Amazon S3 存储桶。  
![\[Amazon S3 存储桶管理界面，其中包含文件夹、上传、版本和权限选项\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/upload-firmware-rx65n.png)

1. 创建任务以更新 RX65 N-RSK 上的固件。

   AWS IoT Jobs 是一项向一台或多台连接的设备通知待处理[任务](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html)的服务。作业可用于管理设备队列、更新设备上的固件和安全证书，或者执行管理任务，例如重新启动设备和执行诊断。

   1. 登录 [AWS IoT 控制台](https://console.aws.amazon.com/iotv2/)。在导航窗格中，选择**管理**，然后选择**作业**。

   1. 选择**创建作业**，然后选择**创建 OTA 更新作业**。选择一个事物，然后选择**下一步**。

   1. 按照以下方式创建 FreeRTOS OTA 更新作业：
      + 选择 **MQTT**。
      + 选择在上一节中创建的代码签名配置文件。
      + 选择上传到 Amazon S3 存储桶的固件映像。
      + 对于**设备上固件映像的路径名**，请输入**test**。
      + 选择在上一部分中创建的 IAM 角色。

   1. 选择**下一步**。  
![\[固件映像签名和 OTA 更新设置，其中包含签署新固件、选择之前签署的固件、使用自定义已签署固件、指定代码签名配置文件、固件映像文件、设备上的路径以及 OTA 更新作业的 IAM 角色的选项。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/create-job-next-rx65n.png)

   1. 输入一个 ID，然后选择**创建**。

1. 重新打开 Tera Term 以验证固件是否已成功更新到 OTA 演示版 0.9.3。  
![\[命令行输出，展示了线程的初始化以及与代理的连接。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/update-successful-rx65n.png)

1. 在 AWS IoT 控制台上，验证任务状态是否为 “**成功**”。  
![\[AFR OTA-demo 测试作业概览，展示了 1 个资源已成功。\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/completed-succeeded-rx65n.png)

# 教程：使用 ESP32 FreeRTOS 低功耗蓝牙在 Espressif 上执行 OTA 更新
<a name="ota-updates-esp32-ble"></a>

**重要**  <a name="deprecation-message"></a>
该参考集成托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

本教程向您展示如何在 Android 设备上更新连接到 MQTT 低功耗蓝牙代理的乐鑫 ESP32 微控制器。它使用 AWS IoT Over-the-air (OTA) 更新任务更新设备。设备 AWS IoT 使用在安卓演示应用程序中输入的 Amazon Cognito 凭证进行连接。经过身份验证的操作员从云端启动 OTA 更新。当设备通过 Android 演示应用程序进行连接时，OTA 更新即会启动，设备上的固件也会更新。

FreeRTOS 版本 2019.06.00 主版本及更高版本包括蓝牙低功耗 MQTT 代理支持，可用于 Wi-Fi 配置和服务安全连接。 AWS IoT 通过使用低功耗蓝牙功能，您可以构建低功耗设备，这些设备无需 Wi-Fi 即可与移动设备配对，从而进行连接。设备可以通过使用通用接入配置文件 (GAP) 和通用属性 (GATT) 配置文件的 Android 或 iOS 低功耗 SDKs 蓝牙进行连接，从而使用 MQTT 进行通信。

为了允许通过低功耗蓝牙进行 OTA 更新，我们将按照以下步骤操作：

1. **配置存储**：创建 Amazon S3 存储桶和策略，并配置可执行更新的用户。

1. **创建代码签名证书**：创建签名证书并允许用户签署固件更新。

1. **配置 Amazon Cognito 身份验证**：创建凭证提供程序、用户群体和应用程序对用户群体的访问权限。

1. **配置 FreeRTOS**：设置低功耗蓝牙、客户端凭证和代码签名公共证书。

1. **配置 Android 应用程序**：设置凭证提供程序、用户群体，并将应用程序部署到 Android 设备。

1. **运行 OTA 更新脚本**：要启动 OTA 更新，请使用 OTA 更新脚本。

有关更新工作的更多信息，请参阅 [FreeRTOS 更新 Over-the-Air](freertos-ota-dev.md)。有关如何设置低功耗蓝牙 MQTT 代理功能的更多信息，请参阅 Richard Kang 在 Espressif 上的《在 FreeRTOS [上使用低功耗蓝牙 FreeRTOS》 ESP32](https://aws.amazon.com/blogs/iot/using-bluetooth-low-energy-with-amazon-freertos-on-espressif-esp32/)一文。

## 先决条件
<a name="ota-updates-esp32-ble-prereq"></a>

要执行本教程中的步骤，您需要以下资源：
+  ESP32 开发板。
+ 一根 MicroUSB 转 USB A 电缆。
+ 一个 AWS 账户（免费套餐就足够了）。
+ 一台使用 Android v 6.0 或更高版本和蓝牙版本 4.2或更高版本的 Android 手机。

在开发计算机上，您需要：
+ 有足够的磁盘空间（约 500 Mb）来存放 Xtensa 工具链和 FreeRTOS 源代码和示例。
+ 已安装 Android Studio
+ 已安装 [AWS CLI](https://aws.amazon.com/cli/)。
+ 已安装 Python3。
+ 适用于 Py [thon 的 boto3 AWS 软件开发套件 (SDK)](https://github.com/boto/boto3)。

本教程中的步骤假设 Xtensa 工具链、ESP-IDF 和 FreeRTOS 代码已安装在主目录的 `/esp` 目录中。您必须将 `~/esp/xtensa-esp32-elf/bin` 添加到 `$PATH` 变量中。

## 步骤 1：配置存储
<a name="ota-updates-esp32-ble-step1"></a>

1. [创建 Amazon S3 存储桶以存储更新](dg-ota-bucket.md) 并启用版本控制来保留固件映像。

1. [创建 OTA 更新服务角色](create-service-role.md) 并为角色添加以下托管策略：
   + AWSIot正在记录
   + AWSIotRuleActions
   + AWSIotThingsRegistration
   + AWSFreeRTOSOTAUpdate

1. [创建可执行 OTA 更新的用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html)。该用户可以在账户中的 IoT 设备上签名和部署固件更新，并且有权在所有设备上执行 OTA 更新。访问权限应仅限于可信实体。

1. 按照步骤[创建 OTA 用户策略](create-ota-user-policy.md)并将其附加到您的用户。

## 步骤 2：创建代码签名证书
<a name="ota-updates-esp32-ble-step2"></a>

1. 创建启用版本控制的 Amazon S3 存储桶来保留固件映像。

1. 创建可用于对固件进行签名的代码签名证书。导入证书时，记录证书的 Amazon 资源名称 (ARN)。

   ```
   aws acm import-certificate --profile=ota-update-user --certificate file://ecdsasigner.crt --private-key file://ecdsasigner.key
   ```

   输出示例：

   ```
   {
   "CertificateArn": "arn:aws:acm:us-east-1:<account>:certificate/<certid>"
   }
   ```

   稍后您将使用 ARN 创建签名配置文件。如果需要，您可以立即使用以下命令创建该配置文件：

   ```
   aws signer put-signing-profile --profile=ota-update-user --profile-name esp32Profile --signing-material certificateArn=arn:aws:acm:us-east-1:account:certificate/certid --platform AmazonFreeRTOS-Default --signing-parameters certname=/cert.pem
   ```

   输出示例：

   ```
   {
   "arn": "arn:aws:signer::<account>:/signing-profiles/esp32Profile"
   }
   ```

## 步骤 3：Amazon Cognito 身份验证配置
<a name="ota-updates-esp32-ble-step3"></a>

**创建 AWS IoT 策略**

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

1. 在控制台的右上角，选择**我的账户**。在**账户设置**下，记下您的 12 位账户 ID。

1. 在左侧导航窗格中，选择**设置**。在**设备数据端点**下，记下端点值。该端点的值类似于 `xxxxxxxxxxxxxx.iot.us-west-2.amazonaws.com`。在本示例中， AWS 区域为“us-west-2”。

1. 在左导航窗格中依次选择**安全**、**策略**和**创建**。如果您的账户中没有任何策略，则会看到“您还没有任何政策”消息，并且您可以选择**创建政策**。

1. 输入策略的名称，例如，“esp32\$1mqtt\$1proxy\$1iot\$1policy”。

1. 在**添加语句**部分中，选择**高级模式**。将以下 JSON 复制并粘贴到策略编辑器窗口中。将 `aws-account-id` 替换为您的账户 ID，并将 `aws-region` 替换为您的区域（例如，“us-west-2”）。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "iot:Connect",
               "Resource": "arn:aws:iot:us-east-1:123456789012:*"
           },
           {
               "Effect": "Allow",
               "Action": "iot:Publish",
               "Resource": "arn:aws:iot:us-east-1:123456789012:*"
           },
           {
               "Effect": "Allow",
               "Action": "iot:Subscribe",
               "Resource": "arn:aws:iot:us-east-1:123456789012:*"
           },
           {
               "Effect": "Allow",
               "Action": "iot:Receive",
               "Resource": "arn:aws:iot:us-east-1:123456789012:*"
           }
       ]
   }
   ```

------

1. 选择**创建**。

**创建 AWS IoT 事物**

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

1. 在左侧导航窗格中选择**管理**，然后选择**事物**。

1. 在右上角，选择**创建**。如果您的账户中没有注册任何事物，则会显示消息“您还没有任何事物”，并且您可以选择**注册事物**。

1. 在**创建 AWS IoT 事物**页面上，选择**创建单个事物**。

1. 在**将设备添加到事物注册表**页面上，为您的事物输入一个名称（例如，“esp32-ble”）。仅允许使用字母数字字符、连字符 (-) 和下划线 (\$1) 字符。选择**下一步**。

1. 在**添加事物的证书**页面上的**跳过证书并创建事物**下，选择**创建没有证书的事物**。由于我们使用 BLE 代理移动应用程序，该应用程序使用 Amazon Cognito 凭证进行身份验证和授权，因此不需要设备证书。

**创建 Amazon Cognito 应用程序客户端**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/users/)。

1. 在右上角的导航横幅中选择**创建用户群体**。

1. 输入群体名称（例如，“esp32\$1mqtt\$1proxy\$1user\$1pool”）。

1. 选择 **Review defaults (查看原定设置)**。

1. 在**应用程序客户端**中，选择**添加应用程序客户端**，然后选择**添加应用程序客户端**。

1. 输入应用程序客户端名称（例如，“mqtt\$1app\$1client”）。

1. 确保选中**生成客户端密钥**。

1. 选择**创建应用程序客户端**。

1. 选择 **Return to pool details**（返回池详细信息）。

1. 在用户群体的**审核**页面上，选择**创建群体**。您应该会看到一条“已成功创建用户池”的消息。记下该群体 ID。

1. 在导航窗格中选择**应用程序客户端**。

1. 选择**显示详细信息**。记录应用程序客户端 ID 和应用程序客户端密钥。

**创建 Amazon Cognito 身份池**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/federated)。

1. 选择**创建新身份池**。

1. 输入身份池的名称（例如，“mqtt\$1proxy\$1identity\$1pool”）。

1. 展开**身份验证提供程序**。

1. 选择 **Cognito** 选项卡。

1. 输入在前面的步骤中记下的用户群体 ID 和应用程序客户端 ID。

1. 选择**创建池**。

1. 在下一页上，要为经过身份验证和未经过身份验证的身份创建新角色，请选择**允许**。

1. 记下身份池 ID，其格式为 `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`。

**将 IAM policy 附加到经过身份验证的身份。**

1. 打开 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/federated)。

1. 选择刚才创建的身份池（例如，“mqtt\$1proxy\$1identity\$1pool”）。

1. 选择**编辑身份池**。

1. 记下分配给经过身份验证的角色的 IAM 角色（例如，“cognito\$1mqtt\$1proxy\$1identity\$1poolauth\$1Role”）。

1. 打开 [IAM 控制台](https://console.aws.amazon.com/iam/home)。

1. 在导航窗格中，选择**角色**。

1. 搜索分配的角色（例如，“cognito\$1mqtt\$1proxy\$1identity\$1poolauth\$1Role”），然后将其选中。

1. 选择**添加内联策略**，然后选择 **JSON**。

1. 输入以下策略：

------
#### [ JSON ]

****  

   ```
   {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
          {
             "Effect": "Allow",
             "Action": [
                "iot:AttachPolicy",
                "iot:AttachPrincipalPolicy",
                "iot:Connect",
                "iot:Publish",
                "iot:Subscribe"
             ],
             "Resource": "*"
          }]
       }
   ```

------

1. 选择**查看策略**。

1. 输入策略名称（例如，“mqttProxyCognito策略”）。

1. 选择**创建策略**。

## 步骤 4：配置 Amazon FreeRTOS
<a name="ota-updates-esp32-ble-step4"></a>

1. [从 FreeRTOS 存储库下载最新版本的亚马逊 FreeRTOS 代码。 GitHub ](https://github.com/aws/amazon-freertos)

1. 要启用 OTA 更新演示，请按照[开始使用 Espressif ESP32-C 和 DevKit ESP-WROVER-KIT](getting_started_espressif.md)中的步骤操作。

1. 在以下文件中进行这些修改：

   1. 打开 `vendors/espressif/boards/esp32/aws_demos/config_files/aws_demo_config.h` 并定义 `CONFIG_OTA_UPDATE_DEMO_ENABLED`。

   1. 打开 `vendors/espressif/boards/esp32/aws_demos/common/config_files/aws_demo_config.h` 并将 `democonfigNETWORK_TYPES` 更为为 `AWSIOT_NETWORK_TYPE_BLE`。

   1. 打开 `demos/include/aws_clientcredential.h` 并输入 `clientcredentialMQTT_BROKER_ENDPOINT` 的端点 URL。

      输入 `clientcredentialIOT_THING_NAME` 的事物名称（例如，“esp32-ble”）。使用 Amazon Cognito 凭证时，无需添加证书。

   1. 打开 `vendors/espressif/boards/esp32/aws_demos/config_files/aws_iot_network_config.h` 并更改 `configSUPPORTED_NETWORKS` 和 `configENABLED_NETWORKS`，以便仅包含 `AWSIOT_NETWORK_TYPE_BLE`。

   1. 打开 `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` 文件，然后输入您的证书。

      ```
      #define otapalconfigCODE_SIGNING_CERTIFICATE [] = "your-certificate-key";
      ```

   应用程序应该会启动并输出演示版本：

   ```
   11 13498 [iot_thread] [INFO ][DEMO][134980] Successfully initialized the demo. Network type for the demo: 2
   12 13498 [iot_thread] [INFO ][MQTT][134980] MQTT library successfully initialized.
   13 13498 [iot_thread] OTA demo version 0.9.20
   14 13498 [iot_thread] Creating MQTT Client...
   ```

## 步骤 5：配置 Android 应用程序
<a name="ota-updates-esp32-ble-step5"></a>

1. 从 [amazon-freertos-ble-android-sdk 存储库中下载安卓蓝牙低功耗 SDK](https://github.com/aws/amazon-freertos-ble-android-sdk) GitHub 和示例应用程序。

1. 打开文件`app/src/main/res/raw/awsconfiguration.json`并填写池 ID AppClientId、区域，然后 AppClientSecret 按照以下 JSON 示例中的说明进行操作。

   ```
   {
     "UserAgent": "MobileHub/1.0",
     "Version": "1.0",
     "CredentialsProvider": {
       "CognitoIdentity": {
         "Default": {
           "PoolId": "Cognito->Manage Identity Pools->Federated Identities->mqtt_proxy_identity_pool->Edit Identity Pool->Identity Pool ID",
           "Region": "Your region (for example us-east-1)"
         }
       }
     },
   
     "IdentityManager": {
       "Default": {}
     },
   
     "CognitoUserPool": {
       "Default": {
         "PoolId": "Cognito-> Manage User Pools -> esp32_mqtt_proxy_user_pool -> General Settings -> PoolId",
         "AppClientId": "Cognito-> Manage User Pools -> esp32_mqtt_proxy_user_pool -> General Settings -> App clients ->Show Details",
         "AppClientSecret": "Cognito-> Manage User Pools -> esp32_mqtt_proxy_user_pool -> General Settings -> App clients ->Show Details",
         "Region": "Your region (for example us-east-1)"
       }
     }
   }
   ```

1. 打开`app/src/main/java/software/amazon/freertos/DemoConstants.java`并输入您之前创建的策略名称（例如*esp32\$1mqtt\$1proxy\$1iot\$1policy*）和区域（例如*us-east-1*）。

1. 构建和安装演示应用程序。

   1. 在 Android Studio 中，选择**构建**，然后选择**创建模块应用程序**。

   1. 选择**运行**，然后选择**运行应用程序**。您可以转到 Android Studio 中的 logcat 窗格来监控日志消息。

   1. 在 Android 设备上，通过登录屏幕创建一个账户。

   1. 创建用户。如果用户已存在，请输入凭证。

   1. 允许 Amazon FreeRTOS 演示访问设备的位置。

   1. 扫描低功耗蓝牙设备。

   1. 将找到的设备的滑块移至**开**。

   1. 在串行端口调试控制台上按 **y** ESP32。

   1. 选择**配对并连接**。

1. 建立连接后，**更多...**链接会变为活动状态。连接完成后，Android 设备 logcat 中的连接状态会更改为“BLE\$1CONNECTED”：

   ```
   2019-06-06 20:11:32.160 23484-23497/software.amazon.freertos.demo I/FRD: BLE connection state changed: 0; new state: BLE_CONNECTED
   ```

1. 在传输消息之前，Amazon FreeRTOS 设备和 Android 设备会协商 MTU。您会在 logcat 中看到以下输出：

   ```
   2019-06-06 20:11:46.720 23484-23497/software.amazon.freertos.demo I/FRD: onMTUChanged : 512 status: Success
   ```

1. 设备连接到应用程序并开始使用 MQTT 代理发送 MQTT 消息。要确认设备可通信，请确保 MQTT\$1CONTROL 特征数据值已更改为 01：

   ```
   2019-06-06 20:12:28.752 23484-23496/software.amazon.freertos.demo D/FRD: <-<-<- Writing to characteristic: MQTT_CONTROL with data: 01
   2019-06-06 20:12:28.839 23484-23496/software.amazon.freertos.demo D/FRD: onCharacteristicWrite for: MQTT_CONTROL; status: Success; value: 01
   ```

1. 设备配对后，您将在 ESP32 主机上看到提示。要启用 BLE，请按 **y**。在执行此步骤后，演示才能运行。

   ```
   E (135538) BT_GATT: GATT_INSUF_AUTHENTICATION: MITM Required
   W (135638) BT_L2CAP: l2cble_start_conn_update, the last connection update command still pending.
   E (135908) BT_SMP: Value for numeric comparison = 391840
   15 13588 [InputTask] Numeric comparison:391840
   16 13589 [InputTask] Press 'y' to confirm
   17 14078 [InputTask] Key accepted
   W (146348) BT_SMP: FOR LE SC LTK IS USED INSTEAD OF STK
   18 16298 [iot_thread] Connecting to broker...
   19 16298 [iot_thread] [INFO ][MQTT][162980] Establishing new MQTT connection.
   20 16298 [iot_thread] [INFO ][MQTT][162980] (MQTT connection 0x3ffd5754, CONNECT operation 0x3ffd586c) Waiting for operation completion.
   21 16446 [iot_thread] [INFO ][MQTT][164450] (MQTT connection 0x3ffd5754, CONNECT operation 0x3ffd586c) Wait complete with result SUCCESS.
   22 16446 [iot_thread] [INFO ][MQTT][164460] New MQTT connection 0x3ffc0ccc established.
   23 16446 [iot_thread] Connected to broker.
   ```

## 步骤 6：运行 OTA 更新脚本
<a name="ota-updates-esp32-ble-step6"></a>

1. 要安装先决条件，请运行下面的命令：

   ```
   pip3 install boto3
   ```

   ```
   pip3 install pathlib
   ```

1. 在 `demos/include/aws_application_version.h` 中增加 FreeRTOS 应用程序的版本。

1. 构建一个新的 .bin 文件。

1. 下载 python 脚本 [start\$1ota.py](https://github.com/aws-samples/amazon-freertos-ota-scripts/blob/master/scripts/start_ota.py)。要查看脚本的帮助内容，请在终端窗口中运行以下命令：

   ```
   python3 start_ota.py -h
   ```

   您应看到类似于以下内容的信息：

   ```
   usage: start_ota.py [-h] --profile PROFILE [--region REGION]
                       [--account ACCOUNT] [--devicetype DEVICETYPE] --name NAME
                       --role ROLE --s3bucket S3BUCKET --otasigningprofile
                       OTASIGNINGPROFILE --signingcertificateid
                       SIGNINGCERTIFICATEID [--codelocation CODELOCATION]
   Script to start OTA update
   optional arguments:
   -h, --help            show this help message and exit
   --profile PROFILE     Profile name created using aws configure
   --region REGION       Region
   --account ACCOUNT     Account ID
   --devicetype DEVICETYPE thing|group
   --name NAME           Name of thing/group
   --role ROLE           Role for OTA updates
   --s3bucket S3BUCKET   S3 bucket to store firmware updates
   --otasigningprofile OTASIGNINGPROFILE
                         Signing profile to be created or used
   --signingcertificateid SIGNINGCERTIFICATEID
                         certificate id (not arn) to be used
   --codelocation CODELOCATION
                         base folder location (can be relative)
   ```

1. 如果您使用提供的 CloudFormation 模板创建资源，请运行以下命令：

   ```
   python3 start_ota_stream.py --profile otausercf --name esp32-ble --role ota_ble_iot_role-sample --s3bucket afr-ble-ota-update-bucket-sample --otasigningprofile abcd --signingcertificateid certificateid
   ```

   你应该在 ESP32 调试控制台中看到更新开始：

   ```
   38 2462 [OTA Task] [prvParseJobDoc] Job was accepted. Attempting to start transfer.
   ---
   49 2867 [OTA Task] [prvIngestDataBlock] Received file block 1, size 1024
   50 2867 [OTA Task] [prvIngestDataBlock] Remaining: 1290
   51 2894 [OTA Task] [prvIngestDataBlock] Received file block 2, size 1024
   52 2894 [OTA Task] [prvIngestDataBlock] Remaining: 1289
   53 2921 [OTA Task] [prvIngestDataBlock] Received file block 3, size 1024
   54 2921 [OTA Task] [prvIngestDataBlock] Remaining: 1288
   55 2952 [OTA Task] [prvIngestDataBlock] Received file block 4, size 1024
   56 2953 [OTA Task] [prvIngestDataBlock] Remaining: 1287
   57 2959 [iot_thread] State: Active  Received: 5   Queued: 5   Processed: 5   Dropped: 0
   ```

1. OTA 更新完成后，设备将按照 OTA 更新过程的要求重新启动。然后，它会尝试使用更新的固件进行连接。如果升级成功，则会将更新后的固件标记为活动状态，您会在控制台中看到更新的版本：

   ```
   13 13498 [iot_thread] OTA demo version 0.9.21
   ```

# AWS IoT Device Shadow 演示应用程序
<a name="shadow-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="shadow-demo-introduction"></a>

此演示展示了如何使用 Dev AWS IoT ice Shadow 库连接到 Dev [AWS ice Shadow 服务](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html)。它使用 TLS（相互身份验证）与 MQTT 代理建立 M AWS IoT QTT 连接，并使用 CoreJson 库解析器来解析从 Shadow 服务收到的影子文档。[coreMQTT 库](coremqtt.md) AWS 该演示展示了基本的影子操作，例如如何更新影子文档和如何删除影子文档。该演示还展示了如何在 coreMQTT 库中注册回调函数来处理影子消息，例如，影子 `/update` 和从 AWS IoT Device Shadow 服务发送的 `/update/delta` 消息等。

此演示仅用于学习练习，因为更新影子文档（状态）的请求和更新响应是由同一个应用程序完成的。在现实生产场景中，即使设备当前未连接，外部应用程序也会请求远程更新设备的状态。设备连接后将确认更新请求。

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。

## 功能
<a name="shadow-demo-functionality"></a>

该演示创建了一个应用程序任务，该任务会循环执行一组示例，这些示例演示了影子 `/update` 和 `/update/delta` 回调，从而模拟切换远程设备的状态。它会发送带有新的 `desired` 状态的影子更新，并等待设备根据新的 `reported` 状态更改其 `desired` 状态。此外，它还使用影子 `/update` 回调来输出不断变化的影子状态。此演示还使用了与 MQTT 代理的安全的 AWS IoT MQTT 连接，并假设设备影子中存在`powerOn`状态。

该演示执行以下操作：

1. 使用 `shadow_demo_helpers.c` 中的帮助程序函数建立 MQTT 连接。

1. 使用 AWS IoT Device Shadow 库定义的宏汇编用于设备影子操作的 MQTT 主题字符串。

1. 发布到用于删除设备影子的 MQTT 主题以删除任何现有设备影子。

1. 使用 `shadow_demo_helpers.c` 中的帮助程序函数为 `/update/delta`、`/update/accepted` 和 `/update/rejected` 订阅 MQTT 主题。

1. 使用 `shadow_demo_helpers.c` 中的帮助程序函数发布 `powerOn` 的所需状态。这将导致向设备发送 `/update/delta` 消息。

1. 使用 Device Shadow 库定义的函数（`Shadow_MatchTopic`）处理传入的 MQTT 消息，并确定该消息是否与 AWS IoT 设备影子相关。`prvEventCallback`如果该消息是设备影子 `/update/delta` 消息，则主演示函数将发布第二条消息，将报告的状态更新为 `powerOn`。如果收到一条 `/update/accepted` 消息，请确认该消息与之前在更新消息中发布的消息具有相同的 `clientToken`。这标志演示的结束。

![\[影子演示终端输出\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/shadow-demo-output.png)


该演示可以在文件中`freertos/demos/device_shadow_for_aws/shadow_demo_main.c`或上找到[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c)。

以下屏幕截图显示了演示成功时的预期输出。

![\[显示成功的影子演示终端输出\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/shadow-demo-screenshot.png)


## 连接 AWS IoT MQTT 经纪商
<a name="shadow-demo-connect-mqtt"></a>

要连接到 AWS IoT MQTT 代理，我们使用与`MQTT_Connect()`中相同的[coreMQTT 双向身份验证演示](mqtt-demo-ma.md)方法。

## 删除影子文档
<a name="shadow-demo-delete-document"></a>

要删除影子文档，请使用 D `xPublishToTopic` evice Shadow 库定义的 AWS IoT 宏调用一条空消息。这会使用 `MQTT_Publish` 来发布到 `/delete` 主题。以下代码部分显示了如何在函数 `prvShadowDemoTask` 中执行此操作。

```
/* First of all, try to delete any Shadow document in the cloud. */
returnStatus = PublishToTopic( SHADOW_TOPIC_STRING_DELETE( THING_NAME ),
                               SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
                               pcUpdateDocument,
                               0U );
```

## 订阅影子主题
<a name="shadow-demo-subscribe"></a>

订阅 Device Shadow 主题，接收 AWS IoT 代理发送的有关影子变更的通知。Device Shadow 主题由 Device Shadow 库中定义的宏汇编而成。以下代码部分显示了如何在函数 `prvShadowDemoTask` 中执行此操作。

```
/* Then try to subscribe shadow topics. */
if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
}

if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
}

if( returnStatus == EXIT_SUCCESS )
{
    returnStatus = SubscribeToTopic( 
                     SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ),
                     SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
}
```

## 发送影子更新
<a name="shadow-demo-send-updates"></a>

要发送影子更新，该演示使用由 Device Shadow 库定义的宏，通过一条 JSON 格式的消息调用 `xPublishToTopic`。这会使用 `MQTT_Publish` 来发布到 `/delete` 主题。以下代码部分显示了如何在函数 `prvShadowDemoTask` 中执行此操作。

```
#define SHADOW_REPORTED_JSON    \
    "{"                         \
    "\"state\":{"               \
    "\"reported\":{"            \
    "\"powerOn\":%01d"          \
    "}"                         \
    "},"                        \
    "\"clientToken\":\"%06lu\"" \
    "}"
snprintf( pcUpdateDocument,
          SHADOW_REPORTED_JSON_LENGTH + 1,
          SHADOW_REPORTED_JSON,
           ( int ) ulCurrentPowerOnState,
           ( long unsigned ) ulClientToken );

xPublishToTopic( SHADOW_TOPIC_STRING_UPDATE( THING_NAME ),
                 SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
                 pcUpdateDocument,
                 ( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
```

## 处理阴影增量消息和影子更新消息
<a name="shadow-demo-delta-and-update"></a>

使用 `MQTT_Init` 函数注册到 [coreMQTT 客户端库](https://www.freertos.org/iot-device-shadow/device-shadow-demo.html#handle-shadow-messages)的用户回调函数将通知我们传入数据包的事件。请参阅[ prvEventCallback](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L671-L753)上的回调函数 GitHub。

回调函数确认传入的数据包的类型为 `MQTT_PACKET_TYPE_PUBLISH`，并使用 Device Shadow 库 API `Shadow_MatchTopic` 确认传入的消息是否为影子消息。

如果传入的消息是带有类型的影子消息`ShadowMessageTypeUpdateDelta`，则我们调用 [ prvUpdateDeltaHandler](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L464-L580) 来处理此消息。处理程序 `prvUpdateDeltaHandler` 使用 coreJson 库解析消息，以便获取 `powerOn` 状态的增量值，并将其与本地维护的当前设备状态进行比较。如果不同，则会更新本地设备状态以反映影子文档中 `powerOn` 状态的新值。

如果传入的消息是带有类型的影子消息`ShadowMessageTypeUpdateAccepted`，则我们调用 [ prvUpdateAcceptedHandler](https://github.com/aws/amazon-freertos/blob/main/demos/device_shadow_for_aws/shadow_demo_main.c#L584-L667) 来处理此消息。处理程序 `prvUpdateAcceptedHandler` 使用 coreJson 库解析消息，以便从消息获取 `clientToken`。此处理函数会检查 JSON 消息中的客户端令牌是否与应用程序使用的客户端令牌匹配。如果不匹配，则此函数会记录警告消息。

# 安全套接字 Echo 客户端演示
<a name="secure-sockets-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

以下示例使用单个 RTOS 堆栈。可以在 `demos/tcp/aws_tcp_echo_client_single_task.c` 中找到本示例的源代码。

在开始之前，请确认您已将 FreeRTOS 下载到微控制器，并且已构建和运行 FreeRTOS 演示项目。您可以从 [GitHub](https://github.com/aws/amazon-freertos) 克隆或下载 FreeRTOS。有关说明，请参阅 [README.md](https://github.com/aws/amazon-freertos/blob/main/README.md) 文件。

**运行演示**

**注意**  
要设置和运行 FreeRTOS 演示，请按照[开始使用 FreeRTOS](freertos-getting-started.md)中的步骤操作。  
Cypress CYW943907AEVAL1F 和 CYW954907AEVAL1F 开发工具包当前不支持 TCP 服务器和客户端演示。

1. 按照《FreeRTOS 移植指南》中[设置 TLS Echo 服务器](https://docs.aws.amazon.com/freertos/latest/portingguide/tls-echo-server.html)的说明进行操作。

   TLS Echo 服务器应已运行并在端口 9000 上侦听。

   在设置期间，您应已生成四个文件：
   + `client.pem`（客户端证书）
   + `client.key`（客户端私有密钥）
   + `server.pem`（服务器证书）
   + `server.key`（服务器私有密钥）

1. 使用工具 `tools/certificate_configuration/CertificateConfigurator.html` 将客户端证书 (`client.pem`) 和客户端私有密钥 (`client.key`) 复制到 `aws_clientcredential_keys.h`。

1. 打开 `FreeRTOSConfig.h`文件。

1. 将 `configECHO_SERVER_ADDR0`、`configECHO_SERVER_ADDR1`、`configECHO_SERVER_ADDR2` 和 `configECHO_SERVER_ADDR3` 变量设置为 4 个整数，它们构成了 TLS Echo 服务器在其中运行的 IP 地址。

1. 将 `configTCP_ECHO_CLIENT_PORT` 变量设置为 `9000`（TLS Echo 服务器所侦听的端口）。

1. 将 `configTCP_ECHO_TASKS_SINGLE_TASK_TLS_ENABLED` 变量设置为 `1`。

1. 使用工具 `tools/certificate_configuration/PEMfileToCString.html` 将服务器证书 (`server.pem`) 复制到 `cTlsECHO_SERVER_CERTIFICATE_PEM` 文件中的 `aws_tcp_echo_client_single_task.c`。

1. 打开 `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`，注释掉 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 并定义 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

微控制器和 TLS Echo 服务器应位于同一网络中。在演示开始时 (`main.c`)，您应看到一条日志消息，其内容为 `Received correct string from echo server`。