

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

# OTA 教程
<a name="dev-guide-ota-workflow"></a>

本部分包含了如何使用 OTA 更新在运行 FreeRTOS 的设备上更新固件的教程。除了固件映像之外，您还可以使用 OTA 更新将任何类型的文件发送到已连接 AWS IoT的设备。

您可以使用 AWS IoT 控制台或创建 AWS CLI OTA 更新。控制台是开始使用 OTA 的最简便方式，因为它为您执行了大量工作。 AWS CLI 在自动执行 OTA 更新任务、使用大量设备或使用不符合 FreeRTOS 资格的设备时，这非常有用。有关获得 FreeRTOS 资格认证的设备的更多信息，请参阅 [FreeRTOS 合作伙伴](https://aws.amazon.com/partners/dqp/)网站。<a name="create-update"></a>

**创建 OTA 更新**

1. 将初始版本的固件部署到一个或多个设备。

1. 验证固件的运行是否正常。

1. 需要固件更新时，修改代码并构建新映像。

1. 如果手动签署固件，则对固件映像进行签名，之后将其上传到 Amazon S3 存储桶。如果您使用代码签名 AWS IoT，请将未签名的固件映像上传到 Amazon S3 存储桶。

1. 创建 OTA 更新。

在创建 OTA 更新时，可以指定映像传输协议 MQTT 或 HTTP，也可以指定两者来让设备进行选择。设备上的 FreeRTOS OTA 代理将接收更新后的固件映像，并验证数字签名、校验和以及新映像的版本号。如果固件更新通过验证，设备将重置，并根据应用程序定义的逻辑提交更新。如果设备未运行 FreeRTOS，则必须实现一个在设备上运行的 OTA 代理。

# 安装初始固件
<a name="dg-ota-initial-firmware"></a>

要更新固件，必须安装初始版本的固件，该固件使用 OTA 代理库侦听 OTA 更新作业。如果未运行 FreeRTOS，请跳过此步骤。而是必须将 OTA 代理实现复制到设备上。

**Topics**
+ [

# 在德州仪器 CC3220 SF-LAUNCHXL 上安装固件的初始版本
](burn-initial-firmware-ti.md)
+ [

# 在 Espressif 上安装固件的初始版本 ESP32
](burn-initial-firmware-esp.md)
+ [

# 在 Nordic n RF52840 DK 上安装固件的初始版本
](burn-initial-firmware-nordic.md)
+ [

# Windows 模拟器上的初始固件
](burn-initial-firmware-windows.md)
+ [

# 在自定义主板上安装初始版本的固件
](burn-initial-firmware-other.md)

# 在德州仪器 CC3220 SF-LAUNCHXL 上安装固件的初始版本
<a name="burn-initial-firmware-ti"></a>

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

编写以下步骤时，假定您已经按照[在德州仪器 SF-LAUNCHXL 上下载、构建、刷新和运行 FreeRTOS OTA 演示 CC3220](download-ota-ti.md) 中的说明，构建了 `aws_demos` 项目。<a name="burn-demo-ti"></a>

1. 在德州仪器 CC3220 SF-LAUNCHXL 上，将 SOP 跳线放在中间的一组引脚（位置 = 1）上，然后重置电路板。

1. 下载并安装 [TI Uniflash 工具](http://www.ti.com/tool/UNIFLASH)。

1. 启动 Uniflash。**从配置列表中选择 **CC3220SF-LAUNCHXL，然后选择 “启动**图像创建器”。**

1. 选择**新项目**。

1. 在 **Start new project (启动新项目)** 页面上，输入项目名称。在 “**设备类型**” 中，选择 **CC3220SF**。对于 **Device Mode (设备模式)**，选择 **Develop (开发)**。选择**创建项目**。

1. 断开终端模拟器。

1. 在 Uniflash 应用程序窗口的右侧，选择 **Connect (连接)**。

1. 在 **Advanced (高级)**、**Files (文件)** 下，选择 **User Files (用户文件)**。

1. 在 **File (文件)** 选择器窗格中，选择 **Add File (添加文件)** 图标 ![\[Document icon representing a file or page.\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/add-file.png)。

1. 浏览至 `/Applications/Ti/simplelink_cc32xx_sdk_version/tools/cc32xx_tools/certificate-playground` 目录，选择 `dummy-root-ca-cert`，然后依次选择 **Open (打开)** 和 **Write (写入)**。

1. 在 **File (文件)** 选择器窗格中，选择 **Add File (添加文件)** 图标 ![\[Document icon representing a file or page.\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/add-file.png)。

1. 浏览至创建代码签名证书和私有密钥的工作目录，选择 `tisigner.crt.der`，然后依次选择 **Open (打开)** 和 **Write (写入)**。

1. 从 **Action (操作)** 下拉列表中，选择 **Select MCU Image (选择 MCU 映像)**，然后选择 **Browse (浏览)** 以选择要写入设备的固件映像 (**aws\$1demos.bin**)。此文件位于 `freertos/vendors/ti/boards/cc3220_launchpad/aws_demos/ccs/Debug` 目录中。选择**打开**。

   1. 在“File (文件)”对话框中，确认文件名设置为 `mcuflashimg.bin`

   1. 选中 **Vendor (供应商)** 复选框。

   1. 在 **File Token (文件令牌)** 下，键入 **1952007250**。

   1. 在 **Private Key File Name (私有密钥文件名称)** 下，选择 **Browse (浏览)**，然后从创建代码签名证书和私有密钥的工作目录中选择 `tisigner.key`。

   1. 在 **Certification File Name (认证文件名称)** 下，选择 `tisigner.crt.der`。

   1. 选择**写入**。

1. 在左侧窗格的 **Files (文件)** 下，选择 **Service Pack**。

1. 在 **Service Pack File Name (Service Pack 文件名称)** 下，选择 **Browse (浏览)**，浏览至 `simplelink_cc32x_sdk_version/tools/cc32xx_tools/servicepack-cc3x20`，选择 `sp_3.7.0.1_2.0.0.0_2.2.0.6.bin`，然后选择 **Open (打开)**。

1. 在左侧窗格的 **Files (文件)** 下，选择 **Trusted Root-Certificate Catalog (受信任的根证书目录)**。

1. 清除 **Use default Trusted Root-Certificate Catalog (使用默认的受信任的根证书目录)** 复选框。

1. **在 “**源文件**” 下，选择 “**浏览”，选择 s** **implelink\$1cc32xx\$1sdk\$1/20160911.ls *version*** t，然后选择 “打开”。tools/cc32xx\$1tools/certificate-playground/certcatalogPlayGround**

1. **在 “**签名源文件**” 下，选择 “**浏览**”，选择 s **implelink\$1cc32xx\$1sdk\$1/20160911.lst.signed\$13220.b *version*** in，然后选择 “打开”。tools/cc32xx\$1tools/certificate-playground/certcatalogPlayGround**

1. 选择 ![\[Floppy disk icon representing a save or storage function.\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/save.png) 按钮保存项目。

1. 选择 ![\[Feather icon representing a lightweight or simplified feature or concept.\]](http://docs.aws.amazon.com/zh_cn/freertos/latest/userguide/images/flame.png) 按钮。

1. 选择 **Program Image (Create and Program) (编程映像 (创建和编程))**。

1. 编程过程完成之后，将 SOP 跳线放在第一组针脚（位置 = 0）上，重置主板，然后重新连接终端模拟器，以确保输出与使用 Code Composer Studio 调试演示代码时是相同的。记下终端输出中的应用程序版本号。稍后可以使用此版本号验证固件是否已通过 OTA 更新进行了更新。

   终端应显示类似于以下内容的输出。

   ```
   0 0 [Tmr Svc] Simple Link task created
   
   Device came up in Station mode
   
   1 369 [Tmr Svc] Starting key provisioning...
   2 369 [Tmr Svc] Write root certificate...
   3 467 [Tmr Svc] Write device private key...
   4 568 [Tmr Svc] Write device certificate...
   SL Disconnect...
   
   5 664 [Tmr Svc] Key provisioning done...
   Device came up in Station mode
   
   Device disconnected from the AP on an ERROR..!! 
   
   [WLAN EVENT] STA Connected to the AP: Guest , BSSID: 11:22:a1:b2:c3:d4
   
   [NETAPP EVENT] IP acquired by the device
   
   
   Device has connected to Guest
   
   Device IP Address is 111.222.3.44 
   
   
   6 1716 [OTA] OTA demo version 0.9.0
   7 1717 [OTA] Creating MQTT Client...
   8 1717 [OTA] Connecting to broker...
   9 1717 [OTA] Sending command to MQTT task.
   10 1717 [MQTT] Received message 10000 from queue.
   11 2193 [MQTT] MQTT Connect was accepted. Connection established.
   12 2193 [MQTT] Notifying task.
   13 2194 [OTA] Command sent to MQTT task passed.
   14 2194 [OTA] Connected to broker.
   15 2196 [OTA Task] Sending command to MQTT task.
   16 2196 [MQTT] Received message 20000 from queue.
   17 2697 [MQTT] MQTT Subscribe was accepted. Subscribed.
   18 2697 [MQTT] Notifying task.
   19 2698 [OTA Task] Command sent to MQTT task passed.
   20 2698 [OTA Task] [OTA] Subscribed to topic: $aws/things/TI-LaunchPad/jobs/$next/get/accepted
   
   21 2699 [OTA Task] Sending command to MQTT task.
   22 2699 [MQTT] Received message 30000 from queue.
   23 2800 [MQTT] MQTT Subscribe was accepted. Subscribed.
   24 2800 [MQTT] Notifying task.
   25 2801 [OTA Task] Command sent to MQTT task passed.
   26 2801 [OTA Task] [OTA] Subscribed to topic: $aws/things/TI-LaunchPad/jobs/notify-next
   
   27 2814 [OTA Task] [OTA] Check For Update #0
   28 2814 [OTA Task] Sending command to MQTT task.
   29 2814 [MQTT] Received message 40000 from queue.
   30 2916 [MQTT] MQTT Publish was successful.
   31 2916 [MQTT] Notifying task.
   32 2917 [OTA Task] Command sent to MQTT task passed.
   33 2917 [OTA Task] [OTA] Set job doc parameter [ clientToken: 0:TI-LaunchPad ]
   34 2917 [OTA Task] [OTA] Missing job parameter: execution
   35 2917 [OTA Task] [OTA] Missing job parameter: jobId
   36 2918 [OTA Task] [OTA] Missing job parameter: jobDocument
   37 2918 [OTA Task] [OTA] Missing job parameter: ts_ota
   38 2918 [OTA Task] [OTA] Missing job parameter: files
   39 2918 [OTA Task] [OTA] Missing job parameter: streamname
   40 2918 [OTA Task] [OTA] Missing job parameter: certfile
   41 2918 [OTA Task] [OTA] Missing job parameter: filepath
   42 2918 [OTA Task] [OTA] Missing job parameter: filesize
   43 2919 [OTA Task] [OTA] Missing job parameter: sig-sha1-rsa
   44 2919 [OTA Task] [OTA] Missing job parameter: fileid
   45 2919 [OTA Task] [OTA] Missing job parameter: attr
   47 3919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   48 4919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   49 5919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   ```

# 在 Espressif 上安装固件的初始版本 ESP32
<a name="burn-initial-firmware-esp"></a>

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

[本指南假设您已经执行了 [Espressif ESP32-DevKit C 入门中的步骤，以及更新先决 ESP-WROVER-KIT](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html)条件。Over-the-Air ](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html)在尝试 OTA 更新之前，可能需要运行 [FreeRTOS 入门](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-getting-started.html)中所述的 MQTT 演示项目，以确保主板和工具链设置正确。

**将初始出厂映像刷写到主板**

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. 将 [OTA 更新先决条件](ota-prereqs.md) 中生成的 SHA-256/ECDSA PEM 格式的代码签名证书复制到 `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h`。应按以下方式为其设置格式。

   ```
   #define otapalconfigCODE_SIGNING_CERTIFICATE  \
   "-----BEGIN CERTIFICATE-----\n" \
   "...base64 data...\n" \
   "-----END CERTIFICATE-----\n";
   ```

1. 选择 OTA Update 演示后，按照[入门中概述的 ESP32](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html)相同步骤构建和刷新映像。如果之前已构建并刷写了项目，则可能需要先运行 `make clean`。在运行 `make flash monitor` 后，将会看到类似于以下内容的输出。某些消息的顺序可能会有所不同，因为演示应用程序同时运行多个任务。

   ```
   I (28) boot: ESP-IDF v3.1-dev-322-gf307f41-dirty 2nd stage bootloader
   I (28) boot: compile time 16:32:33
   I (29) boot: Enabling RNG early entropy source...
   I (34) boot: SPI Speed : 40MHz
   I (38) boot: SPI Mode : DIO
   I (42) boot: SPI Flash Size : 4MB
   I (46) boot: Partition Table:
   I (50) boot: ## Label Usage Type ST Offset Length
   I (57) boot: 0 nvs WiFi data 01 02 00010000 00006000
   I (64) boot: 1 otadata OTA data 01 00 00016000 00002000
   I (72) boot: 2 phy_init RF data 01 01 00018000 00001000
   I (79) boot: 3 ota_0 OTA app 00 10 00020000 00100000
   I (87) boot: 4 ota_1 OTA app 00 11 00120000 00100000
   I (94) boot: 5 storage Unknown data 01 82 00220000 00010000
   I (102) boot: End of partition table
   I (106) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x14784 ( 83844) map
   I (144) esp_image: segment 1: paddr=0x000347ac vaddr=0x3ffb0000 size=0x023ec ( 9196) load
   I (148) esp_image: segment 2: paddr=0x00036ba0 vaddr=0x40080000 size=0x00400 ( 1024) load
   I (151) esp_image: segment 3: paddr=0x00036fa8 vaddr=0x40080400 size=0x09068 ( 36968) load
   I (175) esp_image: segment 4: paddr=0x00040018 vaddr=0x400d0018 size=0x719b8 (465336) map
   I (337) esp_image: segment 5: paddr=0x000b19d8 vaddr=0x40089468 size=0x04934 ( 18740) load
   I (345) esp_image: segment 6: paddr=0x000b6314 vaddr=0x400c0000 size=0x00000 ( 0) load
   I (353) boot: Loaded app from partition at offset 0x20000
   I (353) boot: ota rollback check done
   I (354) boot: Disabling RNG early entropy source...
   I (360) cpu_start: Pro cpu up.
   I (363) cpu_start: Single core mode
   I (368) heap_init: Initializing. RAM available for dynamic allocation:
   I (375) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
   I (381) heap_init: At 3FFC0748 len 0001F8B8 (126 KiB): DRAM
   I (387) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
   I (393) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
   I (400) heap_init: At 4008DD9C len 00012264 (72 KiB): IRAM
   I (406) cpu_start: Pro cpu start user code
   I (88) cpu_start: Starting scheduler on PRO CPU.
   I (113) wifi: wifi firmware version: f79168c
   I (113) wifi: config NVS flash: enabled
   I (113) wifi: config nano formating: disabled
   I (113) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
   I (123) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
   I (133) wifi: Init dynamic tx buffer num: 32
   I (143) wifi: Init data frame dynamic rx buffer num: 32
   I (143) wifi: Init management frame dynamic rx buffer num: 32
   I (143) wifi: wifi driver task: 3ffc73ec, prio:23, stack:4096
   I (153) wifi: Init static rx buffer num: 10
   I (153) wifi: Init dynamic rx buffer num: 32
   I (163) wifi: wifi power manager task: 0x3ffcc028 prio: 21 stack: 2560
   0 6 [main] WiFi module initialized. Connecting to AP <Your_WiFi_SSID>...
   I (233) phy: phy_version: 383.0, 79a622c, Jan 30 2018, 15:38:06, 0, 0
   I (233) wifi: mode : sta (30:ae:a4:80:0a:04)
   I (233) WIFI: SYSTEM_EVENT_STA_START
   I (363) wifi: n:1 0, o:1 0, ap:255 255, sta:1 0, prof:1
   I (1343) wifi: state: init -> auth (b0)
   I (1343) wifi: state: auth -> assoc (0)
   I (1353) wifi: state: assoc -> run (10)
   I (1373) wifi: connected with <Your_WiFi_SSID>, channel 1
   I (1373) WIFI: SYSTEM_EVENT_STA_CONNECTED
   1 302 [IP-task] vDHCPProcess: offer c0a86c13ip
   I (3123) event: sta ip: 192.168.108.19, mask: 255.255.224.0, gw: 192.168.96.1
   I (3123) WIFI: SYSTEM_EVENT_STA_GOT_IP
   2 302 [IP-task] vDHCPProcess: offer c0a86c13ip
   3 303 [main] WiFi Connected to AP. Creating tasks which use network...
   4 304 [OTA] OTA demo version 0.9.6
   5 304 [OTA] Creating MQTT Client...
   6 304 [OTA] Connecting to broker...
   I (4353) wifi: pm start, type:0
   
   I (8173) PKCS11: Initializing SPIFFS
   I (8183) PKCS11: Partition size: total: 52961, used: 0
   7 1277 [OTA] Connected to broker.
   8 1280 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/<Your_Thing_Name>/jobs/$next/get/accepted
   I (12963) ota_pal: prvPAL_GetPlatformImageState
   I (12963) esp_ota_ops: [0] aflags/seq:0x2/0x1, pflags/seq:0xffffffff/0x0
   9 1285 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/<Your_Thing_Name>/jobs/notify-next
   10 1286 [OTA Task] [OTA_CheckForUpdate] Request #0
   11 1289 [OTA Task] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:<Your_Thing_Name> ]
   12 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: execution
   13 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobId
   14 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobDocument
   15 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: afr_ota
   16 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: streamname
   17 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: files
   18 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filepath
   19 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filesize
   20 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: fileid
   21 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: certfile
   22 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: sig-sha256-ecdsa
   23 1289 [OTA Task] [prvParseJobDoc] Ignoring job without ID.
   24 1289 [OTA Task] [prvOTA_Close] Context->0x3ffbb4a8
   25 1290 [OTA] [OTA_AgentInit] Ready.
   26 1390 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   27 1490 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   28 1590 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   29 1690 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   [ ... ]
   ```

1.  ESP32 董事会现在正在监听 OTA 更新。ESP-IDF 监视器通过 `make flash monitor` 命令启动。您可以按 **Ctrl\$1]** 以退出。您也可以使用最中意的 TTY 终端程序（例如，PuTTY、Tera Term 或 GNU Screen）来侦听主板的串行输出。请注意，连接到主板的串行端口可能会导致主板重新启动。

# 在 Nordic n RF52840 DK 上安装固件的初始版本
<a name="burn-initial-firmware-nordic"></a>

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

本指南假设您已经执行了[Nordic nRF52840-DK 入门](getting_started_nordic.md)和[Over-the-Air 更新先决条件](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html)中的步骤。在尝试 OTA 更新之前，可能需要运行 [FreeRTOS 入门](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-getting-started.html)中所述的 MQTT 演示项目，以确保主板和工具链设置正确。

**将初始出厂映像刷写到主板**

1. 打开 `freertos/vendors/nordic/boards/nrf52840-dk/aws_demos/config_files/aws_demo_config.h`。

1. 将 `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` 替换为 `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` 或 `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`。

1. 使用所选的 OTA 更新演示，按照 [Nordic nRF52840-DK 入门](getting_started_nordic.md)中概述的相同步骤，构建并刷写映像。

   您应该可以看到类似于如下所示的输出内容。

   ```
   9 1285 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/your-thing-name/jobs/notify-next
   10 1286 [OTA Task] [OTA_CheckForUpdate] Request #0
   11 1289 [OTA Task] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:your-thing-name ]
   12 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: execution
   13 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobId
   14 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobDocument
   15 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: afr_ota
   16 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: streamname
   17 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: files
   18 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filepath
   19 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filesize
   20 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: fileid
   21 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: certfile
   22 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: sig-sha256-ecdsa
   23 1289 [OTA Task] [prvParseJobDoc] Ignoring job without ID.
   24 1289 [OTA Task] [prvOTA_Close] Context->0x3ffbb4a8
   25 1290 [OTA] [OTA_AgentInit] Ready.
   26 1390 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   27 1490 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   28 1590 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   29 1690 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   ```

   您的主板此时正在侦听 OTA 更新。

# Windows 模拟器上的初始固件
<a name="burn-initial-firmware-windows"></a>

在使用 Windows 模拟器时，无需刷写初始版本的固件。Windows 模拟器是 `aws_demos` 应用程序的一部分，其中也包含了固件。

# 在自定义主板上安装初始版本的固件
<a name="burn-initial-firmware-other"></a>

使用 IDE 构建 `aws_demos` 项目，确保包括了 OTA 库。有关 FreeRTOS 源代码结构的更多信息，请参阅 [FreeRTOS 演示](freertos-next-steps.md)。

请确保 FreeRTOS 项目或设备中包括了代码签名证书、私有密钥和证书信任链。

使用适当的工具将应用程序刻录到主板上，并确保其正常运行。

# 更新固件版本
<a name="dg-ota-update-firmware"></a>

FreeRTOS 包含的 OTA 代理会检查任何更新版本，仅当该版本高于现有固件版本时才会进行安装。以下步骤展示了如何递增 OTA 演示应用程序的固件版本。

1. 在 IDE 中打开 `aws_demos` 项目。

1. 找到文件 ` /vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` 并增加 **APP\$1VERSION\$1BUILD** 的值。

1. 要安排对文件类型不是 0（非固件文件）的 Renesas rx65n 平台进行更新，必须使用 Renesas Secure Flash Progradmer 工具对文件进行签名，否则设备上的签名检查将失败。该工具创建带有扩展名 `.rsu` 的签名文件包，该文件包是 Renesas 的专有文件类型。该工具可以在 [Github](https://github.com/renesas/Amazon-FreeRTOS-Tools) 上找到。您可以使用以下示例命令生成映像：

   ```
   "Renesas Secure Flash Programmer.exe" CUI Update "RX65N(ROM 2MB)/Secure Bootloader=256KB" "sig-sha256-ecdsa" 1 "file_name" "output_file_name.rsu"
   ```

1. 重新构建项目。

必须将固件更新复制到您创建的 Amazon S3 存储桶中，如[创建 Amazon S3 存储桶以存储更新](dg-ota-bucket.md)中所述。需要复制到 Amazon S3 的文件名称取决于所使用的硬件平台：
+ 德州仪器 CC3220 SF-LAUNCHXL：`vendors/ti/boards/cc3220_launchpad/aws_demos/ccs/debug/aws_demos.bin`
+ Espressif ESP32: `vendors/espressif/boards/esp32/aws_demos/make/build/aws_demos.bin`

# 创建 OTA 更新（AWS IoT 控制台）
<a name="ota-console-workflow"></a>

1. 在 AWS IoT 控制台的导航窗格中，在 “**管理**” 下选择 “**远程操作**”，然后选择 “**作业**”。

1. 请选择**创建任务**。

1. 在**作业类型**下，选择**创建 FreeRTOS OTA 更新作业**，然后选择**下一步**。

1. 在**作业属性**中，输入**作业名称**和（可选）作业的**描述**，然后选择**下一步**。

1. 可以将一个 OTA 更新部署到单个设备或一组设备。在**要更新的设备**下，从下拉列表中选择一个或多个事物或事物组。

1. 在**选择文件传输协议**下，选择 **HTTP** 或 **MQTT**，或者同时选择两者以允许每台设备确定要使用的协议。

1. 在**签名并选择文件**下，选择**为我签署一个新文件**。

1. 在**代码签名配置文件**下，选择**创建新配置文件**。

1. 在 **Create a code signing profile (创建代码签名配置文件)** 中，为代码签名配置文件输入名称。

   1. 在 **Device hardware platform (设备硬件平台)** 下，选择硬件平台。
**注意**  
该列表中只显示了符合 FreeRTOS 条件的硬件平台。如果您正在测试不符合条件的平台，并且使用 ECDSA P-256 SHA-256 密码套件进行签名，则可以选择 Windows 模拟器代码签名配置文件以生成兼容签名。如果您使用的是不合格的平台，并且使用的是 ECDSA P-256 SHA-256 以外的密码套件进行签名，则可以使用代码签名 AWS IoT，也可以自己签署固件更新。有关更多信息，请参阅 [对固件更新进行数字签名](ota-cli-workflow.md#ota-sign-cli)。

   1. 在**代码签名证书**下，选择**选择现有证书**，然后选择以前导入的证书，或者选择**导入新的代码签名证书**，选择您的文件，然后选择**导入**，以便导入新证书。

   1. 在 **Pathname of code signing certificate on device (设备上代码签名证书的路径名)** 下，输入代码签名证书在设备上的完全限定路径名称。对于大多数设备，您可以将此字段留空。对于 Windows 模拟器以及将证书放在特定文件位置的设备，请在此处输入路径名。
**重要**  
在德州仪器 CC3220 SF-LAUNCHXL 上，如果您的代码签名证书存在于文件系统的根目录中，则不要在文件名前面加上前导斜杠 (**/**)。否则，OTA 更新将在身份验证过程中失败，且产生 `file not found` 错误。

   1. 选择**创建**。

1. 在**文件**下，**选择现有文件**，然后选择**浏览 S3**。此时将显示 Amazon S3 存储桶的列表。选择包含固件更新的存储桶，然后在存储桶中选择固件更新。
**注意**  
Microchip Curi PIC32 osity MZEF 演示项目生成两张默认名称为和的`mplab.production.bin`二进制图像。`mplab.production.ota.bin`如果要上传映像用于 OTA 更新，请使用第二个文件。

1. 在**设备上文件的路径名**下，输入设备上 OTA 作业要将固件映像复制到的位置的完全限定路径名称。此位置因平台而异。
**重要**  
在德州仪器 CC3220 SF-LAUNCHXL 上，由于安全限制，固件镜像路径名必须为。`/sys/mcuflashimg.bin`

1. 在**文件类型**下，输入一个介于 0-255 范围内的整数值。您输入的文件类型将添加到传送到 MCU 的 Job 文档中。MCU firmware/software 开发者对如何处理此值拥有完全所有权。可能的场景包括带有辅助处理器的 MCU，其固件可以独立于主处理器进行更新。当设备收到 OTA 更新任务时，它可以使用文件类型来识别更新适用于哪个处理器。

1. 在 **IAM 角色**下，根据[创建 OTA 更新服务角色](create-service-role.md)中的说明选择一个角色。

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

1. 为 OTA 更新作业输入 ID 和描述。

1. 在 “**任务类型**” 下，选择 “**您的任务将在部署到所选任务后完成 devices/groups （快照）**”。

1. 为作业选择任何适当的可选配置（**作业执行推出**、**作业中止**、**作业执行超时**和**标签**）。

1. 选择**创建**。<a name="previously-signed"></a>

**选择以前签署的固件映像**

1. 在 **Select and sign your firmware image (选择并签署固件映像)** 下，选择 **Select a previously signed firmware image (选择以前签署的固件映像)**。

1. 在 **Pathname of firmware image on device (设备上固件映像的路径名)** 下，输入设备上 OTA 作业要将固件映像复制到的位置的完全限定路径名称。此位置因平台而异。

1. 在 **Previous code signing job (原有的代码签名作业)** 下，选择 **Select (选择)**，然后选择用来签署用于 OTA 更新的固件映像的上一个代码签名作业。<a name="custom-signed"></a>

**使用自定义的已签署固件映像**

1. 在 **Select and sign your firmware image (选择并签署固件映像)** 下，选择 **Use my custom signed firmware image (使用我的自定义已签署固件映像)**。

1. 在 **Pathname of code signing certificate on device (设备上代码签名证书的路径名)** 下，输入代码签名证书在设备上的完全限定路径名称。对于大多数设备，您可以将此字段留空。对于 Windows 模拟器以及将证书放在特定文件位置的设备，请在此处输入路径名。

1. 在 **Pathname of firmware image on device (设备上固件映像的路径名)** 下，输入设备上 OTA 作业要将固件映像复制到的位置的完全限定路径名称。此位置因平台而异。

1. 在 **Signature (签名)** 下，粘贴 PEM 格式的签名。

1. 在 **Original hash algorithm (原始哈希算法)** 下，选择在创建文件签名时所使用的哈希算法。

1. 在 **Original encryption algorithm (原始加密算法)** 下，选择在创建文件签名时所使用的算法。

1. 在**在 Amazon S3 中选择固件映像**下，选择 Amazon S3 存储桶以及 Amazon S3 存储桶中已签署的固件映像。

指定代码签名信息后，为更新指定 OTA 更新作业类型、服务角色和 ID。

**注意**  
请勿在 OTA 更新的作业 ID 中使用任何个人身份信息。个人身份信息示例包括：  
名称。
IP 地址。
电子邮件地址。
位置。
银行详细信息。
医疗信息。

1. 在 **Job type (作业类型)** 下，选择 **Your job will complete after deploying to the selected devices/groups (snapshot) (您的作业将在部署到所选设备/组后完成 (快照))**。

1. 在 **IAM role for OTA update job (OTA 更新作业的 IAM 角色)** 下，选择 OTA 服务角色。

1. 为作业输入字母数字形式的 ID，然后选择 **Create (创建)**。

任务显示在 AWS IoT 控制台中，状态为 “进行**中**”。

**注意**  
 AWS IoT 控制台不会自动更新作业的状态。刷新浏览器可以查看更新。

将串行 UART 终端连接到设备。您应当看到输出表明设备正在下载更新后的固件。

设备在下载完更新后的固件之后，将重新启动，然后安装固件。在 UART 终端中可以看到所发生的情况。

有关说明如何使用控制台创建 OTA 更新的教程，请参阅[Over-the-air 更新演示应用程序](ota-demo.md)。

# 使用创建 OTA 更新 AWS CLI
<a name="ota-cli-workflow"></a>

使用创建 OTA 更新时，您： AWS CLI 

1. 对固件映像进行数字签名。

1. 创建经数字签名的固件映像的流。

1. 启动 OTA 更新作业。

## 对固件更新进行数字签名
<a name="ota-sign-cli"></a>

当你使用执行 AWS CLI OTA 更新时，你可以使用代码签名 AWS IoT，也可以自己签署固件更新。有关代码签名支持的加密签名和哈希算法的列表 AWS IoT，请参阅。[ SigningConfigurationOverrides](https://docs.aws.amazon.com/signer/latest/api/API_SigningConfigurationOverrides.html)如果您想使用代码签名不支持的加密算法，则必须先对固件二进制文件进行签名 AWS IoT，然后再将其上传到 Amazon S3。

### 使用代码签名对固件映像进行签名 AWS IoT
<a name="ota-sign-csfa"></a>

要使用代码签名对固件映像进行签名 AWS IoT，可以使用[AWS SDKs 或命令行工具](https://aws.amazon.com/tools/)之一。有关代码签名的更多信息 AWS IoT，请参阅的[代码签名 AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html)。

安装和配置代码签名工具后，将未签名的固件映像复制到 Amazon S3 存储桶，然后使用以下命令开始代码签名任务。 AWS CLI **put-signing-profile** 命令用于创建一个可重复使用的代码签名配置文件。**start-signing-job** 命令用于启动签名作业。

```
aws signer put-signing-profile \
    --profile-name your_profile_name \
    --signing-material certificateArn=arn:aws:acm::your-region:your-aws-account-id:certificate/your-certificate-id \
    --platform your-hardware-platform \
    --signing-parameters certname=your_certificate_path_on_device
```

```
aws signer start-signing-job \
    --source 's3={bucketName=your_s3_bucket,key=your_s3_object_key,version=your_s3_object_version_id}' \
    --destination 's3={bucketName=your_destination_bucket}' \
    --profile-name your_profile_name
```

**注意**  
*your-source-bucket-name*并且*your-destination-bucket-name*可以是相同的 Amazon S3 存储桶。

以下是 **put-signing-profile** 和 **start-signing-job** 命令的参数：

**`source`**  
指定未签名的固件在 S3 存储桶中的位置。  
+ `bucketName`：S3 存储桶的名称。
+ `key`：固件在 S3 存储桶中的密钥（文件名）。
+ `version`：固件在 S3 存储桶中的 S3 版本。该版本不同于固件版本。要找到此版本，请转至 Amazon S3 控制台，选择存储桶，然后在页面顶部的**版本**旁选择**显示**。

**`destination`**  
S3 存储桶中已签名的固件将被复制到的设备上的目的地。该参数的格式与 `source` 参数是一样的。

**`signing-material`**  
代码签名证书的 ARN。在将证书导入 ACM 中时，生成此 ARN。

**`signing-parameters`**  
签名的键值对映射。其中可以包括签名过程中要使用的任何信息。  
在创建代码签名配置文件以使用 Code Signing for AWS IoT对 OTA 更新进行签名时，需要使用该参数。

**`platform`**  
要将 OTA 更新分配到的硬件平台的 `platformId`。  
要返回可用的平台及其 `platformId` 值的列表，请使用 `aws signer list-signing-platforms` 命令。

签名作业启动，将已签名的固件映像写入目标 Amazon S3 存储桶。已签名的固件映像的文件名是 GUID。创建流时将需要此文件名。浏览至 Amazon S3 控制台并选择存储桶即可找到此文件名。如果没有看到带有 GUID 文件名的文件，可刷新浏览器。

此命令将显示作业 ARN 和作业 ID。稍后会需要这些值。有关代码签名的更多信息 AWS IoT，请参阅的[代码签名 AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html)。

### 手动签署固件映像
<a name="ota-sign-manual"></a>

对固件映像进行数字签名，并将已签名的固件映像上传到 Amazon S3 存储桶。

## 创建固件更新流
<a name="ota-stream"></a>

流是设备可以使用的数据的抽象接口。流可以隐藏访问存储在不同位置或各种基于云的服务中的数据的复杂性。利用 OTA Update Manager 服务，您可以使用存储在 Amazon S3 中的各个位置的多个数据段来执行 OTA 更新。

创建 O AWS IoT TA 更新时，您还可以创建包含已签名固件更新的流。创建一个 JSON 文件 (`stream.json`)，该文件标识已签名的固件映像。JSON 文件应包含以下内容。

```
[
  {
    "fileId":"your_file_id",
    "s3Location":{
      "bucket":"your_bucket_name",
      "key":"your_s3_object_key"
    }
  }   
]
```

以下是 JSON 文件中的属性：

**`fileId`**  
介于 0–255 之间的任意整数，用于标识固件映像。

**`s3Location`**  
固件到流的存储桶和密钥。    
**`bucket`**  
存储未签名的固件映像的 Amazon S3 存储桶。  
**`key`**  
已签名的固件映像在 Amazon S3 存储桶中的文件名。可以在 Amazon S3 控制台中，通过查看存储桶的内容来找到该值。  
如果您使用代码签名 AWS IoT，则文件名是代码签名为 AWS IoT生成的 GUID。

使用 **create-stream** AWS CLI 命令创建流。

```
aws iot create-stream \
    --stream-id your_stream_id \
    --description your_description \
    --files file://stream.json \
    --role-arn your_role_arn
```

以下是该**create-stream** AWS CLI 命令的参数：

**`stream-id`**  
任意字符串，用于标识流。

**`description`**  
流的描述（可选）。

**`files`**  
JSON 文件的一个或多个引用，包含有关固件映像到流的数据。JSON 文件必须包含以下属性：    
**`fileId`**  
任意文件 ID。  
**`s3Location`**  
存储已签名的固件映像的存储桶名称，以及已签名的固件映像的密钥（文件名）。  
**`bucket`**  
存储已签名的固件映像的 Amazon S3 存储桶。  
**`key`**  
已签名的固件映像的密钥（文件名）。  
当您使用代码签名时 AWS IoT，此密钥是一个 GUID。
下面是一个 `stream.json` 示例文件。  

```
[
    {
        "fileId":123,
        "s3Location": {
            "bucket":"codesign-ota-bucket",
            "key":"48c67f3c-63bb-4f92-a98a-4ee0fbc2bef6"
        }
    }
]
```

**`role-arn`**  
[OTA 服务角色](create-service-role.md)还授予对存储固件映像的 Amazon S3 存储桶的访问权限。

要查找已签名固件映像的 Amazon S3 对象密钥，请使用**aws signer describe-signing-job --job-id *my-job-id***命令显示的任务 ID 在`my-job-id`哪里。**create-signing-job** AWS CLI **describe-signing-job** 命令的输出中包含已签名的固件映像的密钥。

```
... text deleted for brevity ...
  "signedObject": {
    "s3": {
      "bucketName": "ota-bucket",
      "key": "7309da2c-9111-48ac-8ee4-5a4262af4429"
    }
  }
... text deleted for brevity ...
```

## 创建 OTA 更新
<a name="create-ota-update"></a>

使用**create-ota-update** AWS CLI 命令创建 OTA 更新任务。

**注意**  
请勿在 OTA 更新作业 ID 中使用任何个人身份信息 (PII)。个人身份信息示例包括：  
名称。
IP 地址。
电子邮件地址。
位置。
银行详细信息。
医疗信息。

```
aws iot  create-ota-update \
    --ota-update-id value \
    [--description value] \
    --targets value \
    [--protocols value] \
    [--target-selection value] \
    [--aws-job-executions-rollout-config value] \
    [--aws-job-presigned-url-config value] \
    [--aws-job-abort-config value] \
    [--aws-job-timeout-config value] \
    --files value \
    --role-arn value \
    [--additional-parameters value] \
    [--tags value]  \
    [--cli-input-json value] \
    [--generate-cli-skeleton]
```

 `cli-input-json` 格式

```
{
  "otaUpdateId": "string",
  "description": "string",
  "targets": [
    "string"
  ],
  "protocols": [
    "string"
  ],
  "targetSelection": "string",
  "awsJobExecutionsRolloutConfig": {
    "maximumPerMinute": "integer",
    "exponentialRate": {
      "baseRatePerMinute": "integer",
      "incrementFactor": "double",
      "rateIncreaseCriteria": {
        "numberOfNotifiedThings": "integer",
        "numberOfSucceededThings": "integer"
      }
    }
  },
  "awsJobPresignedUrlConfig": {
    "expiresInSec": "long"
  },
  "awsJobAbortConfig": {
    "abortCriteriaList": [
      {
        "failureType": "string",
        "action": "string",
        "thresholdPercentage": "double",
        "minNumberOfExecutedThings": "integer"
      }
    ]
  },
  "awsJobTimeoutConfig": {
    "inProgressTimeoutInMinutes": "long"
  },
  "files": [
    {
      "fileName": "string",
      "fileType": "integer",
      "fileVersion": "string",
      "fileLocation": {
        "stream": {
          "streamId": "string",
          "fileId": "integer"
        },
        "s3Location": {
          "bucket": "string",
          "key": "string",
          "version": "string"
        }
      },
      "codeSigning": {
        "awsSignerJobId": "string",
        "startSigningJobParameter": {
          "signingProfileParameter": {
            "certificateArn": "string",
            "platform": "string",
            "certificatePathOnDevice": "string"
          },
          "signingProfileName": "string",
          "destination": {
            "s3Destination": {
              "bucket": "string",
              "prefix": "string"
            }
          }
        },
        "customCodeSigning": {
          "signature": {
            "inlineDocument": "blob"
          },
          "certificateChain": {
            "certificateName": "string",
            "inlineDocument": "string"
          },
          "hashAlgorithm": "string",
          "signatureAlgorithm": "string"
        }
      },
      "attributes": {
        "string": "string"
      }
    }
  ],
  "roleArn": "string",
  "additionalParameters": {
    "string": "string"
  },
  "tags": [
    {
      "Key": "string",
      "Value": "string"
    }
  ]
}
```


**`cli-input-json` 字段**  

| Name | Type | 说明 | 
| --- | --- | --- | 
| `otaUpdateId` |  字符串  (max:128 min:1)  | 要创建的 OTA 更新的 ID。 | 
| `description` |  字符串  (max:2028)  | OTA 更新的描述。 | 
| `targets` |  列表  | 接收 OTA 更新的目标设备。 | 
| `protocols` |  列表  |  用于传输 OTA 更新映像的协议。有效值为 [HTTP]、[MQTT]、[HTTP, MQTT]。当同时指定 HTTP 和 MQTT 时，目标设备可以选择协议。  | 
| `targetSelection` | 字符串 |  指定更新将继续运行 (CONTINUOUS)，还是在指定作为目标的所有事物完成更新之后完成 (SNAPSHOT)。如果继续运行，则在检测到目标中出现更改时，更新也会在事物上运行。例如，当某个事物添加到目标组时会在该事物上运行更新，即使是组中原有的全部事物已经完成了更新。有效值：CONTINUOUS \$1 SNAPSHOT。 枚举：CONTINUOUS \$1 SNAPSHOT  | 
| `awsJobExecutionsRolloutConfig` |  | 配置 OTA 更新的推广。 | 
| `maximumPerMinute` |  整数  (max:1000 min:1)  | 每分钟启动的最大 OTA 更新任务执行次数。 | 
| `exponentialRate` |  |  任务推出的增速。此参数允许您定义作业推出的指数增长速率。  | 
| `baseRatePerMinute` |  整数  (max:1000 min:1)  |  在作业推出开始时，每分钟接收待处理作业通知的事物的最小数量。这是作业推出的初始速率。  | 
|   `rateIncreaseCriteria`  |   |  启动任务推出速率提高的条件。 AWS IoT 支持小数点后最多一位数字（例如，1.5，但不是 1.55）。  | 
|   `numberOfNotifiedThings`  |  整数  (min:1)  |  当通知此事物数后，推出速率将提高。  | 
|   `numberOfSucceededThings`  |  整数  (min:1)  |  当此事物数在作业执行中成功应用后，推出速率将提高。  | 
| `awsJobPresignedUrlConfig` |  |  预签名的 URLs配置信息。 | 
|   `expiresInSec`  |  长整数 |  预签名的有效时长（以秒 URLs 为单位）。有效值为 60 – 3600，默认值为 1800 秒。收到工作文档的请求时，会生成预签名 URLs 。  | 
|   `awsJobAbortConfig`  |   |  确定作业停止发生时间和方式的条件。 | 
|   `abortCriteriaList`  |  列表  |  确定何时以及如何停止作业的条件列表。 | 
|   `failureType`  |  字符串 |  可以启动作业停止的作业执行失败类型。  枚举：FAILED \$1 REJECTED \$1 TIMED\$1OUT \$1 ALL  | 
|   `action`  |  字符串 |  用于启动作业停止的作业操作类型。  枚举：CANCEL  | 
|   `minNumberOfExecutedThings`  |  整数  (min:1)  |  作业可以停止之前必须接收作业执行通知的事物的最小数量。  | 
|   `awsJobTimeoutConfig`  |   |  指定每个设备完成其任务执行所具有的时间。计时器在任务执行状态设置为 `IN_PROGRESS` 时启动。如果任务执行状态未在时间到期之前设置为其他最终状态，它会自动设置为 `TIMED_OUT`。  | 
|   `inProgressTimeoutInMinutes`  |  长整数 |  指定此设备完成该任务执行所具有的时间，以分钟为单位。超时间隔可以为 1 分钟到 7 天（1 到 10080 分钟）之间的任意长度。进行中计时器无法更新，将应用到该任务的全部任务执行。只要任务执行保持在 IN\$1PROGRESS 状态的时间长度超过了此间隔，任务执行将失败，并切换为最终 `TIMED_OUT` 状态。  | 
|   `files`  |  列表  |  应由 OTA 更新流式处理的文件。 | 
|   `fileName`  |  字符串 |   文件的名称。 | 
|   `fileType`  |  整数  范围 – 最大值：255，最小值：0  |  您可以在作业文档中包含一个整数值，以允许您的设备识别从云接收的文件类型。  | 
|   `fileVersion`  |  字符串 |  文件版本。 | 
|   `fileLocation`  |   |  更新后固件的位置。 | 
|   `stream`  |   |  包含 OTA 的流。 | 
|   `streamId`  |  字符串  (max:128 min:1)  |  流 ID。 | 
|   `fileId`  |  整数  (max:255 min:0)  |  与流关联的文件的 ID。 | 
|   `s3Location`  |   |  更新后固件在 S3 中的位置。 | 
|   `bucket`  |  字符串  (min:1)  |  S3 存储桶。 | 
|   `key`  |  字符串  (min:1)  |  S3 键。 | 
|   `version`  |  字符串 |  S3 存储桶版本。 | 
|   `codeSigning`  |   |  文件的代码签名方法。 | 
|   `awsSignerJobId`  |  字符串 |  为签署文件而创建的 AWSSigner Job 的 ID。 | 
|   `startSigningJobParameter`  |   |  描述代码签名任务。 | 
|   `signingProfileParameter`  |   |  描述代码签名配置文件。 | 
|   `certificateArn`  |  字符串 |  证书 ARN。 | 
|   `platform`  |  字符串 |  您设备的硬件平台。 | 
|   `certificatePathOnDevice`  |  字符串 |  代码签名证书在设备上的位置。 | 
|   `signingProfileName`  |  字符串 |  代码签名配置文件名称。 | 
|   `destination`  |   |  编写代码签名文件的位置。 | 
|   `s3Destination`  |   |  描述更新后固件在 S3 中的位置。 | 
|   `bucket`  |  字符串  (min:1)  |  包含更新后固件的 S3 存储桶。 | 
|   `prefix`  |  字符串 |  S3 前缀。 | 
|   `customCodeSigning`  |   |  用于对文件执行代码签名的自定义方法。 | 
|   `signature`  |   |  文件的签名。 | 
|   `inlineDocument`  |  blob |  代码签署签名的 base64 编码二进制表示形式。 | 
|   `certificateChain`  |   |  证书链。 | 
|   `certificateName`  |  字符串 |  证书的名称。 | 
|   `inlineDocument`  |  字符串 |  代码签名证书链的 base64 编码二进制表示形式。 | 
|   `hashAlgorithm`  |  字符串 |  用于对文件进行代码签名的哈希算法。 | 
|   `signatureAlgorithm`  |  字符串 |  用于对文件进行代码签名的签名算法。 | 
|   `attributes`  |  映射 |   name/attribute 配对清单。 | 
|   `roleArn`  |  字符串  (max:2048 min:20)  |  一个 IAM 角色，用于授予 AWS IoT 访问 Amazon S3、 AWS IoT 任务和 AWS 代码签名资源的访问权限以创建 OTA 更新任务。 | 
|   `additionalParameters`  |  映射 |  其他 OTA 更新参数 (名称/值对) 的列表。 | 
|   `tags`  |  列表  |  可用于管理更新的元数据。 | 
|   `Key`  |  字符串  (max:128 min:1)  |  标签的键。 | 
|   `Value`  |  字符串  (max:256 min:1)  |  标签的值。 | 

Output

```
{
  "otaUpdateId": "string",
  "awsIotJobId": "string",
  "otaUpdateArn": "string",
  "awsIotJobArn": "string",
  "otaUpdateStatus": "string"
}
```


**AWS CLI 输出字段**  

|  Name |  Type |  说明 | 
| --- | --- | --- | 
|   `otaUpdateId`  |  字符串  (max:128 min:1)  |  OTA 更新 ID。 | 
|   `awsIotJobId`  |  字符串 |  与 OTA 更新关联的 AWS IoT 任务 ID。 | 
|   `otaUpdateArn`  |  字符串 |  OTA 更新 ARN。 | 
|   `awsIotJobArn`  |  字符串 |  与 OTA 更新相关的 AWS IoT 任务 ARN。 | 
|   `otaUpdateStatus`  |  字符串 |  OTA 更新状态。  枚举：CREATE\$1PENDING \$1 CREATE\$1IN\$1PROGRESS \$1 CREATE\$1COMPLETE \$1 CREATE\$1FAILED  | 

以下是传递到使用代码签名的**create-ota-update**命令中的 JSON 文件的示例 AWS IoT。

```
[
  {
    "fileName": "firmware.bin",                
    "fileType": 1,
    "fileLocation": {
      "stream": {
        "streamId": "004",                         
        "fileId":123
      }                        
    },
    "codeSigning": {
      "awsSignerJobId": "48c67f3c-63bb-4f92-a98a-4ee0fbc2bef6"     
    }
  }
]
```

以下是传递到**create-ota-update** AWS CLI 命令中的 JSON 文件的示例，该文件使用内联文件提供自定义代码签名材料。

```
[
  {
    "fileName": "firmware.bin",
    "fileType": 1,
    "fileLocation": {
      "stream": {
        "streamId": "004",
        "fileId": 123
      }
    },
    "codeSigning": {
      "customCodeSigning":{
        "signature":{
          "inlineDocument":"your_signature"
        },
        "certificateChain": {
          "certificateName": "your_certificate_name",
          "inlineDocument":"your_certificate_chain"
        },
        "hashAlgorithm":"your_hash_algorithm",
        "signatureAlgorithm":"your_signature_algorithm"
      }
    }
  }
]
```

以下是传递到**create-ota-update** AWS CLI 命令中的 JSON 文件的示例，该文件允许 FreeRTOS OTA 启动代码签名任务并创建代码签名配置文件和直播。

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "startSigningJobParameter":{
        "signingProfileName": "myTestProfile",
        "signingProfileParameter": {
          "certificateArn": "your_certificate_arn",
          "platform": "your_platform_id",
          "certificatePathOnDevice": "certificate_path"
        },
        "destination": {
          "s3Destination": {
            "bucket": "your_destination_bucket"
          }
        }
      }
    }  
  }
]
```

以下是传递到**create-ota-update** AWS CLI 命令中的 JSON 文件的示例，该文件用于创建 OTA 更新，该更新使用现有配置文件启动代码签名任务并使用指定的流。

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_s3_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "startSigningJobParameter":{
        "signingProfileName": "your_unique_profile_name",
        "destination": {
          "s3Destination": {
            "bucket": "your_destination_bucket"
          }
        }
      }
    }  
  }
]
```

以下是传递到**create-ota-update** AWS CLI 命令中的 JSON 文件的示例，该文件允许 FreeRTOS OTA 使用现有代码签名任务 ID 创建流。

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "codeSigning":{
      "awsSignerJobId": "your_signer_job_id"
    }  
  }
]
```

以下是传递到创建 OTA 更新的**create-ota-update** AWS CLI 命令中的 JSON 文件的示例。该更新根据指定的 S3 对象创建一个流，并使用自定义代码签名。

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "customCodeSigning": {
        "signature":{
          "inlineDocument":"your_signature"
        },
        "certificateChain": {
          "inlineDocument":"your_certificate_chain",
          "certificateName": "your_certificate_path_on_device"
        },
        "hashAlgorithm":"your_hash_algorithm",
        "signatureAlgorithm":"your_sig_algorithm"
      }
    }  
  }
]
```

## 列出 OTA 更新
<a name="list-ota-updates"></a>

您可以使用**list-ota-updates** AWS CLI 命令获取所有 OTA 更新的列表。

```
aws iot list-ota-updates
```

**list-ota-updates** 命令输出如下所示。

```
{
  "otaUpdates": [
     
    {
      "otaUpdateId": "my_ota_update2",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update2",
      "creationDate": 1522778769.042
    },
    {
      "otaUpdateId": "my_ota_update1",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update1",
      "creationDate": 1522775938.956
    },
    {
      "otaUpdateId": "my_ota_update",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update",
      "creationDate": 1522775151.031
    }
  ]
}
```

## 获取有关 OTA 更新的信息
<a name="get-ota-updates"></a>

您可以使用**get-ota-update** AWS CLI 命令获取 OTA 更新的创建或删除状态。

```
aws iot get-ota-update --ota-update-id your-ota-update-id
```

**get-ota-update** 命令的输出如下所示。

```
{ 
    "otaUpdateInfo": { 
        "otaUpdateId": "ota-update-001", 
        "otaUpdateArn": "arn:aws:iot:region:123456789012:otaupdate/ota-update-001", 
        "creationDate": 1575414146.286, 
        "lastModifiedDate": 1575414149.091, 
        "targets": [ 
            "arn:aws:iot:region:123456789012:thing/myDevice" 
        ], 
        "protocols": [ "HTTP" ], 
        "awsJobExecutionsRolloutConfig": { 
            "maximumPerMinute": 0 
        }, 
        "awsJobPresignedUrlConfig": { 
            "expiresInSec": 1800 
        }, 
        "targetSelection": "SNAPSHOT", 
        "otaUpdateFiles": [ 
            { 
                "fileName": "my_firmware.bin", 
                "fileType": 1,
                "fileLocation": { 
                    "s3Location": { 
                        "bucket": "my-bucket", 
                        "key": "my_firmware.bin", 
                        "version": "AvP3bfJC9gyqnwoxPHuTqM5GWENt4iii" 
                    } 
                }, 
                "codeSigning": { 
                    "awsSignerJobId": "b7a55a54-fae5-4d3a-b589-97ed103737c2", 
                    "startSigningJobParameter": { 
                        "signingProfileParameter": {}, 
                        "signingProfileName": "my-profile-name", 
                        "destination": { 
                            "s3Destination": { 
                                "bucket": "some-ota-bucket", 
                                "prefix": "SignedImages/" 
                            } 
                        } 
                    }, 
                    "customCodeSigning": {} 
                } 
            } 
        ], 
        "otaUpdateStatus": "CREATE_COMPLETE", 
        "awsIotJobId": "AFR_OTA-ota-update-001", 
        "awsIotJobArn": "arn:aws:iot:region:123456789012:job/AFR_OTA-ota-update-001" 
    } 
}
```

`otaUpdateStatus` 返回的值包括：

**`CREATE_PENDING`**  
OTA 更新的创建正在等待处理。

**`CREATE_IN_PROGRESS`**  
正在创建 OTA 更新。

**`CREATE_COMPLETE`**  
OTA 更新已创建。

**`CREATE_FAILED`**  
OTA 更新的创建失败。

**`DELETE_IN_PROGRESS`**  
正在删除 OTA 更新。

**`DELETE_FAILED`**  
OTA 更新的删除失败。

**注意**  
要在创建 OTA 更新后获取其执行状态，您需要使用 **describe-job-execution** 命令。有关更多信息，请参阅[描述作业执行](https://docs.aws.amazon.com/iot/latest/developerguide/manage-job-cli.html#describe-job-execution)。

## 删除与 OTA 相关的数据
<a name="delete-ota-data"></a>

目前，您无法使用 AWS IoT 控制台删除直播或 OTA 更新。您可以使用删除直播、OTA 更新以及在 OTA 更新期间创建的 AWS IoT 任务。 AWS CLI 

### 删除 OTA 流
<a name="delete-ota-stream"></a>

在创建使用 MQTT 的 OTA 更新时，您可以使用命令行或 AWS IoT 控制台创建流，将固件分成多个块，以便通过 MQTT 发送。您可以使用**delete-stream** AWS CLI 命令删除此流，如以下示例所示。

```
aws iot delete-stream --stream-id your_stream_id
```

### 删除 OTA 更新
<a name="delete-ota-update"></a>

在创建 OTA 更新时，将创建以下各项：
+ OTA 更新作业数据库中的一个条目。
+ 执行更新的 AWS IoT 任务。
+ 每台正在更新的设备执行的 AWS IoT 任务。

**delete-ota-update** 命令仅删除 OTA 更新作业数据库中的条目。必须使用 **delete-job** 命令来删除 AWS IoT 作业。

可以使用 **delete-ota-update** 命令删除一个 OTA 更新。

```
aws iot delete-ota-update --ota-update-id your_ota_update_id
```

**`ota-update-id`**  
要删除的 OTA 更新的 ID。

**`delete-stream`**  
删除与 OTA 更新关联的流。

**`force-delete-aws-job`**  
删除与 OTA 更新关联的 AWS IoT 任务。如果未设置此标记且任务处于 `In_Progress` 状态，则作业不会被删除。

### 删除为 OTA 更新创建的 IoT 作业
<a name="delete-ota-job"></a>

当你创建 OTA 更新时，FreeRTOS 会 AWS IoT 创建一个任务。也会为处理作业的每个设备创建作业执行。您可以使用**delete-job** AWS CLI 命令删除作业及其关联的任务执行。

```
aws iot delete-job --job-id your-job-id --no-force
```

`no-force` 参数指定只能删除处于结束状态（COMPLETED 或 CANCELLED）的作业。可以通过传递 `force` 参数来删除处于非结束状态的作业。有关更多信息，请参阅 [ DeleteJob API](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteJob.html)。

**注意**  
如果删除状态为 IN\$1PROGRESS 的作业，则设备上处于 IN\$1PROGRESS 状态的任何作业执行都将中断，并可能导致设备处在不确定的状态。请确保已删除的正在执行作业的每个设备都可以恢复到已知状态。

删除作业可能需要几分钟时间，具体取决于为作业创建的作业执行数量以及其他因素。在删除作业的过程中，其状态为 DELETION\$1IN\$1PROGRESS。试图删除或取消已处于 DELETION\$1IN\$1PROGRESS 状态的作业将导致错误。

可以使用 **delete-job-execution** 删除作业执行。如果设备数量太少无法处理作业，您可能希望删除作业执行。这会删除单个设备的作业执行，如以下示例中所示。

```
aws iot delete-job-execution --job-id your-job-id --thing-name
                    your-thing-name --execution-number your-job-execution-number --no-force
```

与**delete-job** AWS CLI 命令一样，您可以将`--force`参数传递**delete-job-execution**给以强制删除任务执行。有关更多信息，请参阅 [DeleteJobExecutionAPI](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteJobExecution.html)。

**注意**  
如果删除状态为 IN\$1PROGRESS 的作业执行，则设备上处于 IN\$1PROGRESS 状态的任何作业执行都将中断，并可能导致设备处在不确定的状态。请确保已删除的正在执行作业的每个设备都可以恢复到已知状态。

有关使用 OTA 更新应用程序的更多信息，请参阅[Over-the-air 更新演示应用程序](ota-demo.md)。