将 OTA 代理集成到应用程序中 - FreeRTOS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

将 OTA 代理集成到应用程序中

无线 (OTA) 代理旨在简化为将 OTA 更新功能添加到产品中所必须编写的代码。集成负担主要包括 OTA 代理的初始化,以及创建自定义回调函数以响应 OTA 代理完成事件消息。在操作系统初始化期间,MQTT、HTTP(如果文件下载使用 HTTP)和平台特定实现 (PAL) 接口将传递给 OTA 代理。也可以初始化缓冲区并将其传递给 OTA 代理。

注意

尽管将 OTA 更新功能集成到应用程序中非常简单,但 OTA 更新系统需要了解的不仅仅是设备代码集成。要熟悉如何配置 Amazon 账户的 Amazon IoT 事物、凭证、代码签名证书、预配置设备和 OTA 更新作业,请参阅 FreeRTOS 先决条件

连接管理

OTA 代理使用 MQTT 协议完成所有涉及 Amazon IoT 服务的控制通信操作,但它并不管理 MQTT 连接。要确保 OTA 代理不会干扰应用程序的连接管理策略,必须由主用户应用程序处理 MQTT 连接(包括断开连接和任何重新连接功能)。可以通过 MQTT 或 HTTP 协议下载该文件。可以在创建 OTA 作业时选择协议。如果选择 MQTT,则 OTA 代理将使用相同的连接来控制操作和下载文件。

简单的 OTA 演示

下面是一个简单的 OTA 演示节选,说明了代理如何连接到 MQTT 代理并初始化 OTA 代理。在该示例中,我们对演示进行配置,使用默认的 OTA 应用程序回调,并每一秒返回一次某些统计数据。为简洁起见,我们省略了演示的某些细节。

OTA 演示还通过监控断开回调连接并重新建立连接来演示 MQTT 连接管理。当断开连接时,此演示会先暂停 OTA 代理操作,然后尝试重新建立 MQTT 连接。MQTT 重新连接尝试会延迟一段时间,该时间以指数方式增加到最大值,并且还会增加抖动。如果重新建立连接,OTA 代理将继续运行。

有关使用 Amazon IoT MQTT 代理的工作示例,请参阅 demos/ota 目录中的 OTA 演示代码。

由于 OTA 代理是它自己的任务,该示例中刻意的一秒延迟只会影响本应用程序。对代理的性能不会有任何影响。

static BaseType_t prvRunOTADemo( void ) { /* Status indicating a successful demo or not. */ BaseType_t xStatus = pdFAIL; /* OTA library return status. */ OtaErr_t xOtaError = OtaErrUninitialized; /* OTA event message used for sending event to OTA Agent.*/ OtaEventMsg_t xEventMsg = { 0 }; /* OTA interface context required for library interface functions.*/ OtaInterfaces_t xOtaInterfaces; /* OTA library packet statistics per job.*/ OtaAgentStatistics_t xOtaStatistics = { 0 }; /* OTA Agent state returned from calling OTA_GetState.*/ OtaState_t xOtaState = OtaAgentStateStopped; /* Set OTA Library interfaces.*/ prvSetOtaInterfaces( &xOtaInterfaces ); /*************************** Init OTA Library. ***************************/ if( ( xOtaError = OTA_Init( &xOtaBuffer, &xOtaInterfaces, ( const uint8_t * ) ( democonfigCLIENT_IDENTIFIER ), prvOtaAppCallback ) ) != OtaErrNone ) { LogError( ( "Failed to initialize OTA Agent, exiting = %u.", xOtaError ) ); } else { xStatus = pdPASS; } /************************ Create OTA Agent Task. ************************/ if( xStatus == pdPASS ) { xStatus = xTaskCreate( prvOTAAgentTask, "OTA Agent Task", otaexampleAGENT_TASK_STACK_SIZE, NULL, otaexampleAGENT_TASK_PRIORITY, NULL ); if( xStatus != pdPASS ) { LogError( ( "Failed to create OTA agent task:" ) ); } } /****************************** Start OTA ******************************/ if( xStatus == pdPASS ) { /* Send start event to OTA Agent.*/ xEventMsg.eventId = OtaAgentEventStart; OTA_SignalEvent( &xEventMsg ); } /******************** Loop and display OTA statistics ********************/ if( xStatus == pdPASS ) { while( ( xOtaState = OTA_GetState() ) != OtaAgentStateStopped ) { /* Get OTA statistics for currently executing job. */ if( xOtaState != OtaAgentStateSuspended ) { OTA_GetStatistics( &xOtaStatistics ); LogInfo( ( " Received: %u Queued: %u Processed: %u Dropped: %u", xOtaStatistics.otaPacketsReceived, xOtaStatistics.otaPacketsQueued, xOtaStatistics.otaPacketsProcessed, xOtaStatistics.otaPacketsDropped ) ); } vTaskDelay( pdMS_TO_TICKS( otaexampleEXAMPLE_TASK_DELAY_MS ) ); } } return xStatus; }

