使用低功耗蓝牙执行无线更新 - FreeRTOS
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

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

使用低功耗蓝牙执行无线更新

Introduction

您可以使用 FreeRTOS 低功耗蓝牙 (BLE) 和无线更新 (OTA) 库,通过在配套设备上运行的 MQTT 代理,通过低功耗蓝牙对微控制器设备执行固件更新。将使用 AWS IoT OTA 作业执行更新。配套设备使用演示应用程序中输入的 AWS IoT 凭证连接到 Amazon Cognito。授权操作员从云中启动 OTA 更新。当设备通过演示应用程序进行连接时,OTA 更新将启动并在设备上更新固件。

Prerequisites

  1. 将“无线更新”代理移植到各个微控制器设备:

  2. 将低功耗蓝牙库移植到每个微控制器中:

  3. 如果您还没有 AWS 账户,请设置一个 (免费套餐已足够)。

  4. 您必须有权访问 Android 手机作为装有 Android v 6.0 或更高版本和蓝牙版本 4.2 或更高版本的配套设备。

  5. 使用以下项设置开发平台:

    • Android Studio。

    • 已安装 AWS CLI。

    • 安装了 Python3。

    • 适用于 Python 的 boto3 AWS 软件开发人员工具包 (SDK)。

Setup

以下是设置所需的步骤的概述。如果您已完成步骤 1 和 2,则可跳过这些步骤来通过 WiFi 或以太网测试通过无线更新。

  1. 配置存储— 创建 S3 存储桶和策略,并配置可执行更新的 IAM 用户。

  2. 创建代码签名证书— 创建签名证书并允许 IAM 用户签署固件更新。

  3. 配置 Amazon Cognito 身份验证— 创建凭证提供程序、用户池和应用程序对用户池的访问权限。

  4. 配置 Amazon FreeRTOS— 设置低功耗蓝牙、客户端凭证和代码签名公有证书。

  5. 配置 Android 应用程序— 设置凭证提供程序和用户池,然后将应用程序部署到 Android 设备。

步骤 1: 配置存储

您可以通过启动 AWS CloudFormation 模板跳过这些步骤。

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

  2. 创建 OTA 更新服务角色并向该角色添加以下托管策略:

    • AWSIotLogging

    • AWSIotRuleActions

    • AWSIotThingsRegistration

    • AWSFreeRTOSOTAUpdate

  3. 向角色添加内联策略以允许该角色执行 AWS IoT 操作并允许访问您创建的 S3 存储桶。

  4. 创建可执行 OTA 更新的 IAM 用户。此用户可以对账户中的 AWS IoT 设备签名并部署固件更新,并且可以在所有设备上执行 OTA 更新。访问权限应限制为可信实体。

  5. 使用 OTA 用户策略附加权限

  6. 创建允许创建的 IAM 用户签署固件的内联策略

步骤 2: 创建代码签名证书

创建可用于对固件进行签名的代码签名证书。在导入证书时记下证书 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 myOTAProfile --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/myOTAProfile" }

步骤 3: 配置 Amazon Cognito 身份验证

AWS IoT 配置

首先,设置 AWS IoT 事物和策略。由于我们在将使用 Amazon Cognito 进行身份验证的 Android 手机上使用 MQTT 代理,设备无需 AWS IoT 证书。

在创建 AWS IoT 策略之前,您需要知道 AWS 区域和 AWS 账号。

步骤 3a: 创建 AWS IoT 策略

  1. 登录到 AWS IoT 控制台

  2. 在右上角,选择您的账户,在 My Account (我的账户) 下记下您的 12 位账户 ID。

  3. 在左侧导航窗格中,选择 Settings (设置)。在 Custom endpoint (自定义终端节点) 下,记下终端节点值。终端节点应类似于“xxxxxxxxxxxxxx.iot。us-west-2.amazonaws.com”。在此示例中,AWS 区域是“us-west-2”。

  4. 在左侧导航窗格中,依次选择 Secure (安全)Policies (策略)Create (创建)

  5. 如果您尚未在账户中创建策略,您将看到消息“You don’t have any policies yet”,您应选择 Create a policy

  6. 输入策略的名称(例如,“mqtt_proxy_iot_policy”)。

  7. 添加语句部分中,选择高级模式。将以下 JSON 复制并粘贴到策略编辑器窗口中。将“aws-account-id”替换为您的账户 ID(步骤 2)。将“aws-region”替换为您的区域,例如“us-west-2”(步骤 3)。

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "arn:aws:iot:aws-region:aws-account-id:*" }, { "Effect": "Allow", "Action": "iot:Publish", "Resource": "arn:aws:iot:aws-region:aws-account-id:*" }, { "Effect": "Allow", "Action": "iot:Subscribe", "Resource": "arn:aws:iot:aws-region:aws-account-id:*" }, { "Effect": "Allow", "Action": "iot:Receive", "Resource": "arn:aws:iot:aws-region:aws-account-id:*" } ] }
  8. 选择创建

