本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
将 OTA 代理集成到应用程序中
over-the-air (OTA) 代理旨在简化为产品添加 OTA 更新功能而必须编写的代码量。集成负担主要包括初始化 OTA 代理和创建用于响应 OTA 代理事件消息的自定义回调函数。在初始化操作系统期间,MQTT、HTTP(如果使用 HTTP 进行文件下载)和平台特定实现 (PAL) 接口将传递给 OTA 代理。也可以初始化缓冲区并将其传递给 OTA 代理。
尽管将 OTA 更新功能集成到应用程序中非常简单,但 OTA 更新系统需要了解的不仅仅是设备代码集成。要熟悉如何使用Amazon IoT东西、证书、代码签名证书、配置设备和 OTA 更新任务配置您的Amazon账户,请参阅 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 事件
OTA_SignalEvent
已得到处理,因此可以执行清理操作,例如释放 OTA 缓冲区。 OtaJobEventSelfTestFailed
-
当前作业的 OTA 自检失败。此事件的默认处理方式是关闭 OTA 代理并重新启动它,以便设备回滚到之前的映像。
OtaJobEventUpdateComplete
-
OTA 任务更新完成的通知事件。