以下是该演示应用程序的主要流程:

  • 创建 MQTT 代理上下文。

  • 连接到 Amazon IoT 终端节点。

  • 初始化 OTA 代理。

  • 循环执行 OTA 更新作业并每一秒输出一次统计数据。

  • 如果 MQTT 断开连接,则暂停 OTA 代理操作。

  • 尝试使用指数延迟和抖动再次连接。

  • 如果已重新连接,则恢复 OTA 代理操作。

  • 如果代理停止,则延迟一秒钟,然后尝试重新连接。

对 OTA 代理事件使用应用程序回调

前面的示例使用 prvOtaAppCallback 作为 OTA 代理事件的回调处理程序。(请参阅 OTA_Init API 调用的第四个参数)。如果要实现对完成事件的自定义处理,则必须在 OTA 演示/应用程序中更改默认处理。在 OTA 过程中,OTA 代理可将以下事件枚举中的任意一个发送给回调处理程序。如何以及何时处理这些事件由应用程序开发人员决定。

/** * @ingroup ota_enum_types * @brief OTA Job callback events. * * After an OTA update image is received and authenticated, the agent calls the user * callback (set with the @ref OTA_Init API) with the value OtaJobEventActivate to * signal that the device must be rebooted to activate the new image. When the device * boots, if the OTA job status is in self test mode, the agent calls the user callback * with the value OtaJobEventStartTest, signaling that any additional self tests * should be performed. * * If the OTA receive fails for any reason, the agent calls the user callback with * the value OtaJobEventFail instead to allow the user to log the failure and take * any action deemed appropriate by the user code. * * See the OtaImageState_t type for more information. */ typedef enum OtaJobEvent { OtaJobEventActivate = 0, /*!< @brief OTA receive is authenticated and ready to activate. */ OtaJobEventFail = 1, /*!< @brief OTA receive failed. Unable to use this update. */ OtaJobEventStartTest = 2, /*!< @brief OTA job is now in self test, perform user tests. */ OtaJobEventProcessed = 3, /*!< @brief OTA event queued by OTA_SignalEvent is processed. */ OtaJobEventSelfTestFailed = 4, /*!< @brief OTA self-test failed for current job. */ OtaJobEventParseCustomJob = 5, /*!< @brief OTA event for parsing custom job document. */ OtaJobEventReceivedJob = 6, /*!< @brief OTA event when a new valid AFT-OTA job is received. */ OtaJobEventUpdateComplete = 7, /*!< @brief OTA event when the update is completed. */ OtaLastJobEvent = OtaJobEventStartTest } OtaJobEvent_t;

OTA 代理可以在主应用程序的活动处理期间,在后台接收更新。交付这些事件的目的在于,允许应用程序决定是立即采取行动,还是应当推迟行动,直到其他某些特定于应用程序的处理过程完成。这可以防止设备在活动处理期间(例如,执行 vacuum 操作时),由于固件更新后的重置而导致意外中断。以下是回调处理程序接收的作业事件:

OtaJobEventActivate

如果回调处理程序收到此事件,则可以立即重置设备,或安排调用以稍后重置设备。您可以通过此方法来推迟设备重置和自检阶段(如有必要)。

OtaJobEventFail

如果回调处理程序收到此事件,则更新已失败。在这种情况下不需要执行任何操作。您可能希望输出日志消息或执行某些特定于应用程序的操作。

OtaJobEventStartTest

自检阶段旨在允许最近更新的固件执行并测试自身,然后再确定该固件可以正常使用,并提交为最新的永久应用程序映像。当收到已经过身份验证的新的更新,且设备已重置时,OTA 代理会将 OtaJobEventStartTest 事件发送给已准备好进行测试的回调函数。开发人员可以添加任何必需的测试,以确定设备固件在更新后是否能正常工作。如果通过自检认为设备固件是可靠的,则代码必须调用 OTA_SetImageState( OtaImageStateAccepted ) 函数,将该固件提交为新的永久映像。

OtaJobEventProcessed

已处理 OTA_SignalEvent 排队的 OTA 事件,因此可以执行清理操作,例如释放 OTA 缓冲区。

OtaJobEventSelfTestFailed

当前作业的 OTA 自检失败。此事件的默认处理方式是关闭并重新启动 OTA 代理,以便设备回滚到之前的映像。

OtaJobEventUpdateComplete

OTA 任务更新完成的通知事件。