diff --git a/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.h b/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.h index 05ba9e7960a084..b75ad27ba2a2d9 100644 --- a/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.h +++ b/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.h @@ -38,16 +38,23 @@ typedef NS_ENUM(uint8_t, UserConsentState) { @end @interface OTAProviderDelegate : NSObject -- (void)handleQueryImage:(MTROtaSoftwareUpdateProviderClusterQueryImageParams * _Nonnull)params - completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler; +- (void)handleQueryImageForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterQueryImageParams * _Nonnull)params + completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler; -- (void)handleApplyUpdateRequest:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * _Nonnull)params - completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler; +- (void)handleApplyUpdateRequestForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * _Nonnull)params + completionHandler: + (void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler; -- (void)handleNotifyUpdateApplied:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * _Nonnull)params - completionHandler:(StatusCompletion _Nonnull)completionHandler; +- (void)handleNotifyUpdateAppliedForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * _Nonnull)params + completionHandler:(StatusCompletion _Nonnull)completionHandler; @property (strong, nonatomic, nullable) NSArray * candidates; @property (strong, nonatomic, nullable) DeviceSoftwareVersionModel * selectedCandidate; diff --git a/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.mm b/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.mm index 5a8b1a4d65c645..97f7e47db9000f 100644 --- a/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.mm +++ b/examples/darwin-framework-tool/commands/provider/OTAProviderDelegate.mm @@ -40,9 +40,11 @@ - (instancetype)init return self; } -- (void)handleQueryImage:(MTROtaSoftwareUpdateProviderClusterQueryImageParams * _Nonnull)params - completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler +- (void)handleQueryImageForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterQueryImageParams * _Nonnull)params + completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler { NSError * error; @@ -102,9 +104,12 @@ - (void)handleQueryImage:(MTROtaSoftwareUpdateProviderClusterQueryImageParams * completionHandler(_selectedCandidate, error); } -- (void)handleApplyUpdateRequest:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * _Nonnull)params - completionHandler:(void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler +- (void)handleApplyUpdateRequestForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * _Nonnull)params + completionHandler: + (void (^_Nonnull)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler { MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * applyUpdateResponseParams = [[MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams alloc] init]; @@ -112,15 +117,19 @@ - (void)handleApplyUpdateRequest:(MTROtaSoftwareUpdateProviderClusterApplyUpdate completionHandler(applyUpdateResponseParams, nil); } -- (void)handleNotifyUpdateApplied:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * _Nonnull)params - completionHandler:(StatusCompletion _Nonnull)completionHandler +- (void)handleNotifyUpdateAppliedForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + params:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * _Nonnull)params + completionHandler:(StatusCompletion _Nonnull)completionHandler { completionHandler(nil); } -- (void)handleBDXTransferSessionBegin:(NSString * _Nonnull)fileDesignator - offset:(NSNumber * _Nonnull)offset - completionHandler:(void (^)(NSError * error))completionHandler +- (void)handleBDXTransferSessionBeginForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + fileDesignator:(NSString * _Nonnull)fileDesignator + offset:(NSNumber * _Nonnull)offset + completionHandler:(void (^)(NSError * error))completionHandler { NSLog(@"BDX TransferSession begin with %@ (offset: %@)", fileDesignator, offset); @@ -161,7 +170,9 @@ - (void)handleBDXTransferSessionBegin:(NSString * _Nonnull)fileDesignator completionHandler(nil); } -- (void)handleBDXTransferSessionEnd:(NSError * _Nullable)error +- (void)handleBDXTransferSessionEndForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + error:(NSError * _Nullable)error { NSLog(@"BDX TransferSession end with error: %@", error); _mFileHandle = nil; @@ -169,10 +180,12 @@ - (void)handleBDXTransferSessionEnd:(NSError * _Nullable)error _mFileEndOffset = nil; } -- (void)handleBDXQuery:(NSNumber * _Nonnull)blockSize - blockIndex:(NSNumber * _Nonnull)blockIndex - bytesToSkip:(NSNumber * _Nonnull)bytesToSkip - completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler +- (void)handleBDXQueryForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + blockSize:(NSNumber * _Nonnull)blockSize + blockIndex:(NSNumber * _Nonnull)blockIndex + bytesToSkip:(NSNumber * _Nonnull)bytesToSkip + completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler { NSLog(@"BDX Query received blockSize: %@, blockIndex: %@", blockSize, blockIndex); diff --git a/src/darwin/Framework/CHIP/MTRControllerFactory.mm b/src/darwin/Framework/CHIP/MTRControllerFactory.mm index 3260c00c636da3..337299bde13570 100644 --- a/src/darwin/Framework/CHIP/MTRControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRControllerFactory.mm @@ -578,6 +578,17 @@ - (void)controllerShuttingDown:(MTRDeviceController *)controller } } +- (nullable MTRDeviceController *)runningControllerForFabricIndex:(chip::FabricIndex)fabricIndex +{ + for (MTRDeviceController * existing in _controllers) { + if ([existing fabricIndex] == fabricIndex) { + return existing; + } + } + + return nil; +} + - (MTRPersistentStorageDelegateBridge *)storageDelegateBridge { return _persistentStorageDelegateBridge; diff --git a/src/darwin/Framework/CHIP/MTRControllerFactory_Internal.h b/src/darwin/Framework/CHIP/MTRControllerFactory_Internal.h index 3f783d7b39e975..e976aea01609af 100644 --- a/src/darwin/Framework/CHIP/MTRControllerFactory_Internal.h +++ b/src/darwin/Framework/CHIP/MTRControllerFactory_Internal.h @@ -23,6 +23,8 @@ #import "MTRControllerFactory.h" +#include + class MTRPersistentStorageDelegateBridge; namespace chip { @@ -40,6 +42,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)controllerShuttingDown:(MTRDeviceController *)controller; +/** + * Find a running controller, if any, for the given fabric index. + */ +- (nullable MTRDeviceController *)runningControllerForFabricIndex:(chip::FabricIndex)fabricIndex; + @property (readonly) MTRPersistentStorageDelegateBridge * storageDelegateBridge; @property (readonly) chip::Credentials::GroupDataProvider * groupData; @property (readonly) chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier; diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegate.h b/src/darwin/Framework/CHIP/MTROTAProviderDelegate.h index 9f431a3f8777b1..6949185957f677 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegate.h +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegate.h @@ -28,50 +28,68 @@ NS_ASSUME_NONNULL_BEGIN @protocol MTROTAProviderDelegate @required /** - * Notify the delegate when query image command is received - * + * Notify the delegate when the query image command is received from some node. + * The controller identifies the fabric the node is on, and the nodeID + * identifies the node within that fabric. */ -- (void)handleQueryImage:(MTROtaSoftwareUpdateProviderClusterQueryImageParams *)params - completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler; +- (void)handleQueryImageForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterQueryImageParams *)params + completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler; /** - * Notify the delegate when apply update request command is received - * + * Notify the delegate when the apply update request command is received from + * some node. The controller identifies the fabric the node is on, and the + * nodeID identifies the node within that fabric. */ -- (void)handleApplyUpdateRequest:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams *)params - completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler; +- (void)handleApplyUpdateRequestForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams *)params + completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler; /** - * Notify the delegate when notify update applied command is received - * + * Notify the delegate when the notify update applied command is received from + * some node. The controller identifies the fabric the node is on, and the + * nodeID identifies the node within that fabric. */ -- (void)handleNotifyUpdateApplied:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams *)params - completionHandler:(StatusCompletion)completionHandler; +- (void)handleNotifyUpdateAppliedForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams *)params + completionHandler:(StatusCompletion)completionHandler; /** - * Notify the delegate when a BDX Session starts - * + * Notify the delegate when a BDX Session starts for some node. The controller + * identifies the fabric the node is on, and the nodeID identifies the node + * within that fabric. */ -- (void)handleBDXTransferSessionBegin:(NSString * _Nonnull)fileDesignator - offset:(NSNumber * _Nonnull)offset - completionHandler:(void (^)(NSError * error))completionHandler; +- (void)handleBDXTransferSessionBeginForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + fileDesignator:(NSString *)fileDesignator + offset:(NSNumber *)offset + completionHandler:(void (^)(NSError * error))completionHandler; /** - * Notify the delegate when a BDX Session ends - * + * Notify the delegate when a BDX Session ends for some node. The controller + * identifies the fabric the node is on, and the nodeID identifies the node + * within that fabric. */ -- (void)handleBDXTransferSessionEnd:(NSError * _Nullable)error; +- (void)handleBDXTransferSessionEndForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + error:(NSError * _Nullable)error; /** - * Notify the delegate when a BDX Query message has been received - * + * Notify the delegate when a BDX Query message has been received for some node. + * The controller identifies the fabric the node is on, and the nodeID + * identifies the node within that fabric. */ -- (void)handleBDXQuery:(NSNumber * _Nonnull)blockSize - blockIndex:(NSNumber * _Nonnull)blockIndex - bytesToSkip:(NSNumber * _Nonnull)bytesToSkip - completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler; +- (void)handleBDXQueryForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + blockSize:(NSNumber *)blockSize + blockIndex:(NSNumber *)blockIndex + bytesToSkip:(NSNumber *)bytesToSkip + completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler; @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm index f285e2177748b3..084797a7cd6140 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm @@ -16,6 +16,7 @@ */ #import "MTROTAProviderDelegateBridge.h" +#import "MTRControllerFactory_Internal.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" @@ -33,6 +34,7 @@ using namespace chip::app; using namespace chip::app::Clusters::OtaSoftwareUpdateProvider; using namespace chip::bdx; +using Protocols::InteractionModel::Status; // TODO Expose a method onto the delegate to make that configurable. constexpr uint32_t kMaxBdxBlockSize = 1024; @@ -118,6 +120,8 @@ CHIP_ERROR OnMessageToSend(TransferSession::OutputEvent & event) CHIP_ERROR OnTransferSessionBegin(TransferSession::OutputEvent & event) { + VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); uint16_t fdl = 0; auto fd = mTransfer.GetFileDesignator(fdl); VerifyOrReturnError(fdl <= bdx::kMaxFileDesignatorLen, CHIP_ERROR_INVALID_ARGUMENT); @@ -145,9 +149,17 @@ CHIP_ERROR OnTransferSessionBegin(TransferSession::OutputEvent & event) }); }; + auto * controller = [[MTRControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + auto nodeId = @(mNodeId.Value()); + auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleBDXTransferSessionBegin:fileDesignator offset:offset completionHandler:completionHandler]; + [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId + controller:controller + fileDesignator:fileDesignator + offset:offset + completionHandler:completionHandler]; }); return CHIP_NO_ERROR; @@ -155,6 +167,9 @@ CHIP_ERROR OnTransferSessionBegin(TransferSession::OutputEvent & event) CHIP_ERROR OnTransferSessionEnd(TransferSession::OutputEvent & event) { + VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); + CHIP_ERROR error = CHIP_NO_ERROR; if (event.EventType == TransferSession::OutputEventType::kTransferTimeout) { error = CHIP_ERROR_TIMEOUT; @@ -162,9 +177,15 @@ CHIP_ERROR OnTransferSessionEnd(TransferSession::OutputEvent & event) error = CHIP_ERROR_INTERNAL; } + auto * controller = [[MTRControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + auto nodeId = @(mNodeId.Value()); + auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleBDXTransferSessionEnd:[MTRError errorForCHIPErrorCode:error]]; + [strongDelegate handleBDXTransferSessionEndForNodeID:nodeId + controller:controller + error:[MTRError errorForCHIPErrorCode:error]]; }); ResetState(); @@ -173,6 +194,9 @@ CHIP_ERROR OnTransferSessionEnd(TransferSession::OutputEvent & event) CHIP_ERROR OnBlockQuery(TransferSession::OutputEvent & event) { + VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); + auto blockSize = @(mTransfer.GetTransferBlockSize()); auto blockIndex = @(mTransfer.GetNextBlockNum()); @@ -203,12 +227,18 @@ CHIP_ERROR OnBlockQuery(TransferSession::OutputEvent & event) // TODO Handle MaxLength + auto * controller = [[MTRControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + auto nodeId = @(mNodeId.Value()); + auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleBDXQuery:blockSize - blockIndex:blockIndex - bytesToSkip:bytesToSkip - completionHandler:completionHandler]; + [strongDelegate handleBDXQueryForNodeID:nodeId + controller:controller + blockSize:blockSize + blockIndex:blockIndex + bytesToSkip:bytesToSkip + completionHandler:completionHandler]; }); return CHIP_NO_ERROR; @@ -321,9 +351,44 @@ void ResetState() void MTROTAProviderDelegateBridge::Shutdown() { gOtaSender.Shutdown(); } +namespace { +// Return false if we could not get peer node info (a running controller for +// the fabric and a node id). In that case we will have already added an +// error status to the CommandHandler. +// +// Otherwise set outNodeId and outController to values that identify the source +// node for the command. +bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath & commandPath, NodeId * outNodeId, + MTRDeviceController * __autoreleasing _Nonnull * _Nonnull outController) +{ + auto desc = commandHandler->GetSubjectDescriptor(); + if (desc.authMode != Access::AuthMode::kCase) { + commandHandler->AddStatus(commandPath, Status::Failure); + return false; + } + + auto * controller = + [[MTRControllerFactory sharedInstance] runningControllerForFabricIndex:commandHandler->GetAccessingFabricIndex()]; + if (controller == nil) { + commandHandler->AddStatus(commandPath, Status::Failure); + return false; + } + + *outController = controller; + *outNodeId = desc.subject; + return true; +} +} // anonymous namespace + void MTROTAProviderDelegateBridge::HandleQueryImage( CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::QueryImage::DecodableType & commandData) { + NodeId nodeId; + MTRDeviceController * controller; + if (!GetPeerNodeInfo(commandObj, commandPath, &nodeId, &controller)) { + return; + } + auto * commandParams = [[MTROtaSoftwareUpdateProviderClusterQueryImageParams alloc] init]; CHIP_ERROR err = ConvertToQueryImageParams(commandData, commandParams); if (err != CHIP_NO_ERROR) { @@ -384,13 +449,22 @@ void ResetState() auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleQueryImage:commandParams completionHandler:completionHandler]; + [strongDelegate handleQueryImageForNodeID:@(nodeId) + controller:controller + params:commandParams + completionHandler:completionHandler]; }); } void MTROTAProviderDelegateBridge::HandleApplyUpdateRequest(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::ApplyUpdateRequest::DecodableType & commandData) { + NodeId nodeId; + MTRDeviceController * controller; + if (!GetPeerNodeInfo(commandObj, commandPath, &nodeId, &controller)) { + return; + } + // Make sure to hold on to the command handler and command path to be used in the completion block __block CommandHandler::Handle handle(commandObj); __block ConcreteCommandPath cachedCommandPath(commandPath.mEndpointId, commandPath.mClusterId, commandPath.mCommandId); @@ -413,13 +487,22 @@ void ResetState() auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleApplyUpdateRequest:commandParams completionHandler:completionHandler]; + [strongDelegate handleApplyUpdateRequestForNodeID:@(nodeId) + controller:controller + params:commandParams + completionHandler:completionHandler]; }); } void MTROTAProviderDelegateBridge::HandleNotifyUpdateApplied(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::NotifyUpdateApplied::DecodableType & commandData) { + NodeId nodeId; + MTRDeviceController * controller; + if (!GetPeerNodeInfo(commandObj, commandPath, &nodeId, &controller)) { + return; + } + // Make sure to hold on to the command handler and command path to be used in the completion block __block CommandHandler::Handle handle(commandObj); __block ConcreteCommandPath cachedCommandPath(commandPath.mEndpointId, commandPath.mClusterId, commandPath.mCommandId); @@ -439,7 +522,10 @@ void ResetState() auto strongDelegate = mDelegate; dispatch_async(mWorkQueue, ^{ - [strongDelegate handleNotifyUpdateApplied:commandParams completionHandler:completionHandler]; + [strongDelegate handleNotifyUpdateAppliedForNodeID:@(nodeId) + controller:controller + params:commandParams + completionHandler:completionHandler]; }); } diff --git a/src/darwin/Framework/CHIPTests/MTRTestOTAProvider.m b/src/darwin/Framework/CHIPTests/MTRTestOTAProvider.m index 25c2d0647d31fd..9e880e74162f7b 100644 --- a/src/darwin/Framework/CHIPTests/MTRTestOTAProvider.m +++ b/src/darwin/Framework/CHIPTests/MTRTestOTAProvider.m @@ -20,37 +20,49 @@ @interface MTRTestOTAProvider () @end @implementation MTRTestOTAProvider -- (void)handleQueryImage:(MTROtaSoftwareUpdateProviderClusterQueryImageParams *)params - completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler +- (void)handleQueryImageForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterQueryImageParams *)params + completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler { } -- (void)handleApplyUpdateRequest:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams *)params - completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, - NSError * _Nullable error))completionHandler +- (void)handleApplyUpdateRequestForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams *)params + completionHandler:(void (^)(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data, + NSError * _Nullable error))completionHandler { } -- (void)handleNotifyUpdateApplied:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams *)params - completionHandler:(StatusCompletion)completionHandler +- (void)handleNotifyUpdateAppliedForNodeID:(NSNumber *)nodeID + controller:(MTRDeviceController *)controller + params:(MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams *)params + completionHandler:(StatusCompletion)completionHandler { } -- (void)handleBDXTransferSessionBegin:(NSString * _Nonnull)fileDesignator - offset:(NSNumber * _Nonnull)offset - completionHandler:(void (^)(NSError * error))completionHandler +- (void)handleBDXTransferSessionBeginForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + fileDesignator:(NSString * _Nonnull)fileDesignator + offset:(NSNumber * _Nonnull)offset + completionHandler:(void (^)(NSError * error))completionHandler { } -- (void)handleBDXTransferSessionEnd:(NSError * _Nullable)error +- (void)handleBDXTransferSessionEndForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + error:(NSError * _Nullable)error { } -- (void)handleBDXQuery:(NSNumber * _Nonnull)blockSize - blockIndex:(NSNumber * _Nonnull)blockIndex - bytesToSkip:(NSNumber * _Nonnull)bytesToSkip - completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler +- (void)handleBDXQueryForNodeID:(NSNumber * _Nonnull)nodeID + controller:(MTRDeviceController * _Nonnull)controller + blockSize:(NSNumber * _Nonnull)blockSize + blockIndex:(NSNumber * _Nonnull)blockIndex + bytesToSkip:(NSNumber * _Nonnull)bytesToSkip + completionHandler:(void (^)(NSData * _Nullable data, BOOL isEOF))completionHandler { }