From be80e7a571366316e94829b19652b83ef2ee6c23 Mon Sep 17 00:00:00 2001 From: Carol Yang Date: Thu, 13 Jan 2022 05:43:21 -0800 Subject: [PATCH] Update OTA Requestor Server cluster attributes (#13484) * [OTA] Update OTA Requestor Server cluster attributes * Address code review comments - Add missing idle updates - Fix logic for setting UpdateStateProgress - Remove OtaRequestorServer class and define the setters as global functions --- examples/all-clusters-app/esp32/main/main.cpp | 4 +- .../lighting-app/nrfconnect/main/AppTask.cpp | 4 +- .../nxp/k32w/k32w0/main/AppTask.cpp | 9 +-- examples/ota-requestor-app/efr32/src/main.cpp | 9 +-- .../ota-requestor-app/esp32/main/main.cpp | 8 +-- examples/ota-requestor-app/linux/main.cpp | 48 ++++++------- .../clusters/ota-requestor/BDXDownloader.cpp | 3 +- .../clusters/ota-requestor/BDXDownloader.h | 5 +- .../clusters/ota-requestor/OTARequestor.cpp | 61 +++++++++++----- src/app/clusters/ota-requestor/OTARequestor.h | 71 ++++++++----------- .../ota-requestor/ota-requestor-server.cpp | 49 ++++++++++++- .../ota-requestor/ota-requestor-server.h | 24 +++++++ src/include/platform/OTAImageProcessor.h | 4 +- src/platform/GenericOTARequestorDriver.h | 5 ++ 14 files changed, 187 insertions(+), 117 deletions(-) create mode 100644 src/app/clusters/ota-requestor/ota-requestor-server.h diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 93cabf8dbbaea2..2738a4b4f9ebfb 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -543,12 +543,10 @@ static void InitOTARequestor(void) { #if CONFIG_ENABLE_OTA_REQUESTOR SetRequestorInstance(&gRequestorCore); - gRequestorCore.SetServerInstance(&Server::GetInstance()); - gRequestorCore.SetOtaRequestorDriver(&gRequestorUser); + gRequestorCore.Init(&Server::GetInstance(), &gRequestorUser, &gDownloader); gImageProcessor.SetOTADownloader(&gDownloader); gDownloader.SetImageProcessorDelegate(&gImageProcessor); gRequestorUser.Init(&gRequestorCore, &gImageProcessor); - gRequestorCore.SetBDXDownloader(&gDownloader); #endif } diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index 61f5b1bacae00d..02291e501b3205 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -147,9 +147,7 @@ void AppTask::InitOTARequestor() sOTAImageProcessor.SetOTADownloader(&sBDXDownloader); sBDXDownloader.SetImageProcessorDelegate(&sOTAImageProcessor); sOTARequestorDriver.Init(&sOTARequestor, &sOTAImageProcessor); - sOTARequestor.SetOtaRequestorDriver(&sOTARequestorDriver); - sOTARequestor.SetBDXDownloader(&sBDXDownloader); - sOTARequestor.SetServerInstance(&chip::Server::GetInstance()); + sOTARequestor.Init(&chip::Server::GetInstance(), &sOTARequestorDriver, &sBDXDownloader); chip::SetRequestorInstance(&sOTARequestor); #endif } diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp index 45ab2fb1002130..96ba7f6b2b6a52 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -124,12 +124,7 @@ CHIP_ERROR AppTask::Init() // Initialize and interconnect the Requestor and Image Processor objects -- START SetRequestorInstance(&gRequestorCore); - // Set server instance used for session establishment - chip::Server * server = &(chip::Server::GetInstance()); - gRequestorCore.SetServerInstance(server); - - // Connect the Requestor and Requestor Driver objects - gRequestorCore.SetOtaRequestorDriver(&gRequestorUser); + gRequestorCore.Init(&(chip::Server::GetInstance()), &gRequestorUser, &gDownloader); gRequestorUser.Init(&gRequestorCore, &gImageProcessor); // WARNING: this is probably not realistic to know such details of the image or to even have an OTADownloader instantiated at @@ -143,8 +138,6 @@ CHIP_ERROR AppTask::Init() // Connect the gDownloader and Image Processor objects gDownloader.SetImageProcessorDelegate(&gImageProcessor); - - gRequestorCore.SetBDXDownloader(&gDownloader); // Initialize and interconnect the Requestor and Image Processor objects -- END // QR code will be used with CHIP Tool diff --git a/examples/ota-requestor-app/efr32/src/main.cpp b/examples/ota-requestor-app/efr32/src/main.cpp index 4e54e423633fbb..e3254635ec7610 100644 --- a/examples/ota-requestor-app/efr32/src/main.cpp +++ b/examples/ota-requestor-app/efr32/src/main.cpp @@ -172,12 +172,7 @@ int main(void) // Initialize and interconnect the Requestor and Image Processor objects -- START SetRequestorInstance(&gRequestorCore); - // Set server instance used for session establishment - chip::Server * server = &(chip::Server::GetInstance()); - gRequestorCore.SetServerInstance(server); - - // Connect the Requestor and Requestor Driver objects - gRequestorCore.SetOtaRequestorDriver(&gRequestorUser); + gRequestorCore.Init(&(chip::Server::GetInstance()), &gRequestorUser, &gDownloader); OTAImageProcessorParams ipParams; ipParams.imageFile = CharSpan("test.txt"); @@ -186,8 +181,6 @@ int main(void) // Connect the Downloader and Image Processor objects gDownloader.SetImageProcessorDelegate(&gImageProcessor); - - gRequestorCore.SetBDXDownloader(&gDownloader); // Initialize and interconnect the Requestor and Image Processor objects -- END EFR32_LOG("Starting Platform Manager Event Loop"); diff --git a/examples/ota-requestor-app/esp32/main/main.cpp b/examples/ota-requestor-app/esp32/main/main.cpp index cc6d417ad4d0f8..e53dc1bb341dc1 100644 --- a/examples/ota-requestor-app/esp32/main/main.cpp +++ b/examples/ota-requestor-app/esp32/main/main.cpp @@ -142,14 +142,8 @@ extern "C" void app_main() ESPInitConsole(); SetRequestorInstance(&gRequestorCore); - - Server * server = &(Server::GetInstance()); - gRequestorCore.SetServerInstance(server); - gRequestorCore.SetOtaRequestorDriver(&gRequestorUser); - + gRequestorCore.Init(&(Server::GetInstance()), &gRequestorUser, &gDownloader); gImageProcessor.SetOTADownloader(&gDownloader); gDownloader.SetImageProcessorDelegate(&gImageProcessor); gRequestorUser.Init(&gRequestorCore, &gImageProcessor); - - gRequestorCore.SetBDXDownloader(&gDownloader); } diff --git a/examples/ota-requestor-app/linux/main.cpp b/examples/ota-requestor-app/linux/main.cpp index 01126907c6174a..12bbe74294cd59 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -100,6 +100,27 @@ HelpOptions helpOptions("ota-requestor-app", "Usage: ota-requestor-app [options] OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr }; +static void InitOTARequestor(void) +{ + // Set the global instance of the OTA requestor core component + SetRequestorInstance(&gRequestorCore); + + gRequestorCore.Init(&(chip::Server::GetInstance()), &gRequestorUser, &gDownloader); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + // WARNING: this is probably not realistic to know such details of the image or to even have an OTADownloader instantiated at + // the beginning of program execution. We're using hardcoded values here for now since this is a reference application. + // TODO: instatiate and initialize these values when QueryImageResponse tells us an image is available + // TODO: add API for OTARequestor to pass QueryImageResponse info to the application to use for OTADownloader init + OTAImageProcessorParams ipParams; + ipParams.imageFile = CharSpan("test.txt"); + gImageProcessor.SetOTAImageProcessorParams(ipParams); + gImageProcessor.SetOTADownloader(&gDownloader); + + // Set the image processor instance used for handling image being downloaded + gDownloader.SetImageProcessorDelegate(&gImageProcessor); +} + bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) { bool retval = true; @@ -192,31 +213,8 @@ int main(int argc, char * argv[]) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - // Initialize and interconnect the Requestor and Image Processor objects -- START - SetRequestorInstance(&gRequestorCore); - - // Set server instance used for session establishment - chip::Server * server = &(chip::Server::GetInstance()); - gRequestorCore.SetServerInstance(server); - - // Connect the Requestor and Requestor Driver objects - gRequestorCore.SetOtaRequestorDriver(&gRequestorUser); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); - - // WARNING: this is probably not realistic to know such details of the image or to even have an OTADownloader instantiated at - // the beginning of program execution. We're using hardcoded values here for now since this is a reference application. - // TODO: instatiate and initialize these values when QueryImageResponse tells us an image is available - // TODO: add API for OTARequestor to pass QueryImageResponse info to the application to use for OTADownloader init - OTAImageProcessorParams ipParams; - ipParams.imageFile = CharSpan("test.txt"); - gImageProcessor.SetOTAImageProcessorParams(ipParams); - gImageProcessor.SetOTADownloader(&gDownloader); - - // Connect the Downloader and Image Processor objects - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - - gRequestorCore.SetBDXDownloader(&gDownloader); - // Initialize and interconnect the Requestor and Image Processor objects -- END + // Initialize all OTA download components + InitOTARequestor(); // Test Mode operation: If a delay is provided, QueryImage after the timer expires if (delayQueryTimeInSec > 0) diff --git a/src/app/clusters/ota-requestor/BDXDownloader.cpp b/src/app/clusters/ota-requestor/BDXDownloader.cpp index d33f634089cec2..69297107afdf17 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.cpp +++ b/src/app/clusters/ota-requestor/BDXDownloader.cpp @@ -175,14 +175,13 @@ CHIP_ERROR BDXDownloader::HandleBdxEvent(const chip::bdx::TransferSession::Outpu { // BDX transfer is not complete until BlockAckEOF has been sent SetState(State::kComplete); - - // TODO: how/when to reset the BDXDownloader to be ready to handle another download } break; } case TransferSession::OutputEventType::kBlockReceived: { chip::ByteSpan blockData(outEvent.blockdata.Data, outEvent.blockdata.Length); ReturnErrorOnFailure(mImageProcessor->ProcessBlock(blockData)); + mStateDelegate->OnUpdateProgressChanged(mImageProcessor->GetPercentComplete()); // TODO: this will cause problems if Finalize() is not guaranteed to do its work after ProcessBlock(). if (outEvent.blockdata.IsEof) diff --git a/src/app/clusters/ota-requestor/BDXDownloader.h b/src/app/clusters/ota-requestor/BDXDownloader.h index e00a39ba886781..d783662c5a38fc 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.h +++ b/src/app/clusters/ota-requestor/BDXDownloader.h @@ -48,8 +48,11 @@ class BDXDownloader : public chip::OTADownloader class StateDelegate { public: + // Handle download state change virtual void OnDownloadStateChanged(State state) = 0; - virtual ~StateDelegate() = default; + // Handle update progress change + virtual void OnUpdateProgressChanged(uint8_t percent) = 0; + virtual ~StateDelegate() = default; }; // To be called when there is an incoming message to handle (of any protocol type) diff --git a/src/app/clusters/ota-requestor/OTARequestor.cpp b/src/app/clusters/ota-requestor/OTARequestor.cpp index 93961cf7c3de23..1e23db274e6fb6 100644 --- a/src/app/clusters/ota-requestor/OTARequestor.cpp +++ b/src/app/clusters/ota-requestor/OTARequestor.cpp @@ -20,7 +20,6 @@ * OTA Requestor logic is contained in this class. */ -#include #include #include #include @@ -88,6 +87,17 @@ static void LogApplyUpdateResponse(const ApplyUpdateResponse::DecodableType & re ChipLogDetail(SoftwareUpdate, " delayedActionTime: %" PRIu32 " seconds", response.delayedActionTime); } +static void SetUpdateStateAttribute(OTAUpdateStateEnum state) +{ + OtaRequestorServerSetUpdateState(state); + + // The UpdateStateProgress attribute only applies to the querying state + if (state != OTAUpdateStateEnum::kQuerying) + { + OtaRequestorServerSetUpdateStateProgress(0); + } +} + void StartDelayTimerHandler(System::Layer * systemLayer, void * appState) { VerifyOrReturn(appState != nullptr); @@ -135,13 +145,16 @@ void OTARequestor::OnQueryImageResponse(void * context, const QueryImageResponse case OTAQueryStatus::kBusy: requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::Busy, System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); + SetUpdateStateAttribute(OTAUpdateStateEnum::kDelayedOnQuery); break; case OTAQueryStatus::kNotAvailable: requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::NotAvailable, System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); break; default: requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kQuerying, CHIP_ERROR_BAD_REQUEST); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); break; } } @@ -153,6 +166,7 @@ void OTARequestor::OnQueryImageFailure(void * context, EmberAfStatus status) ChipLogDetail(SoftwareUpdate, "QueryImage failure response %" PRIu8, status); requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kQuerying, CHIP_ERROR_BAD_REQUEST); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); } void OTARequestor::OnApplyUpdateResponse(void * context, const ApplyUpdateResponse::DecodableType & response) @@ -169,9 +183,11 @@ void OTARequestor::OnApplyUpdateResponse(void * context, const ApplyUpdateRespon break; case OTAApplyUpdateAction::kAwaitNextAction: requestorCore->mOtaRequestorDriver->UpdateSuspended(System::Clock::Seconds32(response.delayedActionTime)); + SetUpdateStateAttribute(OTAUpdateStateEnum::kDelayedOnApply); break; case OTAApplyUpdateAction::kDiscontinue: requestorCore->mOtaRequestorDriver->UpdateDiscontinued(); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); break; } } @@ -183,6 +199,7 @@ void OTARequestor::OnApplyUpdateFailure(void * context, EmberAfStatus status) ChipLogDetail(SoftwareUpdate, "ApplyUpdate failure response %" PRIu8, status); requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kApplying, CHIP_ERROR_BAD_REQUEST); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); } EmberAfStatus OTARequestor::HandleAnnounceOTAProvider(app::CommandHandler * commandObj, @@ -271,8 +288,10 @@ void OTARequestor::OnConnected(void * context, OperationalDeviceProxy * devicePr { ChipLogError(SoftwareUpdate, "Failed to send QueryImage command: %" CHIP_ERROR_FORMAT, err.Format()); requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kQuerying, err); + return; } + SetUpdateStateAttribute(OTAUpdateStateEnum::kQuerying); break; } case kStartBDX: { @@ -282,8 +301,11 @@ void OTARequestor::OnConnected(void * context, OperationalDeviceProxy * devicePr { ChipLogError(SoftwareUpdate, "Failed to start download: %" CHIP_ERROR_FORMAT, err.Format()); requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kDownloading, err); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); + return; } + SetUpdateStateAttribute(OTAUpdateStateEnum::kDownloading); break; } case kApplyUpdate: { @@ -293,8 +315,11 @@ void OTARequestor::OnConnected(void * context, OperationalDeviceProxy * devicePr { ChipLogError(SoftwareUpdate, "Failed to send ApplyUpdate command: %" CHIP_ERROR_FORMAT, err.Format()); requestorCore->mOtaRequestorDriver->HandleError(OTAUpdateStateEnum::kApplying, err); + SetUpdateStateAttribute(OTAUpdateStateEnum::kIdle); + return; } + SetUpdateStateAttribute(OTAUpdateStateEnum::kApplying); break; } default: @@ -302,21 +327,6 @@ void OTARequestor::OnConnected(void * context, OperationalDeviceProxy * devicePr } } -OTARequestorInterface::OTATriggerResult OTARequestor::TriggerImmediateQuery() -{ - - if (mProviderNodeId != kUndefinedNodeId) - { - ConnectToProvider(kQueryImage); - return kTriggerSuccessful; - } - else - { - ChipLogError(SoftwareUpdate, "No OTA Providers available"); - return kNoProviderKnown; - } -} - // Called whenever FindOrEstablishSession fails void OTARequestor::OnConnectionFailure(void * context, PeerId peerId, CHIP_ERROR error) { @@ -342,6 +352,20 @@ void OTARequestor::OnConnectionFailure(void * context, PeerId peerId, CHIP_ERROR } } +OTARequestorInterface::OTATriggerResult OTARequestor::TriggerImmediateQuery() +{ + if (mProviderNodeId != kUndefinedNodeId) + { + ConnectToProvider(kQueryImage); + return kTriggerSuccessful; + } + else + { + ChipLogError(SoftwareUpdate, "No OTA Providers available"); + return kNoProviderKnown; + } +} + void OTARequestor::DownloadUpdate() { ConnectToProvider(kStartBDX); @@ -369,6 +393,11 @@ void OTARequestor::OnDownloadStateChanged(OTADownloader::State state) } } +void OTARequestor::OnUpdateProgressChanged(uint8_t percent) +{ + OtaRequestorServerSetUpdateStateProgress(percent); +} + CHIP_ERROR OTARequestor::SendQueryImageRequest(OperationalDeviceProxy & deviceProxy) { constexpr OTADownloadProtocol kProtocolsSupported[] = { OTADownloadProtocol::kBDXSynchronous }; diff --git a/src/app/clusters/ota-requestor/OTARequestor.h b/src/app/clusters/ota-requestor/OTARequestor.h index 663ecbce0a2ba6..ee5184ffaa4d76 100644 --- a/src/app/clusters/ota-requestor/OTARequestor.h +++ b/src/app/clusters/ota-requestor/OTARequestor.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -46,7 +47,10 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe OTARequestor() : mOnConnectedCallback(OnConnected, this), mOnConnectionFailureCallback(OnConnectionFailure, this) {} - // Application interface declarations -- start + //////////// OTARequestorInterface Implementation /////////////// + EmberAfStatus HandleAnnounceOTAProvider( + app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) override; // Application directs the Requestor to start the Image Query process // and download the new image if available @@ -58,53 +62,26 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe // Send ApplyImage void ApplyUpdate() override; - // Handle download state change + //////////// BDXDownloader::StateDelegate Implementation /////////////// void OnDownloadStateChanged(OTADownloader::State state) override; + void OnUpdateProgressChanged(uint8_t percent) override; - // A setter for the delegate class pointer - void SetOtaRequestorDriver(OTARequestorDriver * driver) { mOtaRequestorDriver = driver; } - - // TODO: this should really be OTADownloader, but right now OTARequestor has information that we need to initialize a - // BDXDownloader specifically. - // The BDXDownloader instance should already have the ImageProcessingDelegate set. - void SetBDXDownloader(chip::BDXDownloader * downloader) { mBdxDownloader = downloader; } - - // Application directs the Requestor to abort the download in progress. All the Requestor state (such - // as the QueryImageResponse content) is preserved - void AbortImageUpdate(); - - // Application directs the Requestor to abort the download in progress. All the Requestor state is - // cleared, UploadState is reset to Idle - void AbortAndResetState(); - - // Application notifies the Requestor on the user consent action, TRUE if consent is given, - // FALSE otherwise - void OnUserConsent(bool result); - - /* Commented out until the API is supported - // Application directs the Requestor to download the image using the suppiled parameter and without - // issuing QueryImage - OTATriggerResult ResumeImageDownload(const BdxDownloadParameters & bdxParameters){ return kTriggerSuccessful;} - */ - - // Application interface declarations -- end - - // Virtual functions from OTARequestorInterface -- start - - // Handler for the AnnounceOTAProvider command - EmberAfStatus HandleAnnounceOTAProvider( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) override; - - // Virtual functions from OTARequestorInterface -- end /** - * Called to set the server instance which used to get access to the system resources necessary to open CASE sessions and drive - * BDX transfers + * Called to perform some initialization including: + * - Set server instance used to get access to the system resources necessary to open CASE sessions and drive + * BDX transfers + * - Set the OTA requestor driver instance used to communicate download progress and errors + * - Set the BDX downloader instance used for initiating BDX downloads */ - void SetServerInstance(Server * server) + void Init(Server * server, OTARequestorDriver * driver, BDXDownloader * downloader) { mServer = server; mCASESessionManager = server->GetCASESessionManager(); + mOtaRequestorDriver = driver; + mBdxDownloader = downloader; + + OtaRequestorServerSetUpdateState(app::Clusters::OtaSoftwareUpdateRequestor::OTAUpdateStateEnum::kIdle); + OtaRequestorServerSetUpdateStateProgress(0); } /** @@ -126,6 +103,18 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe mProviderEndpointId = endpointId; } + // Application directs the Requestor to abort the download in progress. All the Requestor state (such + // as the QueryImageResponse content) is preserved + void AbortImageUpdate(); + + // Application directs the Requestor to abort the download in progress. All the Requestor state is + // cleared, UploadState is reset to Idle + void AbortAndResetState(); + + // Application notifies the Requestor on the user consent action, TRUE if consent is given, + // FALSE otherwise + void OnUserConsent(bool result); + private: using QueryImageResponseDecodableType = app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::DecodableType; using ApplyUpdateResponseDecodableType = app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::DecodableType; diff --git a/src/app/clusters/ota-requestor/ota-requestor-server.cpp b/src/app/clusters/ota-requestor/ota-requestor-server.cpp index a38957ad3cd30b..0fc2bffba7ce45 100644 --- a/src/app/clusters/ota-requestor/ota-requestor-server.cpp +++ b/src/app/clusters/ota-requestor/ota-requestor-server.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include @@ -29,6 +29,7 @@ using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::OtaSoftwareUpdateRequestor; +using namespace chip::app::Clusters::OtaSoftwareUpdateRequestor::Attributes; namespace { @@ -78,6 +79,52 @@ CHIP_ERROR OtaSoftwareUpdateRequestorAttrAccess::Write(const ConcreteDataAttribu } // namespace +// ----------------------------------------------------------------------------- +// Global functions +EmberAfStatus OtaRequestorServerSetUpdateState(OTAUpdateStateEnum value) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + + // Find all endpoints that has OtaSoftwareUpdateRequestor implemented + for (auto endpoint : EnabledEndpointsWithServerCluster(OtaSoftwareUpdateRequestor::Id)) + { + OTAUpdateStateEnum currentValue; + status = Attributes::UpdateState::Get(endpoint, ¤tValue); + VerifyOrDie(EMBER_ZCL_STATUS_SUCCESS == status); + + if (currentValue != value) + { + status = Attributes::UpdateState::Set(endpoint, value); + VerifyOrDie(EMBER_ZCL_STATUS_SUCCESS == status); + } + } + + return status; +} + +EmberAfStatus OtaRequestorServerSetUpdateStateProgress(uint8_t value) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + + // Find all endpoints that has OtaSoftwareUpdateRequestor implemented + for (auto endpoint : EnabledEndpointsWithServerCluster(OtaSoftwareUpdateRequestor::Id)) + { + app::DataModel::Nullable currentValue; + status = Attributes::UpdateStateProgress::Get(endpoint, currentValue); + VerifyOrDie(EMBER_ZCL_STATUS_SUCCESS == status); + if (currentValue.IsNull() || currentValue.Value() != value) + { + status = Attributes::UpdateStateProgress::Set(endpoint, value); + VerifyOrDie(EMBER_ZCL_STATUS_SUCCESS == status); + } + } + + return status; +} + +// ----------------------------------------------------------------------------- +// Callbacks implementation + bool emberAfOtaSoftwareUpdateRequestorClusterAnnounceOtaProviderCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) diff --git a/src/app/clusters/ota-requestor/ota-requestor-server.h b/src/app/clusters/ota-requestor/ota-requestor-server.h new file mode 100644 index 00000000000000..9a5afcfc193979 --- /dev/null +++ b/src/app/clusters/ota-requestor/ota-requestor-server.h @@ -0,0 +1,24 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +EmberAfStatus OtaRequestorServerSetUpdateState(chip::app::Clusters::OtaSoftwareUpdateRequestor::OTAUpdateStateEnum value); +EmberAfStatus OtaRequestorServerSetUpdateStateProgress(uint8_t value); diff --git a/src/include/platform/OTAImageProcessor.h b/src/include/platform/OTAImageProcessor.h index 7aaa346a8a5196..b5954394add880 100644 --- a/src/include/platform/OTAImageProcessor.h +++ b/src/include/platform/OTAImageProcessor.h @@ -28,8 +28,8 @@ namespace chip { struct OTAImageProcessorParams { CharSpan imageFile; - uint64_t downloadedBytes; - uint64_t totalFileBytes; + uint64_t downloadedBytes = 0; + uint64_t totalFileBytes = 0; }; /** diff --git a/src/platform/GenericOTARequestorDriver.h b/src/platform/GenericOTARequestorDriver.h index f853821ac785a6..a6533d2fe93cbe 100644 --- a/src/platform/GenericOTARequestorDriver.h +++ b/src/platform/GenericOTARequestorDriver.h @@ -31,6 +31,11 @@ namespace DeviceLayer { class GenericOTARequestorDriver : public OTARequestorDriver { public: + /** + * Called to perform some initialization including: + * - Set the OTA requestor instance used to direct download progress + * - Set the OTA image processor instance used to apply/abort the downloaded image + */ void Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor) { mRequestor = requestor;