使用 AWS CLI 创建 OTA 更新 - FreeRTOS
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

使用 AWS CLI 创建 OTA 更新

在使用 AWS CLI 创建 OTA 更新时,您将:

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

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

  3. 启动 OTA 更新作业。

对固件更新进行数字签名

在使用 AWS CLI 执行 OTA 更新时,可以自行对固件更新进行签名。您必须先对固件二进制文件进行签名,然后才能将其上传到 Amazon S3。

Code Signing for AWS IoT 在以下区域中不可用:

  • 中国(北京)cn-north-1

  • 中国(宁夏)cn-northwest-1

手动签署固件映像

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

创建固件更新流

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

在创建 AWS IoT OTA 更新时,还可以创建包含已签名的固件更新的流。创建一个 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 控制台中,通过查看存储桶的内容来找到该值。

如果使用的是 Code Signing for AWS IoT,则文件名是 Code Signing for AWS IoT 生成的 GUID。

可以使用 create-stream CLI 命令创建一个流。

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

以下是 create-stream CLI 命令的参数:

stream-id

任意字符串,用于标识流。

description

流的描述(可选)。

files

JSON 文件的一个或多个引用,包含有关固件映像到流的数据。JSON 文件必须包含以下属性:

fileId

任意文件 ID。

s3Location

存储已签名的固件映像的存储桶名称,以及已签名的固件映像的密钥(文件名)。

bucket

存储已签名的固件映像的 Amazon S3 存储桶。

key

已签名的固件映像的密钥(文件名)。

如果使用 Code Signing for AWS IoT,则此密钥为 GUID。

下面是一个 stream.json 示例文件。

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

OTA 服务角色还授予对存储固件映像的 Amazon S3 存储桶的访问权限。

要查找已签名的固件映像的 Amazon S3 对象密钥,可使用 aws signer describe-signing-job --job-id my-job-id 命令,其中 my-job-idcreate-signing-job CLI 命令所显示的作业 ID。describe-signing-job 命令的输出中包含已签名的固件映像的密钥。

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

如果您看到 "Error: You have exceeded the limit for the number of streams in your AWS account.",请参阅 您的 AWS 账户已超过流限制

创建 OTA 更新

可以使用 create-ota-update 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", "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 字段

名称

类型

描述

otaUpdateId

字符串

(max:128 min:1)

要创建的 OTA 更新的 ID。

description

字符串

(max:2028)

OTA 更新的描述。

targets

list

接收 OTA 更新的目标设备。

protocols

list

用于传输 OTA 更新映像的协议。有效值为 [HTTP]、[MQTT]、[HTTP, MQTT]。当同时指定 HTTP 和 MQTT 时,目标设备可以选择协议。

targetSelection

字符串

指定更新将继续运行 (CONTINUOUS),还是在指定作为目标的所有事物完成更新之后完成 (SNAPSHOT)。如果继续运行,则在检测到目标中出现更改时,更新也会在事物上运行。例如,当某个事物添加到目标组时会在该事物上运行更新,即使是组中原有的全部事物已经完成了更新。有效值:CONTINUOUS | SNAPSHOT。

枚举:CONTINUOUS | SNAPSHOT

awsJobExecutionsRolloutConfig

配置 OTA 更新的推广。

maximumPerMinute

integer

(max:1000 min:1)

每分钟启动的最大 OTA 更新任务执行次数。

exponentialRate

作业推出的增速。此参数允许您定义作业推出的指数增长速率。

baseRatePerMinute

integer

(max:1000 min:1)

在作业推出开始时,每分钟接收待处理作业通知的事物的最小数量。这是作业推出的初始速率。

rateIncreaseCriteria

启动作业推出速率提高的条件。

AWS IoT 最多支持小数点后一位(例如,支持 1.5,但不支持 1.55)。

numberOfNotifiedThings

integer

(min:1)

当通知此事物数后,推出速率将提高。

numberOfSucceededThings

integer

(min:1)

当此事物数在作业执行中成功应用后,推出速率将提高。

awsJobPresignedUrlConfig

预签名 URL 的配置信息。

expiresInSec

long

预签名 URL 的有效时间长度 (以秒为单位)。有效值为 60 – 3600,默认值为 1800 秒。收到作业文档请求时,将生成预签名 URL。

awsJobAbortConfig

确定作业中止发生时间和方式的条件。

abortCriteriaList

list

确定何时以及如何中止作业的条件列表。

failureType

字符串

可以启动作业中止的作业执行失败类型。

枚举:FAILED | REJECTED | TIMED_OUT | ALL

action

字符串

用于启动作业中止的作业操作类型。

枚举:CANCEL

minNumberOfExecutedThings

integer

(min:1)

作业可以中止之前必须接收作业执行通知的事物的最小数量。

awsJobTimeoutConfig

指定每个设备完成其作业执行所具有的时间。计时器在作业执行状态设置为 IN_PROGRESS 时启动。如果任务执行状态未在时间到期之前设置为其他最终状态,它会自动设置为 TIMED_OUT

inProgressTimeoutInMinutes

long

指定此设备完成该作业执行所具有的时间,以分钟为单位。超时间隔可以为 1 分钟到 7 天(1 到 10080 分钟)之间的任意长度。进行中计时器无法更新,将应用到该任务的全部任务执行。只要任务执行保持在 IN_PROGRESS 状态的时间长度超过了此间隔,任务执行将失败,并切换为最终 TIMED_OUT 状态。

