diff --git a/examples/ota-requestor-app/mbed/CMakeLists.txt b/examples/ota-requestor-app/mbed/CMakeLists.txt index b43f3fc0ac5c61..a4cae46e1dbfce 100644 --- a/examples/ota-requestor-app/mbed/CMakeLists.txt +++ b/examples/ota-requestor-app/mbed/CMakeLists.txt @@ -42,6 +42,7 @@ target_include_directories(${APP_TARGET} PRIVATE ${GEN_DIR}/ota-requestor-app ${APP_ROOT}/ota-requestor-common ${MBED_COMMON}/util/include + ${CHIP_ROOT}/src/app/clusters/ota-requestor ) target_sources(${APP_TARGET} PRIVATE @@ -49,6 +50,7 @@ target_sources(${APP_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/main/ZclCallbacks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main/AppTask.cpp ${MBED_COMMON}/util/LEDWidget.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/main/OTARequestorImpl.cpp ${GEN_DIR}/ota-requestor-app/zap-generated/attribute-size.cpp ${GEN_DIR}/ota-requestor-app/zap-generated/callback-stub.cpp diff --git a/examples/ota-requestor-app/mbed/main/AppTask.cpp b/examples/ota-requestor-app/mbed/main/AppTask.cpp index 002af5bb989456..898c1536c8849a 100644 --- a/examples/ota-requestor-app/mbed/main/AppTask.cpp +++ b/examples/ota-requestor-app/mbed/main/AppTask.cpp @@ -45,6 +45,8 @@ #include "events/EventQueue.h" #include "platform/Callback.h" +#include "OTARequestorImpl.h" + static bool sIsWiFiStationProvisioned = false; static bool sIsWiFiStationEnabled = false; static bool sIsWiFiStationConnected = false; @@ -53,6 +55,7 @@ static bool sHaveBLEConnections = false; static events::EventQueue sAppEventQueue; +using namespace ::chip; using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; @@ -84,6 +87,8 @@ int AppTask::Init() ConnectivityMgr().SetBLEAdvertisingEnabled(true); } + OTARequestorImpl::GetInstance().Init(OnConnectProviderCallback); + chip::DeviceLayer::ConnectivityMgrImpl().StartWiFiManagement(); // Init ZCL Data Model and start server @@ -157,3 +162,44 @@ int AppTask::StartApp() sStatusLED.Animate(); } } + +void AppTask::OnConnectProviderHandler(AppEvent * aEvent) +{ + ChipLogProgress(NotSpecified, "OnConnectProviderHandler"); + + OTARequestorImpl::GetInstance().ConnectProvider(aEvent->OTAProviderConnectEvent.nodeId, + aEvent->OTAProviderConnectEvent.fabricIndex, + aEvent->OTAProviderConnectEvent.ipAddress); +} + +void AppTask::OnConnectProviderCallback(NodeId nodeId, FabricIndex fabricIndex, chip::Optional ipAddress) +{ + AppEvent ota_connect_provider_event; + ota_connect_provider_event.Type = AppEvent::kEventType_ota_provider_connect; + ota_connect_provider_event.OTAProviderConnectEvent.nodeId = nodeId; + ota_connect_provider_event.OTAProviderConnectEvent.fabricIndex = fabricIndex; + ota_connect_provider_event.OTAProviderConnectEvent.ipAddress = reinterpret_cast(ipAddress.Value().data()); + ota_connect_provider_event.Handler = OnConnectProviderHandler; + sAppTask.PostEvent(&ota_connect_provider_event); +} + +void AppTask::PostEvent(AppEvent * aEvent) +{ + auto handle = sAppEventQueue.call([event = *aEvent, this] { DispatchEvent(&event); }); + if (!handle) + { + ChipLogError(NotSpecified, "Failed to post event to app task event queue: Not enough memory"); + } +} + +void AppTask::DispatchEvent(const AppEvent * aEvent) +{ + if (aEvent->Handler) + { + aEvent->Handler(const_cast(aEvent)); + } + else + { + ChipLogError(NotSpecified, "Event received with no handler. Dropping event."); + } +} \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp b/examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp new file mode 100644 index 00000000000000..00d30495114f66 --- /dev/null +++ b/examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp @@ -0,0 +1,26 @@ +/* + * + * 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. + */ + +#include + +bool CheckImageDownloadAllowed() +{ + return true; +} + +void ImageDownloadComplete() {} \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/OTARequestorImpl.cpp b/examples/ota-requestor-app/mbed/main/OTARequestorImpl.cpp index e69de29bb2d1d6..e2241756923879 100644 --- a/examples/ota-requestor-app/mbed/main/OTARequestorImpl.cpp +++ b/examples/ota-requestor-app/mbed/main/OTARequestorImpl.cpp @@ -0,0 +1,253 @@ +/* + * + * 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. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using chip::DeviceProxy; +using chip::EndpointId; +using chip::FabricIndex; +using chip::NodeId; +using chip::OnDeviceConnected; +using chip::OnDeviceConnectionFailure; +using chip::PeerId; +using chip::Server; +using chip::VendorId; +using chip::Callback::Callback; +using chip::Inet::IPAddress; +using chip::System::Layer; +using chip::Transport::PeerAddress; +using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands; +using namespace chip::DeviceLayer; + +OTARequestorImpl OTARequestorImpl::sInstance; + +constexpr const char gRequestorLocation[] = { 'U', 'S' }; +constexpr EmberAfOTADownloadProtocol gRequestorProtocols[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS }; +constexpr chip::EndpointId gOtaProviderEndpoint = 0; +constexpr bool gRequestorCanConsent = false; + +static void OnProviderConnected(void * context, chip::DeviceProxy * deviceProxy); +static void OnProviderConnectionFailure(void * context, chip::NodeId deviceId, CHIP_ERROR error); + +static void +OnQueryImageResponse(void * context, + const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::DecodableType & response); +static void OnQueryImageFailure(void * context, EmberAfStatus status); + +static Callback mOnConnectedCallback(OnProviderConnected, nullptr); +static Callback mOnConnectionFailureCallback(OnProviderConnectionFailure, nullptr); + +OTARequestorImpl::OTARequestorImpl() +{ + mProviderNodeId = chip::kUndefinedNodeId; + mProviderFabricIndex = chip::kUndefinedFabricIndex; + mConnectProviderCallback = nullptr; +} + +bool OTARequestorImpl::HandleAnnounceOTAProvider( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) +{ + if (commandObj == nullptr) + { + ChipLogError(SoftwareUpdate, "Cannot access get FabricIndex"); + return true; + } + + mProviderNodeId = commandData.providerLocation; + mProviderFabricIndex = commandObj->GetAccessingFabricIndex(); + mAnnouncementReason = commandData.announcementReason; + mProviderIpAddress = commandData.metadataForNode; + + ChipLogProgress(SoftwareUpdate, "OTA Requestor received AnnounceOTAProvider"); + ChipLogProgress(SoftwareUpdate, " FabricIndex: %" PRIu8, mProviderFabricIndex); + ChipLogProgress(SoftwareUpdate, " ProviderNodeID: %" PRIu64 " (0x%" PRIX64 ")", mProviderNodeId, mProviderNodeId); + ChipLogProgress(SoftwareUpdate, " VendorID: %" PRIu16 " (0x%" PRIX16 ")", commandData.vendorId, commandData.vendorId); + ChipLogProgress(SoftwareUpdate, " ProviderIP: %s", reinterpret_cast(mProviderIpAddress.Value().data())); + ChipLogProgress(SoftwareUpdate, " AnnouncementReason: %" PRIu8, mAnnouncementReason); + + if (mConnectProviderCallback) + { + mConnectProviderCallback(mProviderNodeId, mProviderFabricIndex, mProviderIpAddress); + } + + return false; +} + +void OTARequestorImpl::ConnectProvider(NodeId peerNodeId, FabricIndex peerFabricIndex, const char * ipAddress) +{ + Server * server = &(Server::GetInstance()); + chip::FabricInfo * fabric = server->GetFabricTable().FindFabricWithIndex(peerFabricIndex); + if (fabric == nullptr) + { + ChipLogError(SoftwareUpdate, "Did not find fabric for index %d", peerFabricIndex); + return; + } + + chip::DeviceProxyInitParams initParams = { + .sessionManager = &(server->GetSecureSessionManager()), + .exchangeMgr = &(server->GetExchangeManager()), + .idAllocator = &(server->GetSessionIDAllocator()), + .fabricInfo = fabric, + .imDelegate = chip::Platform::New(), + }; + + chip::OperationalDeviceProxy * operationalDeviceProxy = + chip::Platform::New(initParams, fabric->GetPeerIdForNode(peerNodeId)); + if (operationalDeviceProxy == nullptr) + { + ChipLogError(SoftwareUpdate, "Failed in creating an instance of OperationalDeviceProxy"); + return; + } + + server->SetOperationalDeviceProxy(operationalDeviceProxy); + + // Explicitly calling UpdateDeviceData() should not be needed once OperationalDeviceProxy can resolve IP address from node + // ID and fabric index + IPAddress ipAddr; + IPAddress::FromString(ipAddress, ipAddr); + PeerAddress addr = PeerAddress::UDP(ipAddr, CHIP_PORT); + operationalDeviceProxy->UpdateDeviceData(addr, operationalDeviceProxy->GetMRPConfig()); + + CHIP_ERROR err = operationalDeviceProxy->Connect(&mOnConnectedCallback, &mOnConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot establish connection to peer device: %" CHIP_ERROR_FORMAT, err.Format()); + } +} + +void OnProviderConnected(void * context, chip::DeviceProxy * deviceProxy) +{ + ChipLogProgress(SoftwareUpdate, "OnProviderConnected"); + chip::Controller::OtaSoftwareUpdateProviderCluster cluster; + + CHIP_ERROR err = cluster.Associate(deviceProxy, gOtaProviderEndpoint); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Associate() failed: %" CHIP_ERROR_FORMAT, err.Format()); + return; + } + + // Send QueryImage command + uint16_t vendorId = 0; + uint16_t productId = 0; + uint16_t hardwareVersion = 0; + uint16_t softwareVersion = 0; + + ConfigurationMgr().GetVendorId(vendorId); + ConfigurationMgr().GetProductId(productId); + ConfigurationMgr().GetHardwareVersion(hardwareVersion); + ConfigurationMgr().GetSoftwareVersion(softwareVersion); + + QueryImage::Type request; + request.vendorId = static_cast(vendorId); + request.productId = productId; + request.softwareVersion = softwareVersion; + request.protocolsSupported = gRequestorProtocols; + request.hardwareVersion.Emplace(hardwareVersion); + request.location.Emplace(gRequestorLocation); + request.requestorCanConsent.SetValue(gRequestorCanConsent); + err = cluster.InvokeCommand(request, /* context = */ nullptr, OnQueryImageResponse, OnQueryImageFailure); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "QueryImage() failed: %" CHIP_ERROR_FORMAT, err.Format()); + } +} + +void OnProviderConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error) +{ + ChipLogError(SoftwareUpdate, "Provider connection failure 0x%" PRIX64 ": %" CHIP_ERROR_FORMAT, deviceId, error.Format()); +} + +void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response) +{ + ChipLogProgress(SoftwareUpdate, "OnQueryImageResponse"); + + OTARequestorImpl::GetInstance().HandleQueryImageResponse( + context, response.status, response.delayedActionTime.ValueOr(0), response.imageURI.ValueOr({}), + response.softwareVersion.ValueOr(0), response.softwareVersionString.ValueOr({}), response.updateToken.ValueOr({}), + response.userConsentNeeded.ValueOr(false), response.metadataForRequestor.ValueOr({})); +} + +void OnQueryImageFailure(void * context, EmberAfStatus status) +{ + ChipLogError(SoftwareUpdate, "QueryImage failure %" PRIu8, status); +} + +bool OTARequestorImpl::HandleQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, chip::CharSpan imageURI, + uint32_t softwareVersion, chip::CharSpan softwareVersionString, + chip::ByteSpan updateToken, bool userConsentNeeded, + chip::ByteSpan metadataForRequestor) +{ + switch (status) + { + case EMBER_ZCL_OTA_QUERY_STATUS_UPDATE_AVAILABLE: + ChipLogProgress(SoftwareUpdate, "Update available"); + break; + case EMBER_ZCL_OTA_QUERY_STATUS_BUSY: + ChipLogProgress(SoftwareUpdate, "OTA provider busy"); + return false; + case EMBER_ZCL_OTA_QUERY_STATUS_NOT_AVAILABLE: + ChipLogProgress(SoftwareUpdate, "Update not available"); + return false; + } + + ChipLogProgress(SoftwareUpdate, " Image URI: %.*s", static_cast(imageURI.size()), imageURI.data()); + ChipLogProgress(SoftwareUpdate, " Version: %" PRIu32, softwareVersion); + + if (updateToken.size() > sizeof(mUpdateDetails.updateToken)) + { + ChipLogError(SoftwareUpdate, "Update token too long"); + return false; + } + + memcpy(mUpdateDetails.updateToken, updateToken.data(), updateToken.size()); + mUpdateDetails.updateTokenLen = static_cast(updateToken.size()); + mUpdateDetails.updateVersion = softwareVersion; + + if (mOtaRequestorDriver) + { + auto ret = mOtaRequestorDriver->CheckImageDownloadAllowed(); + if (!ret) + { + ChipLogProgress(SoftwareUpdate, "Update download not allowed"); + return false; + } + } + + if (mDownloadUpdateCallback) + { + mDownloadUpdateCallback(); + } + return false; +} \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/ZclCallbacks.cpp b/examples/ota-requestor-app/mbed/main/ZclCallbacks.cpp index c885875c799a11..25aaa237cd3571 100644 --- a/examples/ota-requestor-app/mbed/main/ZclCallbacks.cpp +++ b/examples/ota-requestor-app/mbed/main/ZclCallbacks.cpp @@ -21,6 +21,7 @@ #include #include +#include "OTARequestorImpl.h" #include #include #include @@ -41,6 +42,15 @@ bool emberAfOtaSoftwareUpdateRequestorClusterAnnounceOtaProviderCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) { - emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + + auto ret = OTARequestorImpl::GetInstance().HandleAnnounceOTAProvider(commandObj, commandPath, commandData); + if (ret) + { + status = EMBER_ZCL_STATUS_FAILURE; + } + + emberAfSendImmediateDefaultResponse(status); return true; } diff --git a/examples/ota-requestor-app/mbed/main/include/AppEvent.h b/examples/ota-requestor-app/mbed/main/include/AppEvent.h new file mode 100644 index 00000000000000..527a6a2b9e1267 --- /dev/null +++ b/examples/ota-requestor-app/mbed/main/include/AppEvent.h @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * 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 +#include + +struct AppEvent; +typedef void (*EventHandler)(AppEvent *); + +struct AppEvent +{ + enum AppEventTypes + { + kEventType_ota_provider_connect = 0, + }; + + uint16_t Type; + + union + { + struct + { + chip::NodeId nodeId; + chip::FabricIndex fabricIndex; + const char * ipAddress; + } OTAProviderConnectEvent; + }; + + EventHandler Handler; +}; diff --git a/examples/ota-requestor-app/mbed/main/include/AppTask.h b/examples/ota-requestor-app/mbed/main/include/AppTask.h index 4a762aabee35b2..f850f4b4d5d76f 100644 --- a/examples/ota-requestor-app/mbed/main/include/AppTask.h +++ b/examples/ota-requestor-app/mbed/main/include/AppTask.h @@ -19,6 +19,8 @@ #pragma once +#include "AppEvent.h" + class AppTask { public: @@ -29,6 +31,14 @@ class AppTask int Init(); + void PostEvent(AppEvent * aEvent); + void DispatchEvent(const AppEvent * event); + + static void OnConnectProviderHandler(AppEvent * aEvent); + + static void OnConnectProviderCallback(chip::NodeId nodeId, chip::FabricIndex fabricIndex, + chip::Optional ipAddress); + static AppTask sAppTask; }; diff --git a/examples/ota-requestor-app/mbed/main/include/CHIPProjectConfig.h b/examples/ota-requestor-app/mbed/main/include/CHIPProjectConfig.h index ab3dbbecc38342..4e30516ad1db4a 100644 --- a/examples/ota-requestor-app/mbed/main/include/CHIPProjectConfig.h +++ b/examples/ota-requestor-app/mbed/main/include/CHIPProjectConfig.h @@ -28,8 +28,9 @@ #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 1 #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 -#define CHIP_SHELL_MAX_MODULES 30 - // Use a default pairing code if one hasn't been provisioned in flash. #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 + +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DISCOVERY 1 diff --git a/examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h b/examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h new file mode 100644 index 00000000000000..f800f84102f33a --- /dev/null +++ b/examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h @@ -0,0 +1,37 @@ +/* + * + * 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 declaration for the OTARequestorDriver class, an interface + * that abstracts the OTA-related business logic out of the Requestor functionality in + * the Matter SDK. Applications implementing the OTA Requestor functionality must include + * this file. + */ + +#pragma once + +class OTARequestorDriverImpl +{ +public: + // 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() { return true; } + + // Notify the application that the download is complete and the image can be applied + void ImageDownloadComplete() {} +}; \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/include/OTARequestorImpl.h b/examples/ota-requestor-app/mbed/main/include/OTARequestorImpl.h index e69de29bb2d1d6..32722f89cc374a 100644 --- a/examples/ota-requestor-app/mbed/main/include/OTARequestorImpl.h +++ b/examples/ota-requestor-app/mbed/main/include/OTARequestorImpl.h @@ -0,0 +1,104 @@ +/* + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "events/EventQueue.h" +#include + +class OTARequestorImpl +{ + typedef void (*ConnectToProviderCallback)(chip::NodeId, chip::FabricIndex, chip::Optional); + typedef void (*DownloadUpdateCallback)(void); + +public: + struct OTAUpdateDetails + { + uint8_t updateToken[32]; + uint8_t updateTokenLen; + uint32_t updateVersion; + }; + + static OTARequestorImpl & GetInstance() { return sInstance; } + + void Init(ConnectToProviderCallback connectProviderCallback = nullptr, DownloadUpdateCallback downloadUpdateCallback = nullptr) + { + mConnectProviderCallback = connectProviderCallback; + mDownloadUpdateCallback = downloadUpdateCallback; + } + + // Handler for the AnnounceOTAProvider command + bool HandleAnnounceOTAProvider( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData); + + // Handler for the QueryImageResponse command + bool HandleQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, chip::CharSpan imageURI, + uint32_t softwareVersion, chip::CharSpan softwareVersionString, chip::ByteSpan updateToken, + bool userConsentNeeded, chip::ByteSpan metadataForRequestor); + + // Handler for the ApplyUpdateResponse command + bool HandleApplyUpdateResponse( + chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) + { + return false; + } + + // Application directs the Requestor to start the Image Query process + // and download the new image if available + void TriggerImmediateQuery() {} + + // Application directs the Requestor to abort any processing related to + // the image update + void AbortImageUpdate() {} + + // A setter for the delegate class pointer + void SetOtaRequestorDriver(OTARequestorDriverImpl * driver); + + void ConnectProvider(chip::NodeId peerNodeId, chip::FabricIndex peerFabricIndex, const char * ipAddress); + +private: + OTARequestorImpl(); + + static OTARequestorImpl sInstance; + + chip::NodeId mProviderNodeId; + chip::FabricIndex mProviderFabricIndex; + EmberAfOTAAnnouncementReason mAnnouncementReason; + chip::Optional mProviderIpAddress; + + OTAUpdateDetails mUpdateDetails; + + ConnectToProviderCallback mConnectProviderCallback; + DownloadUpdateCallback mDownloadUpdateCallback; + + OTARequestorDriverImpl * mOtaRequestorDriver; +}; + +inline void OTARequestorImpl::SetOtaRequestorDriver(OTARequestorDriverImpl * driver) +{ + mOtaRequestorDriver = driver; +} \ No newline at end of file