diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj index 1591df3729aa04..cbc52e427053d4 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 3CCB8743286A593700771BAD /* CastingServerBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873D286A593700771BAD /* CastingServerBridge.mm */; }; 3CCB8744286A593700771BAD /* ConversionUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873E286A593700771BAD /* ConversionUtils.mm */; }; 3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */; }; + 3CE5ECCE2A673B30007CF331 /* CommissioningCallbackHandlers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */; }; + 3CE5ECD02A673E2C007CF331 /* CommissioningCallbackHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */; }; 3CE868F42946D76200FCB92B /* CommissionableDataProviderImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */; }; 3CF8532728E37F1000F07B9F /* MatterError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CF8532628E37F1000F07B9F /* MatterError.mm */; }; /* End PBXBuildFile section */ @@ -62,6 +64,8 @@ 3CCB873D286A593700771BAD /* CastingServerBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CastingServerBridge.mm; sourceTree = ""; }; 3CCB873E286A593700771BAD /* ConversionUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ConversionUtils.mm; sourceTree = ""; }; 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommissionerDiscoveryDelegateImpl.h; sourceTree = ""; }; + 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommissioningCallbackHandlers.h; sourceTree = ""; }; + 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CommissioningCallbackHandlers.m; sourceTree = ""; }; 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CommissionableDataProviderImpl.mm; sourceTree = ""; }; 3CF8532528E37ED800F07B9F /* MatterError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatterError.h; sourceTree = ""; }; 3CF8532628E37F1000F07B9F /* MatterError.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MatterError.mm; sourceTree = ""; }; @@ -131,6 +135,8 @@ 3C0D9CDF2920A30C00D3332B /* CommissionableDataProviderImpl.hpp */, 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */, 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */, + 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */, + 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */, ); path = MatterTvCastingBridge; sourceTree = ""; @@ -145,6 +151,7 @@ 3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */, 3C26AC8C2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp in Headers */, 3CCB8740286A593700771BAD /* CastingServerBridge.h in Headers */, + 3CE5ECCE2A673B30007CF331 /* CommissioningCallbackHandlers.h in Headers */, 3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */, 3CCB8741286A593700771BAD /* DiscoveredNodeData.h in Headers */, 3CCB87212869085400771BAD /* MatterTvCastingBridge.h in Headers */, @@ -249,6 +256,7 @@ files = ( 3CCB8743286A593700771BAD /* CastingServerBridge.mm in Sources */, 3C4E53B228E5184C00F293E8 /* TargetNavigatorTypes.mm in Sources */, + 3CE5ECD02A673E2C007CF331 /* CommissioningCallbackHandlers.m in Sources */, 3CF8532728E37F1000F07B9F /* MatterError.mm in Sources */, 3C4E53B628E5595A00F293E8 /* ContentLauncherTypes.mm in Sources */, 3C81C75028F7A7D3001CB9D1 /* VideoPlayer.m in Sources */, @@ -419,9 +427,6 @@ "$(CHIP_ROOT)/third_party/nlassert/repo/include", "$(CHIP_ROOT)/third_party/nlio/repo/include", "$(TEMP_DIR)/out/gen/include", - /* Compile time codegen would need this: - "$(TEMP_DIR)/out/gen/src/controller/data_model/zapgen/", - */ "$(CHIP_ROOT)/zzz_generated/app-common", ); INFOPLIST_KEY_NSHumanReadableCopyright = ""; @@ -502,9 +507,6 @@ "$(CHIP_ROOT)/third_party/nlassert/repo/include", "$(CHIP_ROOT)/third_party/nlio/repo/include", "$(TEMP_DIR)/out/gen/include", - /* Compile time codegen would need this: - "$(TEMP_DIR)/out/gen/src/controller/data_model/zapgen/", - */ "$(CHIP_ROOT)/zzz_generated/app-common", ); INFOPLIST_KEY_NSHumanReadableCopyright = ""; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h index d90e4db486156b..162b536330e427 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h @@ -16,6 +16,7 @@ */ #import "AppParameters.h" +#import "CommissioningCallbackHandlers.h" #import "ContentApp.h" #import "ContentLauncherTypes.h" #import "DiscoveredNodeData.h" @@ -109,9 +110,6 @@ @param clientQueue Queue to dispatch the call to the commissioningWindowRequestedHandler on - @param commissioningCompleteCallback Callback for when commissioning of this app has been completed via a call to the general - commissioning cluster (by usually an on-network TV/Media device acting as a Matter commissioner) - @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established @param onConnectionFailureCallback Handles MatterError if there is a failure in establishing connection @@ -119,14 +117,13 @@ @param onNewOrUpdatedEndpointCallback Handles a ContentApp * for each new ContentApp is found. May be called multiple times based on the number of ContentApp - @param commissioningWindowRequestedHandler Handler to call on requesting the opening of a commissioning window + @param commissioningCallbackHandlers Optional parameter to specific handlers for callbacks during commissioning */ - (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue - commissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler - commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; + commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; /*! @brief Gets the list of VideoPlayers currently connected diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm index 50c2467b85be3f..02b7a5f9168c4f 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm @@ -565,24 +565,89 @@ - (OnboardingPayload *)getOnboardingPayload } - (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue - commissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler - commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback + commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback { [self dispatchOnMatterSDKQueue:@"openBasicCommissioningWindow(...)" block:^{ + CommissioningCallbacks commissioningCallbacks; + if (commissioningCallbackHandlers != nil) { + if (commissioningCallbackHandlers.commissioningCompleteCallback != nil) { + commissioningCallbacks.commissioningComplete = [clientQueue, commissioningCallbackHandlers]( + CHIP_ERROR err) { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description: + @"openBasicCommissioningWindow(...) commissioningCompleteCallback" + block:^{ + commissioningCallbackHandlers.commissioningCompleteCallback( + CHIP_NO_ERROR == err); + }]; + }; + } + + if (commissioningCallbackHandlers.sessionEstablishmentStartedCallback != nil) { + commissioningCallbacks.sessionEstablishmentStarted + = [clientQueue, commissioningCallbackHandlers]() { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"openBasicCommissioningWindow(...) " + @"sessionEstablishmentStartedCallback" + block:^{ + commissioningCallbackHandlers + .sessionEstablishmentStartedCallback(); + }]; + }; + } + + if (commissioningCallbackHandlers.sessionEstablishedCallback != nil) { + commissioningCallbacks.sessionEstablished = [clientQueue, commissioningCallbackHandlers]() { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"openBasicCommissioningWindow(...) sessionEstablishedCallback" + block:^{ + commissioningCallbackHandlers.sessionEstablishedCallback(); + }]; + }; + } + + if (commissioningCallbackHandlers.sessionEstablishmentErrorCallback != nil) { + commissioningCallbacks.sessionEstablishmentError = [clientQueue, + commissioningCallbackHandlers]( + CHIP_ERROR err) { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"openBasicCommissioningWindow(...) " + @"sessionEstablishmentErrorCallback" + block:^{ + commissioningCallbackHandlers.sessionEstablishmentErrorCallback( + [[MatterError alloc] + initWithCode:err.AsInteger() + message:[NSString + stringWithUTF8String:err.AsString()]]); + }]; + }; + } + + if (commissioningCallbackHandlers.sessionEstablishmentStoppedCallback != nil) { + commissioningCallbacks.sessionEstablishmentStopped + = [clientQueue, commissioningCallbackHandlers]() { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"openBasicCommissioningWindow(...) " + @"sessionEstablishmentStoppedCallback" + block:^{ + commissioningCallbackHandlers + .sessionEstablishmentStoppedCallback(); + }]; + }; + } + } CHIP_ERROR err = CastingServer::GetInstance()->OpenBasicCommissioningWindow( - [clientQueue, commissioningCompleteCallback](CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) commissioningCompleteCallback" - block:^{ - commissioningCompleteCallback(CHIP_NO_ERROR == err); - }]; - }, + commissioningCallbacks, [clientQueue, onConnectionSuccessCallback](TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { VideoPlayer * videoPlayer = [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; @@ -614,10 +679,13 @@ - (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue }]; }); - dispatch_async(clientQueue, ^{ - ChipLogProgress(AppServer, "[async] Dispatching commissioningWindowRequestedHandler"); - commissioningWindowRequestedHandler(CHIP_NO_ERROR == err); - }); + if (commissioningCallbackHandlers != nil + && commissioningCallbackHandlers.commissioningWindowRequestedHandler != nil) { + dispatch_async(clientQueue, ^{ + ChipLogProgress(AppServer, "[async] Dispatching commissioningWindowRequestedHandler"); + commissioningCallbackHandlers.commissioningWindowRequestedHandler(CHIP_NO_ERROR == err); + }); + } }]; } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h new file mode 100644 index 00000000000000..664faa9516dcc2 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h @@ -0,0 +1,70 @@ +/** + * + * Copyright (c) 2020-2023 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. + */ + +#import "MatterError.h" +#import + +#ifndef CommissioningCallbacksHandlers_h +#define CommissioningCallbacksHandlers_h + +@interface CommissioningCallbackHandlers : NSObject + +- (CommissioningCallbackHandlers * _Nonnull) + initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler + commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback + sessionEstablishmentStartedCallback:(void (^_Nullable)(void))sessionEstablishmentStartedCallback + sessionEstablishedCallback:(void (^_Nullable)(void))sessionEstablishedCallback + sessionEstablishmentErrorCallback:(void (^_Nullable)(MatterError * _Nonnull))sessionEstablishmentErrorCallback + sessionEstablishmentStoppedCallback:(void (^_Nullable)(void))sessionEstablishmentStoppedCallback; + +/** + * This is called when request to open the commissioning window has been made. + */ +@property void (^_Nullable commissioningWindowRequestedHandler)(bool); + +/** + * This is called when the commissioning has been completed + */ +@property void (^_Nullable commissioningCompleteCallback)(bool); + +/** + * This is called when the PBKDFParamRequest is received and indicates the start of the session establishment process + */ +@property void (^_Nullable sessionEstablishmentStartedCallback)(void); + +/** + * This is called when the commissioning session has been established + */ +@property void (^_Nullable sessionEstablishedCallback)(void); + +/** + * This is called when the PASE establishment failed (such as, when an invalid passcode is provided) or PASE was established + * fine but then the fail-safe expired (including being expired by the commissioner). The error param indicates the error that + * occurred during session establishment or the error accompanying the fail-safe timeout. + */ +@property void (^_Nullable sessionEstablishmentErrorCallback)(MatterError * _Nonnull); + +/** + * This is called when the PASE establishment failed or PASE was established fine but then the fail-safe expired (including + * being expired by the commissioner) AND the commissioning window is closed. The window may be closed because the commissioning + * attempts limit was reached or advertising/listening for PASE failed. + */ +@property void (^_Nullable sessionEstablishmentStoppedCallback)(void); + +@end + +#endif /* CommissioningCallbacksHandlers_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m new file mode 100644 index 00000000000000..c217d63156ea34 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m @@ -0,0 +1,42 @@ +/** + * + * Copyright (c) 2020-2023 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. + */ + +#import "CommissioningCallbackHandlers.h" + +@implementation CommissioningCallbackHandlers + +- (CommissioningCallbackHandlers * _Nonnull) + initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler + commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback + sessionEstablishmentStartedCallback:(void (^_Nullable)(void))sessionEstablishmentStartedCallback + sessionEstablishedCallback:(void (^_Nullable)(void))sessionEstablishedCallback + sessionEstablishmentErrorCallback:(void (^_Nullable)(MatterError * _Nonnull))sessionEstablishmentErrorCallback + sessionEstablishmentStoppedCallback:(void (^_Nullable)(void))sessionEstablishmentStoppedCallback +{ + self = [super init]; + if (self) { + _commissioningWindowRequestedHandler = commissioningWindowRequestedHandler; + _commissioningCompleteCallback = commissioningCompleteCallback; + _sessionEstablishmentStartedCallback = sessionEstablishmentStartedCallback; + _sessionEstablishedCallback = sessionEstablishedCallback; + _sessionEstablishmentErrorCallback = sessionEstablishmentErrorCallback; + _sessionEstablishmentStoppedCallback = sessionEstablishmentStoppedCallback; + } + return self; +} + +@end diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift index a0d41633a750fa..ec0c542d942e38 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift @@ -58,17 +58,32 @@ class CommissioningViewModel: ObservableObject { if let castingServerBridge = CastingServerBridge.getSharedInstance() { castingServerBridge.openBasicCommissioningWindow(DispatchQueue.main, - commissioningWindowRequestedHandler: { (result: Bool) -> () in - DispatchQueue.main.async { - self.commisisoningWindowOpened = result + commissioningCallbackHandlers: CommissioningCallbackHandlers( + commissioningWindowRequestedHandler: { (result: Bool) -> () in + DispatchQueue.main.async { + self.Log.info("Commissioning Window opening status: \(result)") + self.commisisoningWindowOpened = result + } + }, + commissioningCompleteCallback: { (result: Bool) -> () in + self.Log.info("Commissioning status: \(result)") + DispatchQueue.main.async { + self.commisisoningComplete = result + } + }, + sessionEstablishmentStartedCallback: { + self.Log.info("PASE session establishment started") + }, + sessionEstablishedCallback: { + self.Log.info("PASE session established") + }, + sessionEstablishmentErrorCallback: { (err: MatterError) -> () in + self.Log.info("PASE session establishment error : \(err)") + }, + sessionEstablishmentStoppedCallback: { + self.Log.info("PASE session establishment stopped") } - }, - commissioningCompleteCallback: { (result: Bool) -> () in - self.Log.info("Commissioning status: \(result)") - DispatchQueue.main.async { - self.commisisoningComplete = result - } - }, + ), onConnectionSuccessCallback: { (videoPlayer: VideoPlayer) -> () in DispatchQueue.main.async { self.connectionSuccess = true @@ -92,7 +107,7 @@ class CommissioningViewModel: ObservableObject { } - private func sendUserDirectedCommissioningRequest(selectedCommissioner: DiscoveredNodeData?) { + private func sendUserDirectedCommissioningRequest(selectedCommissioner: DiscoveredNodeData?) { if let castingServerBridge = CastingServerBridge.getSharedInstance() { castingServerBridge.sendUserDirectedCommissioningRequest(selectedCommissioner!, clientQueue: DispatchQueue.main, udcRequestSentHandler: { (result: Bool) -> () in