files

list

应由 OTA 更新流式处理的文件。

fileName

字符串

文件的名称。

fileVersion

字符串

文件版本。

fileLocation

更新后固件的位置。

stream

包含 OTA 的流。

streamId

字符串

(max:128 min:1)

流 ID。

fileId

integer

(max:255 min:0)

与流关联的文件的 ID。

s3Location

更新后固件在 S3 中的位置。

bucket

字符串

(min:1)

S3 存储桶。

key

字符串

(min:1)

S3 键。

version

字符串

S3 存储桶版本。

codeSigning

文件的代码签名方法。

awsSignerJobId

字符串

已创建用于对文件签名的 AWSSignerJob 的 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

map

名称/属性对的列表。

roleArn

字符串

(max:2048 min:20)

授予 AWS IoT 访问 Amazon S3、AWS IoT 作业和 AWS 代码签名资源的权限以创建 OTA 更新任务的 IAM 角色。

additionalParameters

map

其他 OTA 更新参数 (名称/值对) 的列表。

tags

list

可用于管理更新的元数据。

Key

字符串

(max:128 min:1)

标签的键。

Value

字符串

(max:256 min:1)

标签的值。

输出

{ "otaUpdateId": "string", "awsIotJobId": "string", "otaUpdateArn": "string", "awsIotJobArn": "string", "otaUpdateStatus": "string" }
CLI 输出字段

名称

类型

描述

otaUpdateId

字符串

(max:128 min:1)

OTA 更新 ID。

awsIotJobId

字符串

与 OTA 更新关联的 AWS IoT 任务 ID。

otaUpdateArn

字符串

OTA 更新 ARN。

awsIotJobArn

字符串

与 OTA 更新关联的 AWS IoT 任务 ARN。

otaUpdateStatus

字符串

OTA 更新状态。

枚举:CREATE_PENDING | CREATE_IN_PROGRESS | CREATE_COMPLETE | CREATE_FAILED

以下示例说明了如何将 JSON 文件传递到 create-ota-update 命令,该命令使用 Code Signing for AWS IoT。

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

以下示例说明了如何将 JSON 文件传递到 create-ota-update CLI 命令,该命令使用内联文件提供自定义代码签名材料。

[ { "fileName": "firmware.bin", "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" } } } ]

以下示例说明了如何将 JSON 文件传递到 create-ota-update CLI 命令,该命令允许 FreeRTOS OTA 启动代码签名作业并创建代码签名配置文件和流。

[ { "fileName": "your_firmware_path_on_device", "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" } } } } } ]

以下示例说明了如何将 JSON 文件传递到 create-ota-update CLI 命令,该命令创建一个 OTA 更新以使用现有配置文件启动代码签名作业并使用指定的流。

[ { "fileName": "your_firmware_path_on_device", "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" } } } } } ]

以下示例说明了如何将 JSON 文件传递到 create-ota-update CLI 命令,该命令允许 FreeRTOS OTA 使用现有代码签名作业 ID 创建一个流。

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

以下示例说明了如何将 JSON 文件传递到 create-ota-update CLI 命令,该命令创建一个 OTA 更新。该更新根据指定的 S3 对象创建一个流,并使用自定义代码签名。

[ { "fileName": "your_firmware_path_on_device", "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" } } } ]
注意

如果您看到 "Error: You have exceeded the limit for the number of streams in your AWS account.",请参阅 您的 AWS 账户已超过流限制

列出 OTA 更新

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

aws iot list-ota-updates

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

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

获取有关 OTA 更新的信息

您可以使用 get-ota-update 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:us-west-2:123456789012:otaupdate/ota-update-001", "creationDate": 1575414146.286, "lastModifiedDate": 1575414149.091, "targets": [ "arn:aws:iot:us-west-2:123456789012:thing/myDevice" ], "protocols": [ "HTTP" ], "awsJobExecutionsRolloutConfig": { "maximumPerMinute": 0 }, "awsJobPresignedUrlConfig": { "expiresInSec": 1800 }, "targetSelection": "SNAPSHOT", "otaUpdateFiles": [ { "fileName": "my_firmware.bin", "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:us-west-2: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 命令。有关更多信息,请参阅描述作业执行

删除与 OTA 相关的数据

目前还不能使用 AWS IoT 控制台来删除流或 OTA 更新。可以使用 AWS CLI 来删除流、OTA 更新以及在 OTA 更新过程中创建的 AWS IoT 作业。

删除 OTA 流

在创建使用 MQTT 的 OTA 更新时,可以使用命令行或 AWS IoT 控制台创建流,以将固件分割为多个数据块,以便能通过 MQTT 进行发送。您可以使用 delete-stream CLI 命令删除该流,如以下示例中所示。

aws iot delete-stream --stream-id your_stream_id

删除 OTA 更新

在创建 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 作业

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

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

no-force 参数指定只能删除处于结束状态(COMPLETED 或 CANCELLED)的作业。可以通过传递 force 参数来删除处于非结束状态的作业。有关更多信息,请参阅 DeleteJob API

注意

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

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

可以使用 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 CLI 命令一样,可以将 --force 参数传递到 delete-job-execution 以强制删除作业执行。有关更多信息,请参阅 DeleteJobExecution API

注意

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

有关使用 OTA 更新应用程序的更多信息,请参阅无线更新演示应用程序