步骤 3b: 创建 AWS IoT 事物

  1. 登录到 AWS IoT 控制台

  2. 在左侧导航窗格中选择管理,然后选择事物。在右上角,选择 Create (创建)

  3. 如果您的账户中未注册任何 IoT 事物,则会显示消息“You don’t have any things yet (您还没有任何事物)”,并且您应选择 Register a thing (注册事物)

  4. 创建 AWS IoT 事物页面上,选择创建单个事物

  5. Add your device to the thing registry (将您的设备添加到事物注册表) 页面上,输入事物的名称(例如,“my_thing”)。仅允许使用字母数字字符、连字符 (“-”) 和下划线 (“_”)。选择下一步

  6. Add a certificate for your thing (添加事物的证书) 页面上的 Skip certificate and create thing (跳过证书和创建事物) 下,选择 Create thing without certificate (创建没有证书的事物)

    由于我们使用的是使用 Amazon Cognito 凭证进行身份验证和授权的 BLE 代理移动应用程序,因此无需设备证书。

Amazon Cognito 配置

Amazon Cognito 是 MQTT 代理移动应用程序的身份验证所必需的。IAM 策略将附加到经过身份验证的身份,以允许委托人将 AWS IoT 策略附加到凭证。

步骤 3c: 设置 Amazon Cognito 用户池

  1. 登录到 Amazon Cognito 控制台

  2. 在右侧导航区域中,选择 Create a user pool

  3. 输入池名称(例如,“mqtt_proxy_user_pool”)。

  4. 选择 Review defaults

  5. App Clients (应用程序客户端) 旁边,单击 Add app client... (添加应用程序客户端...),然后选择 Add an app client (添加应用程序客户端)

  6. 输入应用程序客户端名称(例如“mqtt_app_client”)。

  7. 确保选择了 Generate client secret (生成客户端密钥)

  8. 选择 Create app client

  9. 选择返回池详细信息

  10. 在用户池的 Review (审核) 页面上,选择 Create pool (创建池)

  11. 您应看到一条消息,说明“您的用户池已成功创建。”

  12. 记下“Pool ID”。

  13. 在左侧导航窗格中,选择 App clients (应用程序客户端)

  14. 单击 Show Details (显示详细信息)

  15. 记下“App client ID (应用程序客户端 ID)”和“App client secret (应用程序客户端密钥)”。

步骤 3d:Amazon Cognito 身份池

  1. 登录到 Amazon Cognito 控制台

  2. 选择 Create new identity pool (创建新身份池)

  3. 输入身份池的名称(例如,“mqtt_proxy_identity_pool”)。

  4. 展开 Authentication providers

  5. 选择 Cognito 选项卡。

  6. 输入您在“步骤 3c: 设置 Amazon Cognito 用户池”。

  7. 选择 Create Pool

  8. 在下一页上,选择 Allow 以便为经过身份验证和未经身份验证的身份创建新角色。

  9. 记下格式为“us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxxxxxxx”的 Identity pool ID (身份池 ID)

接下来,我们将 IAM 策略附加到经过身份验证的身份,以便凭证可以向该身份附加 IoT 策略。

步骤 3e: 将 IAM 策略附加到经过身份验证的身份

  1. 打开 Amazon Cognito 控制台。

  2. 选择您刚刚创建的身份池 (例如,“mqtt_proxy_identity_pool”)。

  3. 选择编辑身份池

  4. 记下分配给经过身份验证的角色的 IAM 角色 (例如,“Cognito_mqtt_proxy_identity_poolAuth_Role”)。

  5. 打开 IAM 控制台

  6. 在导航窗格中,选择角色

  7. 搜索角色 (例如,“Cognito_mqtt_proxy_identity_poolAuth_Role”),然后选择它。

  8. 选择 Add inline policy (添加内联策略),然后选择 JSON

  9. 输入以下策略:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:AttachPolicy", "iot:AttachPrincipalPolicy", "iot:Connect", "iot:Publish", "iot:Subscribe", "iot:Receive" ], "Resource": "*" } ] }
  10. 选择查看策略

  11. 输入策略名称(例如,“mqttProxyCognitoPolicy”)。

  12. 选择 Create policy (创建策略)

步骤 4: 配置 FreeRTOS

启用 OTA 更新演示,如下所示:

注意

在演示运行程序中,一次只能启用一个演示。

  1. 打开 vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h

    • 定义 CONFIG_OTA_UPDATE_DEMO_ENABLED

    • democonfigNETWORK_TYPES 更改为 AWSIOT_NETWORK_TYPE_BLE

  2. 打开 demos/include/aws_clientcredential.h:

    • clientcredentialMQTT_BROKER_ENDPOINT[] 中更改终端节点 URL。

    • clientcredentialIOT_THING_NAME 中将事物名称更改为您的事物的名称(例如,“my_thing”)。

      注意

      使用 Amazon Cognito 凭证时,不必添加证书。

  3. 打开 vendors/vendor/boards/board/aws_demos/common/config_files/aws_iot_network_config.h

    • configSUPPORTED_NETWORKSconfigENABLED_NETWORKS 更改为仅包含 AWSIOT_NETWORK_TYPE_BLE

  4. 打开 demos/include/aws_ota_codesigner_certificate.h:

    • 更改 signingcredentialSIGNING_CERTIFICATE_PEM 以引用用于对固件二进制文件签名的证书。

    该应用程序应启动并打印演示版本:

    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 应用程序

amazon-freertos-ble-android-sdk GitHub 存储库下载 Android 低功耗蓝牙软件开发工具包和示例应用程序。

进行以下更改:

  1. 修改文件 app/src/main/res/raw/awsconfiguration.json:

    使用以下示例 JSON 中的说明填写“PoolId”、“Region”、“AppClientId”和“AppClientSecret”字段。

    { "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 -> mqtt_proxy_user_pool -> General Settings -> PoolId", "AppClientId": "Cognito-> Manage User Pools -> mqtt_proxy_user_pool -> General Settings -> App clients ->Show Details", "AppClientSecret": "Cognito-> Manage User Pools -> mqtt_proxy_user_pool -> General Settings -> App clients ->Show Details", "Region": "Your region (for example us-east-1)" } } }
  2. 修改文件 app/src/main/java/software/amazon/freertos/DemoConstants.java:

    • 指定您之前创建的策略名称 (例如,“mqtt_proxy_iot_policy”)。

    • 设置区域 (例如,“us-east-1”)。

  3. 构建并安装演示应用程序:

    1. 在 Android Studio 中,依次选择 BuildMake Module app

    2. 选择 Run (运行)Run app (运行应用程序)。您可以转到 Android Studio 中的 logcat 窗口窗格来监控日志消息。

    3. 在 Android 设备上,从登录屏幕创建账户。

    4. 创建用户。如果用户已存在,请输入用户的凭证。

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

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

    7. 将找到的设备的滑块移动到 On (打开)

    8. 在串行端口调试控制台上按 'y'

    9. 选择 Pair & Connect (配对并连接)

More... (更多...) 链接在连接后变为活动状态。连接完成后,您应该会在 Android 设备 logcat 中看到连接状态变为 BLE_CONNECTED:

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

设备和 Android 设备必须先协商 MTU,然后才能传输消息。FreeRTOS您应在 logcat 中看到以下输出:

2019-06-06 20:11:46.720 23484-23497/software.amazon.freertos.demo I/FRD: onMTUChanged : 512 status: Success

设备连接到应用程序并开始使用 MQTT 代理发送 MQTT 消息。要确认设备可以进行通信,请确保您能够看到 MQTT_CONTROL 特性数据值更改为 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:

在微控制器控制台上完成配对

当设备与 Android 设备配对时,系统会提示您在控制台上按“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.

Testing

  1. 要安装先决条件,请运行以下命令:

    pip3 install boto3 pip3 install pathlib
  2. 下载 python 脚本。

  3. 在 FreeRTOS 中凹凸 demos/include/aws_application_version.h 应用程序版本并构建一个新的二进制文件。

  4. 要获取帮助,请在终端窗口中运行以下命令:

    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)
  5. 如果您使用提供的 AWS CloudFormation 模板创建资源,以下是示例运行:

    python3 start_ota_stream.py --profile otausercf --name my_thing --role ota_ble_iot_role-sample --s3bucket afr-ble-ota-update-bucket-sample --otasigningprofile abcd --signingcertificateid certificateid

Validation

  1. 在控制台中,日志显示 OTA 更新已开始,文件块下载正在进行中:

    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
  2. OTA 更新完成后,设备将使用更新后的固件重新启动,再次连接到 Android 应用程序,然后执行自检。

  3. 如果自检成功,则更新后的固件将标记为活动,并且您应在控制台中看到更新后的版本:

    13 13498 [iot_thread] OTA demo version 0.9.21

References