From eab67b3f5c9b351dcaf8559aeb75a1ade0fc2d1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Tue, 28 Dec 2021 22:33:59 +0100 Subject: [PATCH] [ota-requestor] Add generic OTA requestor driver (#13210) * [ota-requestor] Add generic OTA requestor driver 1. Extend OTARequestorDriver interface so it can be notified of various OTA Requestor operations. 2. Use OTARequestorDriver in OTARequestor to report results of operations. 3. Implement GenericOTARequestorDriver that provides default behavior for handling OTARequestor events. For example, it respects DelayedActionTime arguments. 4. Use the driver in existing examples. * Restyled by whitespace Co-authored-by: Restyled.io --- .../lighting-app/nrfconnect/main/AppTask.cpp | 10 +- .../ota-requestor-app/esp32/main/main.cpp | 5 +- examples/ota-requestor-app/linux/main.cpp | 5 +- .../clusters/ota-requestor/BDXDownloader.cpp | 22 +- .../clusters/ota-requestor/BDXDownloader.h | 12 +- .../clusters/ota-requestor/OTARequestor.cpp | 283 +++++++++++------- src/app/clusters/ota-requestor/OTARequestor.h | 26 +- src/include/platform/OTARequestorDriver.h | 75 ++--- src/include/platform/OTARequestorInterface.h | 3 + src/lib/shell/commands/Ota.cpp | 1 - src/platform/BUILD.gn | 7 + src/platform/Darwin/BUILD.gn | 2 - src/platform/ESP32/BUILD.gn | 2 - src/platform/ESP32/OTARequestorDriverImpl.cpp | 40 --- src/platform/ESP32/OTARequestorDriverImpl.h | 31 -- src/platform/GenericOTARequestorDriver.cpp | 100 +++++++ src/platform/GenericOTARequestorDriver.h | 59 ++++ src/platform/Linux/BUILD.gn | 2 - src/platform/Linux/OTARequestorDriverImpl.cpp | 41 --- src/platform/Linux/OTARequestorDriverImpl.h | 46 --- 20 files changed, 423 insertions(+), 349 deletions(-) delete mode 100644 src/platform/ESP32/OTARequestorDriverImpl.cpp delete mode 100644 src/platform/ESP32/OTARequestorDriverImpl.h create mode 100644 src/platform/GenericOTARequestorDriver.cpp create mode 100644 src/platform/GenericOTARequestorDriver.h delete mode 100644 src/platform/Linux/OTARequestorDriverImpl.cpp delete mode 100644 src/platform/Linux/OTARequestorDriverImpl.h diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index f8d9f6a3b53cb9..6ff8cf69f3f8a2 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -39,6 +39,7 @@ #if CONFIG_CHIP_OTA_REQUESTOR #include #include +#include #include #endif @@ -72,13 +73,7 @@ bool sIsThreadEnabled = false; bool sHaveBLEConnections = false; #if CONFIG_CHIP_OTA_REQUESTOR -class DummyOTARequestorDriver : public chip::OTARequestorDriver -{ - bool CheckImageDownloadAllowed() override { return true; } - chip::UserConsentAction RequestUserConsent() override { return chip::ImmediateYes; } - void ImageDownloadComplete() override {} -} sOTARequestorDriver; - +GenericOTARequestorDriver sOTARequestorDriver; OTAImageProcessorImpl sOTAImageProcessor; chip::BDXDownloader sBDXDownloader; chip::OTARequestor sOTARequestor; @@ -145,6 +140,7 @@ void AppTask::InitOTARequestor() #if CONFIG_CHIP_OTA_REQUESTOR sOTAImageProcessor.SetOTADownloader(&sBDXDownloader); sBDXDownloader.SetImageProcessorDelegate(&sOTAImageProcessor); + sOTARequestorDriver.Init(&sOTARequestor, &sOTAImageProcessor); sOTARequestor.SetOtaRequestorDriver(&sOTARequestorDriver); sOTARequestor.SetBDXDownloader(&sBDXDownloader); sOTARequestor.SetServerInstance(&chip::Server::GetInstance()); diff --git a/examples/ota-requestor-app/esp32/main/main.cpp b/examples/ota-requestor-app/esp32/main/main.cpp index ab3bc6fff2843d..cc6d417ad4d0f8 100644 --- a/examples/ota-requestor-app/esp32/main/main.cpp +++ b/examples/ota-requestor-app/esp32/main/main.cpp @@ -43,7 +43,7 @@ #include #include "OTAImageProcessorImpl.h" -#include "OTARequestorDriverImpl.h" +#include "platform/GenericOTARequestorDriver.h" #include "platform/OTARequestorInterface.h" #include #include @@ -65,7 +65,7 @@ static DeviceCallbacks EchoCallbacks; CmdArgs applyUpdateCmdArgs; OTARequestor gRequestorCore; -OTARequestorDriverImpl gRequestorUser; +GenericOTARequestorDriver gRequestorUser; BDXDownloader gDownloader; OTAImageProcessorImpl gImageProcessor; } // namespace @@ -149,6 +149,7 @@ extern "C" void app_main() 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 7131edb35f96dd..01126907c6174a 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -24,8 +24,8 @@ #include "app/clusters/ota-requestor/BDXDownloader.h" #include "app/clusters/ota-requestor/OTARequestor.h" +#include "platform/GenericOTARequestorDriver.h" #include "platform/Linux/OTAImageProcessorImpl.h" -#include "platform/Linux/OTARequestorDriverImpl.h" using chip::BDXDownloader; using chip::ByteSpan; @@ -52,7 +52,7 @@ using namespace chip::Messaging; using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands; OTARequestor gRequestorCore; -OTARequestorDriverImpl gRequestorUser; +DeviceLayer::GenericOTARequestorDriver gRequestorUser; BDXDownloader gDownloader; OTAImageProcessorImpl gImageProcessor; @@ -201,6 +201,7 @@ int main(int argc, char * argv[]) // 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. diff --git a/src/app/clusters/ota-requestor/BDXDownloader.cpp b/src/app/clusters/ota-requestor/BDXDownloader.cpp index ec347ecf2c478e..8c2ef8c3626562 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.cpp +++ b/src/app/clusters/ota-requestor/BDXDownloader.cpp @@ -65,7 +65,7 @@ CHIP_ERROR BDXDownloader::BeginPrepareDownload() VerifyOrReturnError(mImageProcessor != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(mImageProcessor->PrepareDownload()); - mState = State::kPreparing; + SetState(State::kPreparing); return CHIP_NO_ERROR; } @@ -76,7 +76,7 @@ CHIP_ERROR BDXDownloader::OnPreparedForDownload(CHIP_ERROR status) if (status == CHIP_NO_ERROR) { - mState = State::kInProgress; + SetState(State::kInProgress); // Must call here because StartTransfer() should have prepared a ReceiveInit message, and now we should send it. PollTransferSession(); @@ -85,7 +85,7 @@ CHIP_ERROR BDXDownloader::OnPreparedForDownload(CHIP_ERROR status) { ChipLogError(BDX, "failed to prepare download: %" CHIP_ERROR_FORMAT, status.Format()); mBdxTransfer.Reset(); - mState = State::kIdle; + SetState(State::kIdle); } return CHIP_NO_ERROR; @@ -110,7 +110,7 @@ void BDXDownloader::OnDownloadTimeout() { mImageProcessor->Abort(); } - mState = State::kIdle; + SetState(State::kIdle); } else { @@ -128,7 +128,7 @@ void BDXDownloader::EndDownload(CHIP_ERROR reason) { mImageProcessor->Abort(); } - mState = State::kIdle; + SetState(State::kIdle); // Because AbortTransfer() will generate a StatusReport to send. PollTransferSession(); @@ -171,7 +171,7 @@ CHIP_ERROR BDXDownloader::HandleBdxEvent(const chip::bdx::TransferSession::Outpu if (outEvent.msgTypeData.HasMessageType(chip::bdx::MessageType::BlockAckEOF)) { // BDX transfer is not complete until BlockAckEOF has been sent - mState = State::kComplete; + SetState(State::kComplete); // TODO: how/when to reset the BDXDownloader to be ready to handle another download } @@ -217,4 +217,14 @@ CHIP_ERROR BDXDownloader::HandleBdxEvent(const chip::bdx::TransferSession::Outpu return CHIP_NO_ERROR; } +void BDXDownloader::SetState(State state) +{ + mState = state; + + if (mStateDelegate) + { + mStateDelegate->OnDownloadStateChanged(state); + } +} + } // namespace chip diff --git a/src/app/clusters/ota-requestor/BDXDownloader.h b/src/app/clusters/ota-requestor/BDXDownloader.h index d4c86d29736bd1..e00a39ba886781 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.h +++ b/src/app/clusters/ota-requestor/BDXDownloader.h @@ -45,12 +45,18 @@ class BDXDownloader : public chip::OTADownloader virtual ~MessagingDelegate() {} }; - BDXDownloader() : chip::OTADownloader() {} + class StateDelegate + { + public: + virtual void OnDownloadStateChanged(State state) = 0; + virtual ~StateDelegate() = default; + }; // To be called when there is an incoming message to handle (of any protocol type) void OnMessageReceived(const chip::PayloadHeader & payloadHeader, chip::System::PacketBufferHandle msg); void SetMessageDelegate(MessagingDelegate * delegate) { mMsgDelegate = delegate; } + void SetStateDelegate(StateDelegate * delegate) { mStateDelegate = delegate; } // Initialize a BDX transfer session but will not proceed until OnPreparedForDownload() is called. CHIP_ERROR SetBDXParams(const chip::bdx::TransferSession::TransferInitData & bdxInitData); @@ -68,9 +74,11 @@ class BDXDownloader : public chip::OTADownloader private: void PollTransferSession(); CHIP_ERROR HandleBdxEvent(const chip::bdx::TransferSession::OutputEvent & outEvent); + void SetState(State state); chip::bdx::TransferSession mBdxTransfer; - MessagingDelegate * mMsgDelegate; + MessagingDelegate * mMsgDelegate = nullptr; + StateDelegate * mStateDelegate = nullptr; }; } // namespace chip diff --git a/src/app/clusters/ota-requestor/OTARequestor.cpp b/src/app/clusters/ota-requestor/OTARequestor.cpp index f1eac9912a9b25..b4e3604035ed02 100644 --- a/src/app/clusters/ota-requestor/OTARequestor.cpp +++ b/src/app/clusters/ota-requestor/OTARequestor.cpp @@ -80,6 +80,13 @@ static void LogQueryImageResponse(const QueryImageResponse::DecodableType & resp } } +static void LogApplyUpdateResponse(const ApplyUpdateResponse::DecodableType & response) +{ + ChipLogDetail(SoftwareUpdate, "ApplyUpdateResponse:"); + ChipLogDetail(SoftwareUpdate, " action: %" PRIu8 "", to_underlying(response.action)); + ChipLogDetail(SoftwareUpdate, " delayedActionTime: %" PRIu32 " seconds", response.delayedActionTime); +} + void StartDelayTimerHandler(System::Layer * systemLayer, void * appState) { VerifyOrReturn(appState != nullptr); @@ -96,87 +103,85 @@ OTARequestorInterface * GetRequestorInstance() return globalOTARequestorInstance; } -struct OTARequestor::QueryImageRequest -{ - char location[2]; - QueryImage::Type args; -}; - void OTARequestor::OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response) { LogQueryImageResponse(response); OTARequestor * requestorCore = static_cast(context); - - VerifyOrReturn(requestorCore != nullptr, ChipLogError(SoftwareUpdate, "Received QueryImageResponse with invalid context")); - // TODO: Add a method to OTARequestorDriver used to report error condictions - VerifyOrReturn(requestorCore->ValidateQueryImageResponse(response), - ChipLogError(SoftwareUpdate, "Received invalid QueryImageResponse")); + VerifyOrDie(requestorCore != nullptr); switch (response.status) { case OTAQueryStatus::kUpdateAvailable: { - // Parse out the provider node ID and file designator from the image URI - NodeId nodeId = kUndefinedNodeId; - CharSpan fileDesignator; - CHIP_ERROR err = bdx::ParseURI(response.imageURI.Value(), nodeId, fileDesignator); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Parse BDX image URI (%.*s) returned err=%" CHIP_ERROR_FORMAT, - static_cast(response.imageURI.Value().size()), response.imageURI.Value().data(), - err.Format())); - requestorCore->mProviderNodeId = nodeId; + UpdateDescription update; + CHIP_ERROR err = requestorCore->ExtractUpdateDescription(response, update); + + if (err != CHIP_NO_ERROR) + { + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Querying, err); + return; + } MutableByteSpan updateToken(requestorCore->mUpdateTokenBuffer); - CopySpanToMutableSpan(response.updateToken.Value(), updateToken); - requestorCore->mUpdateVersion = response.softwareVersion.Value(); + CopySpanToMutableSpan(update.updateToken, updateToken); + requestorCore->mUpdateVersion = update.softwareVersion; requestorCore->mUpdateToken = updateToken; - // CSM should already be created for sending QueryImage command so use the same CSM since the - // provider node ID that will supply the OTA image must be on the same fabric as the sender of the QueryImageResponse - requestorCore->ConnectToProvider(kStartBDX); + requestorCore->mOtaRequestorDriver->UpdateAvailable(update, + System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); break; } case OTAQueryStatus::kBusy: + requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::Busy, + System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); break; case OTAQueryStatus::kNotAvailable: + requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::NotAvailable, + System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); break; - case OTAQueryStatus::kDownloadProtocolNotSupported: - break; - // Issue #9524 should handle all response status appropriately default: + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Querying, CHIP_ERROR_BAD_REQUEST); break; } } void OTARequestor::OnQueryImageFailure(void * context, EmberAfStatus status) { + OTARequestor * requestorCore = static_cast(context); + VerifyOrDie(requestorCore != nullptr); + ChipLogDetail(SoftwareUpdate, "QueryImage failure response %" PRIu8, status); + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Querying, CHIP_ERROR_BAD_REQUEST); } void OTARequestor::OnApplyUpdateResponse(void * context, const ApplyUpdateResponse::DecodableType & response) { - VerifyOrReturn(context != nullptr, ChipLogError(SoftwareUpdate, "Received ApplyUpdateResponse with invalid context")); + LogApplyUpdateResponse(response); OTARequestor * requestorCore = static_cast(context); + VerifyOrDie(requestorCore != nullptr); switch (response.action) { - case EMBER_ZCL_OTA_APPLY_UPDATE_ACTION_PROCEED: { - // TODO: Call OTARequestorDriver to schedule the image application. - VerifyOrReturn(requestorCore->mBdxDownloader != nullptr, ChipLogError(SoftwareUpdate, "Downloader is not set")); - OTAImageProcessorInterface * imageProcessor = requestorCore->mBdxDownloader->GetImageProcessorDelegate(); - VerifyOrReturn(imageProcessor != nullptr, ChipLogError(SoftwareUpdate, "Image processor is not set")); - imageProcessor->Apply(); + case EMBER_ZCL_OTA_APPLY_UPDATE_ACTION_PROCEED: + requestorCore->mOtaRequestorDriver->UpdateConfirmed(System::Clock::Seconds32(response.delayedActionTime)); break; - } - default: + case EMBER_ZCL_OTA_APPLY_UPDATE_ACTION_AWAIT_NEXT_ACTION: + requestorCore->mOtaRequestorDriver->UpdateSuspended(System::Clock::Seconds32(response.delayedActionTime)); + break; + case EMBER_ZCL_OTA_APPLY_UPDATE_ACTION_DISCONTINUE: + requestorCore->mOtaRequestorDriver->UpdateDiscontinued(); break; } } void OTARequestor::OnApplyUpdateFailure(void * context, EmberAfStatus status) { + OTARequestor * requestorCore = static_cast(context); + VerifyOrDie(requestorCore != nullptr); + ChipLogDetail(SoftwareUpdate, "ApplyUpdate failure response %" PRIu8, status); + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Applying, CHIP_ERROR_BAD_REQUEST); } EmberAfStatus OTARequestor::HandleAnnounceOTAProvider(app::CommandHandler * commandObj, @@ -229,6 +234,9 @@ EmberAfStatus OTARequestor::HandleAnnounceOTAProvider(app::CommandHandler * comm void OTARequestor::ConnectToProvider(OnConnectedAction onConnectedAction) { + VerifyOrReturn(mOtaRequestorDriver != nullptr, ChipLogError(SoftwareUpdate, "OTA requestor driver not set")); + VerifyOrReturn(mServer != nullptr, ChipLogError(SoftwareUpdate, "Server not set")); + FabricInfo * fabricInfo = mServer->GetFabricTable().FindFabricWithIndex(mProviderFabricIndex); VerifyOrReturn(fabricInfo != nullptr, ChipLogError(SoftwareUpdate, "Cannot find fabric")); @@ -246,86 +254,42 @@ void OTARequestor::ConnectToProvider(OnConnectedAction onConnectedAction) // Called whenever FindOrEstablishSession is successful void OTARequestor::OnConnected(void * context, OperationalDeviceProxy * deviceProxy) { - VerifyOrReturn(context != nullptr, ChipLogError(SoftwareUpdate, "Successfully established session but context is invalid")); OTARequestor * requestorCore = static_cast(context); + VerifyOrDie(requestorCore != nullptr); + VerifyOrDie(deviceProxy != nullptr); switch (requestorCore->mOnConnectedAction) { case kQueryImage: { - QueryImageRequest request; - CHIP_ERROR err = requestorCore->BuildQueryImageRequest(request); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Failed to build QueryImage command: %" CHIP_ERROR_FORMAT, err.Format())); - - Controller::OtaSoftwareUpdateProviderCluster cluster; - cluster.Associate(deviceProxy, requestorCore->mProviderEndpointId); + CHIP_ERROR err = requestorCore->SendQueryImageRequest(*deviceProxy); - err = cluster.InvokeCommand(request.args, requestorCore, OnQueryImageResponse, OnQueryImageFailure); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Failed to send QueryImage command: %" CHIP_ERROR_FORMAT, err.Format())); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Failed to send QueryImage command: %" CHIP_ERROR_FORMAT, err.Format()); + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Querying, err); + } break; } case kStartBDX: { - VerifyOrReturn(requestorCore->mBdxDownloader != nullptr, ChipLogError(SoftwareUpdate, "Downloader is null")); - - // TODO: allow caller to provide their own OTADownloader instance and set BDX parameters + CHIP_ERROR err = requestorCore->StartDownload(*deviceProxy); - TransferSession::TransferInitData initOptions; - initOptions.TransferCtlFlags = bdx::TransferControlFlags::kReceiverDrive; - initOptions.MaxBlockSize = 1024; - char testFileDes[9] = { "test.txt" }; - initOptions.FileDesLength = static_cast(strlen(testFileDes)); - initOptions.FileDesignator = reinterpret_cast(testFileDes); - - if (deviceProxy != nullptr) + if (err != CHIP_NO_ERROR) { - chip::Messaging::ExchangeManager * exchangeMgr = deviceProxy->GetExchangeManager(); - if (exchangeMgr == nullptr) - { - ChipLogError(SoftwareUpdate, "Cannot retrieve exchange manager from device"); - return; - } - - Optional session = deviceProxy->GetSecureSession(); - if (!session.HasValue()) - { - ChipLogError(SoftwareUpdate, "Cannot retrieve session from device"); - return; - } - - requestorCore->mExchangeCtx = exchangeMgr->NewContext(session.Value(), &requestorCore->mBdxMessenger); - - if (requestorCore->mExchangeCtx == nullptr) - { - ChipLogError(BDX, "Unable to allocate ec: exchangeMgr=%p sessionExists? %u, OTA progress cannot continue", - exchangeMgr, session.HasValue()); - return; - } + ChipLogError(SoftwareUpdate, "Failed to start download: %" CHIP_ERROR_FORMAT, err.Format()); + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Downloading, err); } - requestorCore->mBdxMessenger.Init(requestorCore->mBdxDownloader, requestorCore->mExchangeCtx); - requestorCore->mBdxDownloader->SetMessageDelegate(&requestorCore->mBdxMessenger); - CHIP_ERROR err = requestorCore->mBdxDownloader->SetBDXParams(initOptions); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Error init BDXDownloader: %" CHIP_ERROR_FORMAT, err.Format())); - err = requestorCore->mBdxDownloader->BeginPrepareDownload(); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Cannot begin prepare download: %" CHIP_ERROR_FORMAT, err.Format())); break; } case kApplyUpdate: { - ApplyUpdateRequest::Type args; - CHIP_ERROR err = requestorCore->BuildApplyUpdateRequest(args); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Failed to build ApplyUpdate command: %" CHIP_ERROR_FORMAT, err.Format())); - - Controller::OtaSoftwareUpdateProviderCluster cluster; - cluster.Associate(deviceProxy, requestorCore->mProviderEndpointId); + CHIP_ERROR err = requestorCore->SendApplyUpdateRequest(*deviceProxy); - err = cluster.InvokeCommand(args, requestorCore, OnApplyUpdateResponse, OnApplyUpdateFailure); - VerifyOrReturn(err == CHIP_NO_ERROR, - ChipLogError(SoftwareUpdate, "Failed to send ApplyUpdate command: %" CHIP_ERROR_FORMAT, err.Format())); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Failed to send ApplyUpdate command: %" CHIP_ERROR_FORMAT, err.Format()); + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Applying, err); + } break; } @@ -352,8 +316,31 @@ OTARequestorInterface::OTATriggerResult OTARequestor::TriggerImmediateQuery() // Called whenever FindOrEstablishSession fails void OTARequestor::OnConnectionFailure(void * context, PeerId peerId, CHIP_ERROR error) { + OTARequestor * requestorCore = static_cast(context); + VerifyOrDie(requestorCore != nullptr); + ChipLogError(SoftwareUpdate, "Failed to connect to node 0x%" PRIX64 ": %" CHIP_ERROR_FORMAT, peerId.GetNodeId(), error.Format()); + + switch (requestorCore->mOnConnectedAction) + { + case kQueryImage: + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Querying, error); + break; + case kStartBDX: + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Downloading, error); + break; + case kApplyUpdate: + requestorCore->mOtaRequestorDriver->HandleError(UpdateStateEnum::Applying, error); + break; + default: + break; + } +} + +void OTARequestor::DownloadUpdate() +{ + ConnectToProvider(kStartBDX); } void OTARequestor::ApplyUpdate() @@ -361,11 +348,27 @@ void OTARequestor::ApplyUpdate() ConnectToProvider(kApplyUpdate); } -CHIP_ERROR OTARequestor::BuildQueryImageRequest(QueryImageRequest & request) +void OTARequestor::OnDownloadStateChanged(OTADownloader::State state) +{ + VerifyOrReturn(mOtaRequestorDriver != nullptr); + + switch (state) + { + case OTADownloader::State::kComplete: + mOtaRequestorDriver->UpdateDownloaded(); + break; + case OTADownloader::State::kIdle: + mOtaRequestorDriver->HandleError(UpdateStateEnum::Downloading, CHIP_ERROR_CONNECTION_ABORTED); + break; + default: + break; + } +} + +CHIP_ERROR OTARequestor::SendQueryImageRequest(OperationalDeviceProxy & deviceProxy) { constexpr EmberAfOTADownloadProtocol kProtocolsSupported[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS }; - constexpr bool kRequestorCanConsent = false; - QueryImage::Type & args = request.args; + QueryImage::Type args; uint16_t vendorId; VerifyOrReturnError(Basic::Attributes::VendorID::Get(kRootEndpointId, &vendorId) == EMBER_ZCL_STATUS_SUCCESS, @@ -379,7 +382,7 @@ CHIP_ERROR OTARequestor::BuildQueryImageRequest(QueryImageRequest & request) CHIP_ERROR_READ_FAILED); args.protocolsSupported = kProtocolsSupported; - args.requestorCanConsent.SetValue(kRequestorCanConsent); + args.requestorCanConsent.SetValue(mOtaRequestorDriver->CanConsent()); uint16_t hardwareVersion; if (Basic::Attributes::HardwareVersion::Get(kRootEndpointId, &hardwareVersion) == EMBER_ZCL_STATUS_SUCCESS) @@ -387,27 +390,72 @@ CHIP_ERROR OTARequestor::BuildQueryImageRequest(QueryImageRequest & request) args.hardwareVersion.SetValue(hardwareVersion); } - if (Basic::Attributes::Location::Get(kRootEndpointId, MutableCharSpan(request.location)) == EMBER_ZCL_STATUS_SUCCESS) + char location[DeviceLayer::ConfigurationManager::kMaxLocationLength]; + if (Basic::Attributes::Location::Get(kRootEndpointId, MutableCharSpan(location)) == EMBER_ZCL_STATUS_SUCCESS) { - args.location.SetValue(CharSpan(request.location)); + args.location.SetValue(CharSpan(location)); } + Controller::OtaSoftwareUpdateProviderCluster cluster; + cluster.Associate(&deviceProxy, mProviderEndpointId); + + return cluster.InvokeCommand(args, this, OnQueryImageResponse, OnQueryImageFailure); +} + +CHIP_ERROR OTARequestor::ExtractUpdateDescription(const QueryImageResponseDecodableType & response, + UpdateDescription & update) const +{ + NodeId nodeId; + CharSpan fileDesignator; + + VerifyOrReturnError(response.imageURI.HasValue(), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(bdx::ParseURI(response.imageURI.Value(), nodeId, fileDesignator)); + update.imageURI = response.imageURI.Value(); + + VerifyOrReturnError(response.softwareVersion.HasValue(), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(response.softwareVersionString.HasValue(), CHIP_ERROR_INVALID_ARGUMENT); + update.softwareVersion = response.softwareVersion.Value(); + + VerifyOrReturnError(response.updateToken.HasValue(), CHIP_ERROR_INVALID_ARGUMENT); + update.updateToken = response.updateToken.Value(); + + update.userConsentNeeded = response.userConsentNeeded.ValueOr(false); + update.metadataForRequestor = response.metadataForRequestor.ValueOr({}); + return CHIP_NO_ERROR; } -bool OTARequestor::ValidateQueryImageResponse(const QueryImageResponse::DecodableType & response) const +CHIP_ERROR OTARequestor::StartDownload(OperationalDeviceProxy & deviceProxy) { - if (response.status == OTAQueryStatus::kUpdateAvailable) - { - VerifyOrReturnError(response.imageURI.HasValue(), false); - VerifyOrReturnError(response.softwareVersion.HasValue() && response.softwareVersionString.HasValue(), false); - VerifyOrReturnError(response.updateToken.HasValue(), false); - } + VerifyOrReturnError(mBdxDownloader != nullptr, CHIP_ERROR_INCORRECT_STATE); - return true; + // TODO: allow caller to provide their own OTADownloader instance and set BDX parameters + + TransferSession::TransferInitData initOptions; + initOptions.TransferCtlFlags = bdx::TransferControlFlags::kReceiverDrive; + initOptions.MaxBlockSize = mOtaRequestorDriver->GetMaxDownloadBlockSize(); + char testFileDes[9] = { "test.txt" }; + initOptions.FileDesLength = static_cast(strlen(testFileDes)); + initOptions.FileDesignator = reinterpret_cast(testFileDes); + + chip::Messaging::ExchangeManager * exchangeMgr = deviceProxy.GetExchangeManager(); + VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); + + Optional session = deviceProxy.GetSecureSession(); + VerifyOrReturnError(session.HasValue(), CHIP_ERROR_INCORRECT_STATE); + + mExchangeCtx = exchangeMgr->NewContext(session.Value(), &mBdxMessenger); + VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_NO_MEMORY); + + mBdxMessenger.Init(mBdxDownloader, mExchangeCtx); + mBdxDownloader->SetMessageDelegate(&mBdxMessenger); + mBdxDownloader->SetStateDelegate(this); + + ReturnErrorOnFailure(mBdxDownloader->SetBDXParams(initOptions)); + return mBdxDownloader->BeginPrepareDownload(); } -CHIP_ERROR OTARequestor::BuildApplyUpdateRequest(ApplyUpdateRequest::Type & args) +CHIP_ERROR OTARequestor::SendApplyUpdateRequest(OperationalDeviceProxy & deviceProxy) { if (mUpdateToken.empty()) { @@ -423,9 +471,14 @@ CHIP_ERROR OTARequestor::BuildApplyUpdateRequest(ApplyUpdateRequest::Type & args mUpdateToken = ByteSpan(mUpdateTokenBuffer, sizeof(NodeId)); } + ApplyUpdateRequest::Type args; args.updateToken = mUpdateToken; args.newVersion = mUpdateVersion; - return CHIP_NO_ERROR; + + Controller::OtaSoftwareUpdateProviderCluster cluster; + cluster.Associate(&deviceProxy, mProviderEndpointId); + + return cluster.InvokeCommand(args, this, OnApplyUpdateResponse, OnApplyUpdateFailure); } } // namespace chip diff --git a/src/app/clusters/ota-requestor/OTARequestor.h b/src/app/clusters/ota-requestor/OTARequestor.h index 1d494005aba284..663ecbce0a2ba6 100644 --- a/src/app/clusters/ota-requestor/OTARequestor.h +++ b/src/app/clusters/ota-requestor/OTARequestor.h @@ -33,7 +33,7 @@ namespace chip { // This class implements all of the core logic of the OTA Requestor -class OTARequestor : public OTARequestorInterface +class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDelegate { public: // Various actions to take when OnConnected callback is called @@ -52,9 +52,15 @@ class OTARequestor : public OTARequestorInterface // and download the new image if available OTATriggerResult TriggerImmediateQuery() override; + // Initiate download of the new image + void DownloadUpdate() override; + // Send ApplyImage void ApplyUpdate() override; + // Handle download state change + void OnDownloadStateChanged(OTADownloader::State state) override; + // A setter for the delegate class pointer void SetOtaRequestorDriver(OTARequestorDriver * driver) { mOtaRequestorDriver = driver; } @@ -121,7 +127,6 @@ class OTARequestor : public OTARequestorInterface } private: - struct QueryImageRequest; using QueryImageResponseDecodableType = app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::DecodableType; using ApplyUpdateResponseDecodableType = app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::DecodableType; @@ -195,19 +200,24 @@ class OTARequestor : public OTARequestorInterface }; /** - * Create a QueryImage request using values from the Basic cluster attributes + * Send QueryImage request using values matching Basic cluster + */ + CHIP_ERROR SendQueryImageRequest(OperationalDeviceProxy & deviceProxy); + + /** + * Validate and extract mandatory information from QueryImageResponse */ - CHIP_ERROR BuildQueryImageRequest(QueryImageRequest & request); + CHIP_ERROR ExtractUpdateDescription(const QueryImageResponseDecodableType & response, UpdateDescription & update) const; /** - * Verify all required fields are present in the QueryImageResponse + * Start download of the software image returned in QueryImageResponse */ - bool ValidateQueryImageResponse(const QueryImageResponseDecodableType & response) const; + CHIP_ERROR StartDownload(OperationalDeviceProxy & deviceProxy); /** - * Create a ApplyUpdate request using values obtained from QueryImageResponse + * Send ApplyUpdate request using values obtained from QueryImageResponse */ - CHIP_ERROR BuildApplyUpdateRequest(app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::Type & args); + CHIP_ERROR SendApplyUpdateRequest(OperationalDeviceProxy & deviceProxy); /** * Session connection callbacks diff --git a/src/include/platform/OTARequestorDriver.h b/src/include/platform/OTARequestorDriver.h index a1bcb6855801e5..dc6fe2de9bb99f 100644 --- a/src/include/platform/OTARequestorDriver.h +++ b/src/include/platform/OTARequestorDriver.h @@ -25,25 +25,29 @@ #pragma once #include +#include namespace chip { -/* Commented out until the API is supported // The set of parameters needed for starting a BDX download. -struct BdxDownloadParameters +struct UpdateDescription { - uint32_t delayedActionTime; // Might not be needed - chip::CharSpan imageURI; + CharSpan imageURI; uint32_t softwareVersion; - chip::CharSpan softwareVersionString; // Might not be needed - chip::ByteSpan updateToken; - bool userConsentNeeded; // Might not be needed - chip::ByteSpan metadataForRequestor; // Might not be needed + ByteSpan updateToken; + bool userConsentNeeded; + ByteSpan metadataForRequestor; +}; + +enum class UpdateNotFoundReason +{ + Busy, + NotAvailable, + UpToDate }; -*/ // Possible values for the UpdateState attribute -enum UpdateStateEnum +enum class UpdateStateEnum { Unknown = 0, Idle = 1, @@ -56,52 +60,39 @@ enum UpdateStateEnum DelayedOnUserConsent = 8, }; -// Return type for RequestUserConsent() -enum UserConsentAction -{ - ImmediateYes = 1, - ImmediateNo = 2, - Requested = 3, -}; - // Interface class to abstract the OTA-related business logic. Each application // must implement this interface. All calls must be non-blocking unless stated otherwise class OTARequestorDriver { public: - // Mandatory methods, applications are required to implement these + virtual ~OTARequestorDriver() = default; - // A call into the application logic to give it a chance to allow or stop the Requestor - // from proceeding with actual image download. Returning TRUE will allow the download - // to proceed, returning FALSE will abort the download process. - virtual bool CheckImageDownloadAllowed() = 0; + /// Return if the device provides UI for asking a user for consent before downloading a software image + virtual bool CanConsent() = 0; - // Application is directed to complete user consent: either return ImmediateYes/ImmediateNo - // without blocking or return Requested and call OTARequestor::OnUserConsent() later. - virtual UserConsentAction RequestUserConsent() = 0; + /// Return maximum supported download block size + virtual uint16_t GetMaxDownloadBlockSize() { return 1024; } - // Notify the application that the download is complete and the image can be applied - virtual void ImageDownloadComplete() = 0; + /// Called when an error occurs at any OTA requestor operation + virtual void HandleError(UpdateStateEnum state, CHIP_ERROR error) = 0; - // Optional methods, applications may choose to implement these + /// Called when the latest query found a software update + virtual void UpdateAvailable(const UpdateDescription & update, System::Clock::Seconds32 delay) = 0; - /* Commented out until the API is supported - // This method informs the application of the BDX download parameters. This info can be used - // later on for diecting the Requestor to resume an interrupted download - virtual void PostBdxDownloadParameters(const BdxDownloadParameters & bdxParameters){}; - */ + /// Called when the latest query did not find any software update + virtual void UpdateNotFound(UpdateNotFoundReason reason, System::Clock::Seconds32 delay) = 0; - // Return maximum supported download block size - virtual uint16_t GetMaxDownloadBlockSize() { return 1024; } + /// Called when the download of a new software image has finished + virtual void UpdateDownloaded() = 0; - // Get Version of the last downloaded image, return CHIP_ERROR_NOT_FOUND if none exists - virtual CHIP_ERROR GetLastDownloadedImageVersion(uint32_t & out_version) { return CHIP_ERROR_NOT_FOUND; } + /// Called when the current software update can be applied + virtual void UpdateConfirmed(System::Clock::Seconds32 delay) = 0; - // Notify application of a change in the UpdateState attribute - virtual void NotifyUpdateStateChange(chip::UpdateStateEnum state){}; + /// Called when the requestor shall ask again before applying the current software update + virtual void UpdateSuspended(System::Clock::Seconds32 delay) = 0; - // Destructor - virtual ~OTARequestorDriver() = default; + /// Called when the current software update should be discontinued + virtual void UpdateDiscontinued() = 0; }; } // namespace chip diff --git a/src/include/platform/OTARequestorInterface.h b/src/include/platform/OTARequestorInterface.h index 214fe76af2dc21..b629c67fc85916 100644 --- a/src/include/platform/OTARequestorInterface.h +++ b/src/include/platform/OTARequestorInterface.h @@ -58,6 +58,9 @@ class OTARequestorInterface // Send QueryImage command virtual OTATriggerResult TriggerImmediateQuery() = 0; + // Download image + virtual void DownloadUpdate() = 0; + // Send ApplyImage command virtual void ApplyUpdate() = 0; diff --git a/src/lib/shell/commands/Ota.cpp b/src/lib/shell/commands/Ota.cpp index 58cbe87b061ba4..93dee547918bc9 100644 --- a/src/lib/shell/commands/Ota.cpp +++ b/src/lib/shell/commands/Ota.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include using namespace chip::DeviceLayer; diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index cd12ba5da998df..c154565b8ab042 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -296,6 +296,13 @@ if (chip_device_platform != "none") { "PlatformEventSupport.cpp", ] + if (chip_enable_ota_requestor) { + sources += [ + "GenericOTARequestorDriver.cpp", + "GenericOTARequestorDriver.h", + ] + } + cflags = [ "-Wconversion" ] public_deps = [ diff --git a/src/platform/Darwin/BUILD.gn b/src/platform/Darwin/BUILD.gn index 7b31a881b60172..707f7f79183db9 100644 --- a/src/platform/Darwin/BUILD.gn +++ b/src/platform/Darwin/BUILD.gn @@ -81,8 +81,6 @@ static_library("Darwin") { # using the implements from Linux platform "../Linux/OTAImageProcessorImpl.cpp", "../Linux/OTAImageProcessorImpl.h", - "../Linux/OTARequestorDriverImpl.cpp", - "../Linux/OTARequestorDriverImpl.h", ] } diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn index e06792500a7de4..7d70d6bec7f839 100644 --- a/src/platform/ESP32/BUILD.gn +++ b/src/platform/ESP32/BUILD.gn @@ -58,8 +58,6 @@ static_library("ESP32") { sources += [ "OTAImageProcessorImpl.cpp", "OTAImageProcessorImpl.h", - "OTARequestorDriverImpl.cpp", - "OTARequestorDriverImpl.h", ] } diff --git a/src/platform/ESP32/OTARequestorDriverImpl.cpp b/src/platform/ESP32/OTARequestorDriverImpl.cpp deleted file mode 100644 index 0d12b195284e31..00000000000000 --- a/src/platform/ESP32/OTARequestorDriverImpl.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * 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. - */ - -#include "OTARequestorDriverImpl.h" -#include "esp_log.h" - -#define TAG "OTARequestorDriver" - -namespace chip { - -bool OTARequestorDriverImpl::CheckImageDownloadAllowed() -{ - return true; -} - -void OTARequestorDriverImpl::ImageDownloadComplete() -{ - ESP_LOGI(TAG, "Image download complete"); -} - -UserConsentAction OTARequestorDriverImpl::RequestUserConsent() -{ - return ImmediateYes; -} - -} // namespace chip diff --git a/src/platform/ESP32/OTARequestorDriverImpl.h b/src/platform/ESP32/OTARequestorDriverImpl.h deleted file mode 100644 index 848f6d14ae0620..00000000000000 --- a/src/platform/ESP32/OTARequestorDriverImpl.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * 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 - -namespace chip { - -class OTARequestorDriverImpl : public OTARequestorDriver -{ -public: - bool CheckImageDownloadAllowed() override; - void ImageDownloadComplete() override; - UserConsentAction RequestUserConsent() override; -}; -} // namespace chip diff --git a/src/platform/GenericOTARequestorDriver.cpp b/src/platform/GenericOTARequestorDriver.cpp new file mode 100644 index 00000000000000..96acdfbe75c544 --- /dev/null +++ b/src/platform/GenericOTARequestorDriver.cpp @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * 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. + */ + +#include "GenericOTARequestorDriver.h" + +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace { + +GenericOTARequestorDriver * ToDriver(void * context) +{ + return static_cast(context); +} + +} // namespace + +bool GenericOTARequestorDriver::CanConsent() +{ + return false; +} + +uint16_t GenericOTARequestorDriver::GetMaxDownloadBlockSize() +{ + return 1024; +} + +void GenericOTARequestorDriver::HandleError(UpdateStateEnum state, CHIP_ERROR error) +{ + // TODO: Schedule the next QueryImage +} + +void GenericOTARequestorDriver::UpdateAvailable(const UpdateDescription & update, System::Clock::Seconds32 delay) +{ + VerifyOrDie(mRequestor != nullptr); + ScheduleDelayedAction(UpdateStateEnum::DelayedOnQuery, delay, + [](System::Layer *, void * context) { ToDriver(context)->mRequestor->DownloadUpdate(); }); +} + +void GenericOTARequestorDriver::UpdateNotFound(UpdateNotFoundReason reason, System::Clock::Seconds32 delay) +{ + // TODO: Schedule the next QueryImage +} + +void GenericOTARequestorDriver::UpdateDownloaded() +{ + VerifyOrDie(mRequestor != nullptr); + mRequestor->ApplyUpdate(); +} + +void GenericOTARequestorDriver::UpdateConfirmed(System::Clock::Seconds32 delay) +{ + VerifyOrDie(mImageProcessor != nullptr); + ScheduleDelayedAction(UpdateStateEnum::DelayedOnApply, delay, + [](System::Layer *, void * context) { ToDriver(context)->mImageProcessor->Apply(); }); +} + +void GenericOTARequestorDriver::UpdateSuspended(System::Clock::Seconds32 delay) +{ + VerifyOrDie(mRequestor != nullptr); + ScheduleDelayedAction(UpdateStateEnum::DelayedOnApply, delay, + [](System::Layer *, void * context) { ToDriver(context)->mRequestor->ApplyUpdate(); }); +} + +void GenericOTARequestorDriver::UpdateDiscontinued() +{ + VerifyOrDie(mImageProcessor != nullptr); + mImageProcessor->Abort(); +} + +void GenericOTARequestorDriver::ScheduleDelayedAction(UpdateStateEnum state, System::Clock::Seconds32 delay, + System::TimerCompleteCallback action) +{ + CHIP_ERROR error = SystemLayer().StartTimer(std::chrono::duration_cast(delay), action, this); + + if (error != CHIP_NO_ERROR) + { + HandleError(state, error); + } +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/GenericOTARequestorDriver.h b/src/platform/GenericOTARequestorDriver.h new file mode 100644 index 00000000000000..9f552a763a30d2 --- /dev/null +++ b/src/platform/GenericOTARequestorDriver.h @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * 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 +#include +#include + +namespace chip { + +class OTARequestorInterface; +class OTAImageProcessorInterface; + +namespace DeviceLayer { + +class GenericOTARequestorDriver : public OTARequestorDriver +{ +public: + void Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor) + { + mRequestor = requestor; + mImageProcessor = processor; + } + + bool CanConsent() override; + uint16_t GetMaxDownloadBlockSize() override; + + void HandleError(UpdateStateEnum state, CHIP_ERROR error) override; + void UpdateAvailable(const UpdateDescription & update, System::Clock::Seconds32 delay) override; + void UpdateNotFound(UpdateNotFoundReason reason, System::Clock::Seconds32 delay) override; + void UpdateDownloaded() override; + void UpdateConfirmed(System::Clock::Seconds32 delay) override; + void UpdateSuspended(System::Clock::Seconds32 delay) override; + void UpdateDiscontinued() override; + +private: + void ScheduleDelayedAction(UpdateStateEnum state, System::Clock::Seconds32 delay, System::TimerCompleteCallback action); + + OTARequestorInterface * mRequestor = nullptr; + OTAImageProcessorInterface * mImageProcessor = nullptr; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Linux/BUILD.gn b/src/platform/Linux/BUILD.gn index f5bdc54851a6e8..0033bac95cc3f7 100644 --- a/src/platform/Linux/BUILD.gn +++ b/src/platform/Linux/BUILD.gn @@ -106,8 +106,6 @@ static_library("Linux") { sources += [ "OTAImageProcessorImpl.cpp", "OTAImageProcessorImpl.h", - "OTARequestorDriverImpl.cpp", - "OTARequestorDriverImpl.h", ] } diff --git a/src/platform/Linux/OTARequestorDriverImpl.cpp b/src/platform/Linux/OTARequestorDriverImpl.cpp deleted file mode 100644 index 5fcd1f68ab4438..00000000000000 --- a/src/platform/Linux/OTARequestorDriverImpl.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright (c) 2021 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. - */ - -/* This file contains the Linux implementation of the OTAImageProcessorDriver - * interface class - */ - -#include "OTARequestorDriverImpl.h" - -using namespace chip; - -// A call into the application logic to give it a chance to allow or stop the Requestor -// from proceeding with actual image download. Returning TRUE will allow the download -// to proceed, returning FALSE will abort the download process. -bool OTARequestorDriverImpl::CheckImageDownloadAllowed() -{ - return true; -} - -// Notify the application that the download is complete and the image can be applied -void OTARequestorDriverImpl::ImageDownloadComplete() {} - -UserConsentAction OTARequestorDriverImpl::RequestUserConsent() -{ - return ImmediateYes; -} diff --git a/src/platform/Linux/OTARequestorDriverImpl.h b/src/platform/Linux/OTARequestorDriverImpl.h deleted file mode 100644 index 43664db1b12558..00000000000000 --- a/src/platform/Linux/OTARequestorDriverImpl.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Copyright (c) 2021 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. - */ - -/* This file contains the decalarions for the Linux implementation of the - * the OTARequestorDriver interface class - */ -#include - -namespace chip { - -class OTARequestorDriverImpl : public OTARequestorDriver -{ - - // Virtual functions from OTARequestorDriver -- start - - // A call into the application logic to give it a chance to allow or stop the Requestor - // from proceeding with actual image download. Returning TRUE will allow the download - // to proceed, returning FALSE will abort the download process. - bool CheckImageDownloadAllowed(); - - // Notify the application that the download is complete and the image can be applied - void ImageDownloadComplete(); - - // Application is directed to complete user consent: either return ImmediateYes/ImmediateNo - // without blocking or return Requested and call OTARequestor::OnUserConsent() later. - virtual UserConsentAction RequestUserConsent(); - - // Virtual functions from OTARequestorDriver -- end -}; - -} // namespace chip