diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/ConnectionFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/ConnectionFragment.java index 2dfa712b7753c2..d2a0f7952b6485 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/ConnectionFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/ConnectionFragment.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import com.chip.casting.CommissioningCallbacks; import com.chip.casting.ContentApp; import com.chip.casting.DiscoveredNodeData; import com.chip.casting.FailureCallback; @@ -120,15 +121,59 @@ private void beginCommissioning( FailureCallback onConnectionFailure, SuccessCallback onNewOrUpdatedEndpoints) { Log.d(TAG, "Running commissioning"); + MatterCallbackHandler commissioningCompleteCallback = + new MatterCallbackHandler() { + @Override + public void handle(MatterError error) { + Log.d(TAG, "handle() called on CommissioningComplete event with " + error); + } + }; + + SuccessCallback sessionEstablishmentStartedCallback = + new SuccessCallback() { + @Override + public void handle(Void response) { + Log.d(TAG, "handle() called on SessionEstablishmentStartedCallback"); + } + }; + + SuccessCallback sessionEstablishedCallback = + new SuccessCallback() { + @Override + public void handle(Void response) { + Log.d(TAG, "handle() called on SessionEstablishedCallback"); + } + }; + + FailureCallback sessionEstablishmentErrorCallback = + new FailureCallback() { + @Override + public void handle(MatterError error) { + Log.d(TAG, "handle() called on SessionEstablishmentError event with " + error); + } + }; + + FailureCallback sessionEstablishmentStoppedCallback = + new FailureCallback() { + @Override + public void handle(MatterError error) { + Log.d(TAG, "handle() called on SessionEstablishmentStopped event with " + error); + } + }; + + CommissioningCallbacks commissioningCallbacks = + new CommissioningCallbacks.Builder() + .commissioningComplete(commissioningCompleteCallback) + .sessionEstablishmentStarted(sessionEstablishmentStartedCallback) + .sessionEstablished(sessionEstablishedCallback) + .sessionEstablishmentError(sessionEstablishmentErrorCallback) + .sessionEstablishmentStopped(sessionEstablishmentStoppedCallback) + .build(); + this.openCommissioningWindowSuccess = tvCastingApp.openBasicCommissioningWindow( GlobalCastingConstants.CommissioningWindowDurationSecs, - new MatterCallbackHandler() { - @Override - public void handle(MatterError error) { - Log.d(TAG, "handle() called on CommissioningComplete event with " + error); - } - }, + commissioningCallbacks, onConnectionSuccess, onConnectionFailure, onNewOrUpdatedEndpoints); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/CommissioningCallbacks.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/CommissioningCallbacks.java new file mode 100644 index 00000000000000..9a44aba792f18b --- /dev/null +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/CommissioningCallbacks.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023 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. + * + */ +package com.chip.casting; + +public class CommissioningCallbacks { + /** + * This is called when the PBKDFParamRequest is received and indicates the start of the session + * establishment process + */ + private SuccessCallback sessionEstablishmentStarted; + + /** This is called when the commissioning session has been established */ + private SuccessCallback sessionEstablished; + + /** + * 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. + */ + private FailureCallback sessionEstablishmentError; + + /** + * 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. + */ + private FailureCallback sessionEstablishmentStopped; + + /** This is called when the commissioning has been completed */ + private Object commissioningComplete; + + private CommissioningCallbacks(Builder builder) { + this.sessionEstablishmentStarted = builder.sessionEstablishmentStarted; + this.sessionEstablished = builder.sessionEstablished; + this.sessionEstablishmentError = builder.sessionEstablishmentError; + this.sessionEstablishmentStopped = builder.sessionEstablishmentStopped; + this.commissioningComplete = builder.commissioningComplete; + } + + public SuccessCallback getSessionEstablishmentStarted() { + return sessionEstablishmentStarted; + } + + public SuccessCallback getSessionEstablished() { + return sessionEstablished; + } + + public FailureCallback getSessionEstablishmentError() { + return sessionEstablishmentError; + } + + public FailureCallback getSessionEstablishmentStopped() { + return sessionEstablishmentStopped; + } + + public Object getCommissioningComplete() { + return commissioningComplete; + } + + public static class Builder { + private SuccessCallback sessionEstablishmentStarted; + private SuccessCallback sessionEstablished; + private FailureCallback sessionEstablishmentError; + private FailureCallback sessionEstablishmentStopped; + private Object commissioningComplete; + + public Builder sessionEstablishmentStarted(SuccessCallback sessionEstablishmentStarted) { + this.sessionEstablishmentStarted = sessionEstablishmentStarted; + return this; + } + + public Builder sessionEstablished(SuccessCallback sessionEstablished) { + this.sessionEstablished = sessionEstablished; + return this; + } + + public Builder sessionEstablishmentError(FailureCallback sessionEstablishmentError) { + this.sessionEstablishmentError = sessionEstablishmentError; + return this; + } + + public Builder sessionEstablishmentStopped(FailureCallback sessionEstablishmentStopped) { + this.sessionEstablishmentStopped = sessionEstablishmentStopped; + return this; + } + + public Builder commissioningComplete(Object commissioningComplete) { + this.commissioningComplete = commissioningComplete; + return this; + } + + public CommissioningCallbacks build() { + return new CommissioningCallbacks(this); + } + } +} diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java index 7fc9d44da14186..f30132ffc9a6ea 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java @@ -180,7 +180,7 @@ public void stopVideoPlayerDiscovery() { public native boolean openBasicCommissioningWindow( int duration, - Object commissioningCompleteHandler, + CommissioningCallbacks commissioningCallbacks, SuccessCallback onConnectionSuccess, FailureCallback onConnectionFailure, SuccessCallback onNewOrUpdatedEndpointCallback); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.h b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.h index 749f5e873ee074..c05eef016f32b3 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.h +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.h @@ -104,6 +104,30 @@ template SuccessHandlerJNI::~SuccessHandlerJNI(){}; // COMMISSIONING AND CONNECTION +class SessionEstablishmentStartedHandlerJNI : public SuccessHandlerJNI +{ +public: + SessionEstablishmentStartedHandlerJNI() : SuccessHandlerJNI("(Ljava/lang/Object;)V") {} + jobject ConvertToJObject(void * responseData) + { + // return nullptr because the Java callback extends SuccessCallback and its handle() expects a Void param. + // It expects a Void becauase no value is passed as part of this callback. + return nullptr; + } +}; + +class SessionEstablishedHandlerJNI : public SuccessHandlerJNI +{ +public: + SessionEstablishedHandlerJNI() : SuccessHandlerJNI("(Ljava/lang/Object;)V") {} + jobject ConvertToJObject(void * responseData) + { + // return nullptr because the Java callback extends SuccessCallback and its handle() expects a Void param. + // It expects a Void becauase no value is passed as part of this callback. + return nullptr; + } +}; + class OnConnectionSuccessHandlerJNI : public SuccessHandlerJNI { public: diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.cpp index c4af2c37add85c..5293cc31305fd5 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.cpp @@ -113,15 +113,82 @@ JNI_METHOD(void, setDACProvider)(JNIEnv *, jobject, jobject provider) } JNI_METHOD(jboolean, openBasicCommissioningWindow) -(JNIEnv * env, jobject, jint duration, jobject jCommissioningCompleteHandler, jobject jOnConnectionSuccessHandler, +(JNIEnv * env, jobject, jint duration, jobject jCommissioningCallbacks, jobject jOnConnectionSuccessHandler, jobject jOnConnectionFailureHandler, jobject jOnNewOrUpdatedEndpointHandler) { chip::DeviceLayer::StackLock lock; ChipLogProgress(AppServer, "JNI_METHOD openBasicCommissioningWindow called with duration %d", duration); - CHIP_ERROR err = TvCastingAppJNIMgr().getCommissioningCompleteHandler().SetUp(env, jCommissioningCompleteHandler); - VerifyOrExit(CHIP_NO_ERROR == err, - ChipLogError(AppServer, "MatterCallbackHandlerJNI::SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); + + CHIP_ERROR err = CHIP_NO_ERROR; + + CommissioningCallbacks commissioningCallbacks; + jclass jCommissioningCallbacksClass; + chip::JniReferences::GetInstance().GetClassRef(env, "com/chip/casting/CommissioningCallbacks", jCommissioningCallbacksClass); + + jfieldID jCommissioningCompleteField = + env->GetFieldID(jCommissioningCallbacksClass, "commissioningComplete", "Ljava/lang/Object;"); + jobject jCommissioningComplete = env->GetObjectField(jCommissioningCallbacks, jCommissioningCompleteField); + if (jCommissioningComplete != nullptr) + { + err = TvCastingAppJNIMgr().getCommissioningCompleteHandler().SetUp(env, jCommissioningComplete); + VerifyOrReturnValue(err == CHIP_NO_ERROR, false, + ChipLogError(AppServer, "MatterCallbackHandlerJNI::SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); + commissioningCallbacks.commissioningComplete = [](CHIP_ERROR err) { + TvCastingAppJNIMgr().getCommissioningCompleteHandler().Handle(err); + }; + } + + jfieldID jSessionEstablishmentStartedField = + env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentStarted", "Lcom/chip/casting/SuccessCallback;"); + jobject jSessionEstablishmentStarted = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentStartedField); + if (jSessionEstablishmentStarted != nullptr) + { + err = TvCastingAppJNIMgr().getSessionEstablishmentStartedHandler().SetUp(env, jSessionEstablishmentStarted); + VerifyOrReturnValue( + err == CHIP_NO_ERROR, false, + ChipLogError(AppServer, "SessionEstablishmentStartedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); + commissioningCallbacks.sessionEstablishmentStarted = []() { + TvCastingAppJNIMgr().getSessionEstablishmentStartedHandler().Handle(nullptr); + }; + } + + jfieldID jSessionEstablishedField = + env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablished", "Lcom/chip/casting/SuccessCallback;"); + jobject jSessionEstablished = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishedField); + if (jSessionEstablished != nullptr) + { + err = TvCastingAppJNIMgr().getSessionEstablishedHandler().SetUp(env, jSessionEstablished); + VerifyOrReturnValue(err == CHIP_NO_ERROR, false, + ChipLogError(AppServer, "SessionEstablishedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); + commissioningCallbacks.sessionEstablished = []() { TvCastingAppJNIMgr().getSessionEstablishedHandler().Handle(nullptr); }; + } + + jfieldID jSessionEstablishmentErrorField = + env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentError", "Lcom/chip/casting/FailureCallback;"); + jobject jSessionEstablishmentError = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentErrorField); + if (jSessionEstablishmentError != nullptr) + { + err = TvCastingAppJNIMgr().getSessionEstablishmentErrorHandler().SetUp(env, jSessionEstablishmentError); + VerifyOrReturnValue(err == CHIP_NO_ERROR, false); + commissioningCallbacks.sessionEstablishmentError = [](CHIP_ERROR err) { + TvCastingAppJNIMgr().getSessionEstablishmentErrorHandler().Handle(err); + }; + } + + jfieldID jSessionEstablishmentStoppedField = + env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentStopped", "Lcom/chip/casting/FailureCallback;"); + jobject jSessionEstablishmentStopped = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentStoppedField); + if (jSessionEstablishmentStopped != nullptr) + { + err = TvCastingAppJNIMgr().getSessionEstablishmentStoppedHandler().SetUp(env, jSessionEstablishmentStopped); + VerifyOrReturnValue( + err == CHIP_NO_ERROR, false, + ChipLogError(AppServer, "SessionEstablishmentStoppedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); + commissioningCallbacks.sessionEstablishmentStopped = []() { + TvCastingAppJNIMgr().getSessionEstablishmentStoppedHandler().Handle(CHIP_NO_ERROR); + }; + } err = TvCastingAppJNIMgr().getOnConnectionSuccessHandler(false).SetUp(env, jOnConnectionSuccessHandler); VerifyOrExit(CHIP_NO_ERROR == err, @@ -136,7 +203,7 @@ JNI_METHOD(jboolean, openBasicCommissioningWindow) ChipLogError(AppServer, "OnNewOrUpdatedEndpointHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format())); err = CastingServer::GetInstance()->OpenBasicCommissioningWindow( - [](CHIP_ERROR err) { TvCastingAppJNIMgr().getCommissioningCompleteHandler().Handle(err); }, + commissioningCallbacks, [](TargetVideoPlayerInfo * videoPlayer) { TvCastingAppJNIMgr().getOnConnectionSuccessHandler(false).Handle(videoPlayer); }, [](CHIP_ERROR err) { TvCastingAppJNIMgr().getOnConnectionFailureHandler(false).Handle(err); }, [](TargetEndpointInfo * endpoint) { TvCastingAppJNIMgr().getOnNewOrUpdatedEndpointHandler(false).Handle(endpoint); }); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.h b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.h index d77f3a7eac8cce..863e2691c44a52 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.h +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/TvCastingApp-JNI.h @@ -27,10 +27,20 @@ class TvCastingAppJNI { public: MatterCallbackHandlerJNI & getCommissioningCompleteHandler() { return mCommissioningCompleteHandler; } + + SessionEstablishmentStartedHandlerJNI & getSessionEstablishmentStartedHandler() { return mSessionEstablishmentStartedHandler; } + + SessionEstablishedHandlerJNI & getSessionEstablishedHandler() { return mSessionEstablishedHandler; } + + FailureHandlerJNI & getSessionEstablishmentErrorHandler() { return mSessionEstablishmentErrorHandler; } + + FailureHandlerJNI & getSessionEstablishmentStoppedHandler() { return mSessionEstablishmentStoppedHandler; } + OnConnectionSuccessHandlerJNI & getOnConnectionSuccessHandler(bool preCommissioned) { return preCommissioned ? mPreCommissionedOnConnectionSuccessHandler : mCommissioningOnConnectionSuccessHandler; } + FailureHandlerJNI & getOnConnectionFailureHandler(bool preCommissioned) { return preCommissioned ? mPreCommissionedOnConnectionFailureHandler : mCommissioningOnConnectionFailureHandler; @@ -100,6 +110,10 @@ class TvCastingAppJNI static TvCastingAppJNI sInstance; MatterCallbackHandlerJNI mCommissioningCompleteHandler; + SessionEstablishmentStartedHandlerJNI mSessionEstablishmentStartedHandler; + SessionEstablishedHandlerJNI mSessionEstablishedHandler; + FailureHandlerJNI mSessionEstablishmentErrorHandler; + FailureHandlerJNI mSessionEstablishmentStoppedHandler; OnConnectionSuccessHandlerJNI mCommissioningOnConnectionSuccessHandler; FailureHandlerJNI mCommissioningOnConnectionFailureHandler; OnNewOrUpdatedEndpointHandlerJNI mCommissioningOnNewOrUpdatedEndpointHandler; diff --git a/examples/tv-casting-app/android/BUILD.gn b/examples/tv-casting-app/android/BUILD.gn index 7a12b9a9a3efa3..d072dd4c088e95 100644 --- a/examples/tv-casting-app/android/BUILD.gn +++ b/examples/tv-casting-app/android/BUILD.gn @@ -65,6 +65,7 @@ android_library("java") { sources = [ "App/app/src/main/jni/com/chip/casting/AppParameters.java", + "App/app/src/main/jni/com/chip/casting/CommissioningCallbacks.java", "App/app/src/main/jni/com/chip/casting/ContentApp.java", "App/app/src/main/jni/com/chip/casting/ContentLauncherTypes.java", "App/app/src/main/jni/com/chip/casting/DACProvider.java", 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..2489f982fb0645 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,8 +110,7 @@ @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 commissioningCallbackHandlers Optional parameter to specific handlers for callbacks during commissioning @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established @@ -118,15 +118,12 @@ @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 */ - (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..3f4dbce0700bb7 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); + }); + } }]; } @@ -750,6 +818,9 @@ - (void)startMatterServer:(dispatch_queue_t _Nonnull)clientQueue return; } + // Initialize AppDelegation + CastingServer::GetInstance()->InitAppDelegation(); + // Initialize binding handlers err = CastingServer::GetInstance()->InitBindingHandlers(); if (err != CHIP_NO_ERROR) { 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..14288d7ffd6234 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h @@ -0,0 +1,70 @@ +/** + * + * Copyright (c) 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..be79d40793c4c2 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m @@ -0,0 +1,42 @@ +/** + * + * Copyright (c) 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 diff --git a/examples/tv-casting-app/linux/CastingUtils.cpp b/examples/tv-casting-app/linux/CastingUtils.cpp index 5e15a2e30e3e17..dca65f54d741b3 100644 --- a/examples/tv-casting-app/linux/CastingUtils.cpp +++ b/examples/tv-casting-app/linux/CastingUtils.cpp @@ -18,6 +18,8 @@ #include "CastingUtils.h" +#include "CommissioningCallbacks.h" + using namespace chip; using namespace chip::System; using namespace chip::DeviceLayer; @@ -62,8 +64,10 @@ void PrepareForCommissioning(const Dnssd::DiscoveredNodeData * selectedCommissio { CastingServer::GetInstance()->Init(); - CastingServer::GetInstance()->OpenBasicCommissioningWindow(HandleCommissioningCompleteCallback, OnConnectionSuccess, - OnConnectionFailure, OnNewOrUpdatedEndpoint); + CommissioningCallbacks commissioningCallbacks; + commissioningCallbacks.commissioningComplete = HandleCommissioningCompleteCallback; + CastingServer::GetInstance()->OpenBasicCommissioningWindow(commissioningCallbacks, OnConnectionSuccess, OnConnectionFailure, + OnNewOrUpdatedEndpoint); // Display onboarding payload chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig(); diff --git a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h index b24fe0fa0ec1c8..fd427afc712639 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h +++ b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h @@ -22,6 +22,7 @@ #include "ApplicationBasic.h" #include "ApplicationLauncher.h" #include "Channel.h" +#include "CommissioningCallbacks.h" #include "ContentLauncher.h" #include "KeypadInput.h" #include "LevelControl.h" @@ -33,6 +34,7 @@ #include "TargetVideoPlayerInfo.h" #include +#include #include #include #include @@ -45,7 +47,7 @@ constexpr chip::System::Clock::Seconds16 kCommissioningWindowTimeout = chip::Sys * and then have it send TV Casting/Media related commands. This is to be instantiated * as a singleton and is to be used across Linux, Android and iOS. */ -class CastingServer +class CastingServer : public AppDelegate { public: CastingServer(CastingServer & other) = delete; @@ -55,11 +57,12 @@ class CastingServer CHIP_ERROR PreInit(AppParams * AppParams = nullptr); CHIP_ERROR Init(AppParams * AppParams = nullptr); CHIP_ERROR InitBindingHandlers(); + void InitAppDelegation(); CHIP_ERROR DiscoverCommissioners(chip::Controller::DeviceDiscoveryDelegate * deviceDiscoveryDelegate = nullptr); const chip::Dnssd::DiscoveredNodeData * GetDiscoveredCommissioner(int index, chip::Optional & outAssociatedConnectableVideoPlayer); - CHIP_ERROR OpenBasicCommissioningWindow(std::function commissioningCompleteCallback, + CHIP_ERROR OpenBasicCommissioningWindow(CommissioningCallbacks commissioningCallbacks, std::function onConnectionSuccess, std::function onConnectionFailure, std::function onNewOrUpdatedEndpoint); @@ -429,6 +432,13 @@ class CastingServer static void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); void ReadServerClusters(chip::EndpointId endpointId); + void OnCommissioningSessionEstablishmentStarted() override; + void OnCommissioningSessionStarted() override; + void OnCommissioningSessionEstablishmentError(CHIP_ERROR err) override; + void OnCommissioningSessionStopped() override; + void OnCommissioningWindowOpened() override {} + void OnCommissioningWindowClosed() override {} + /** * @brief Retrieve the IP Address to use for the UDC request. * This function will look for an IPv4 address in the list of IPAddresses passed in if available and return @@ -456,7 +466,8 @@ class CastingServer chip::Inet::IPAddress mTargetVideoPlayerIpAddress[chip::Dnssd::CommonResolutionData::kMaxIPAddresses]; chip::Controller::CommissionableNodeController mCommissionableNodeController; - std::function mCommissioningCompleteCallback; + + CommissioningCallbacks mCommissioningCallbacks; std::function mOnNewOrUpdatedEndpoint; std::function mOnConnectionSuccessClientCallback; diff --git a/examples/tv-casting-app/tv-casting-common/include/CommissioningCallbacks.h b/examples/tv-casting-app/tv-casting-common/include/CommissioningCallbacks.h new file mode 100644 index 00000000000000..06d31eb2b50253 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/include/CommissioningCallbacks.h @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2023 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 + +struct CommissioningCallbacks +{ + /** + * This is called when the PBKDFParamRequest is received and indicates the start of the session establishment process + */ + std::function sessionEstablishmentStarted = {}; + + /** + * This is called when the commissioning session has been established + */ + std::function sessionEstablished = {}; + + /** + * 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 CHIP_ERROR param indicates the error that occurred during session establishment or the error accompanying the fail-safe + * timeout. + */ + std::function sessionEstablishmentError = {}; + + /** + * 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. + */ + std::function sessionEstablishmentStopped = {}; + + /** + * This is called when the commissioning has been completed + */ + std::function commissioningComplete = {}; +}; diff --git a/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h b/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h index 076149f786ed52..bbc086ae64a52d 100644 --- a/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h +++ b/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h @@ -110,7 +110,6 @@ class TargetVideoPlayerInfo static void HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) { - ChipLogProgress(AppServer, "tmplog: HandleDeviceConnected called"); VideoPlayerConnectionContext * connectionContext = static_cast(context); if (connectionContext == nullptr || connectionContext->mTargetVideoPlayerInfo == nullptr) { diff --git a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp index 313a6dc2e6a6d0..1d40cb500c287e 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -54,6 +54,9 @@ CHIP_ERROR CastingServer::Init(AppParams * AppParams) return CHIP_NO_ERROR; } + // Set CastingServer as AppDelegate + InitAppDelegation(); + // Initialize binding handlers ReturnErrorOnFailure(InitBindingHandlers()); @@ -67,6 +70,11 @@ CHIP_ERROR CastingServer::Init(AppParams * AppParams) return CHIP_NO_ERROR; } +void CastingServer::InitAppDelegation() +{ + chip::Server::Server::GetInstance().GetCommissioningWindowManager().SetAppDelegate(this); +} + CHIP_ERROR CastingServer::SetRotatingDeviceIdUniqueId(chip::Optional rotatingDeviceIdUniqueIdOptional) { #if CHIP_ENABLE_ROTATING_DEVICE_ID @@ -130,18 +138,55 @@ CHIP_ERROR CastingServer::DiscoverCommissioners(DeviceDiscoveryDelegate * device Dnssd::DiscoveryFilter(Dnssd::DiscoveryFilterType::kDeviceType, static_cast(35))); } -CHIP_ERROR CastingServer::OpenBasicCommissioningWindow(std::function commissioningCompleteCallback, +CHIP_ERROR CastingServer::OpenBasicCommissioningWindow(CommissioningCallbacks commissioningCallbacks, std::function onConnectionSuccess, std::function onConnectionFailure, std::function onNewOrUpdatedEndpoint) { - mCommissioningCompleteCallback = commissioningCompleteCallback; + mCommissioningCallbacks = commissioningCallbacks; mOnConnectionSuccessClientCallback = onConnectionSuccess; mOnConnectionFailureClientCallback = onConnectionFailure; mOnNewOrUpdatedEndpoint = onNewOrUpdatedEndpoint; return Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(kCommissioningWindowTimeout); } +void CastingServer::OnCommissioningSessionStarted() +{ + ChipLogProgress(AppServer, "CastingServer::OnCommissioningSessionStarted"); + if (mCommissioningCallbacks.sessionEstablished) + { + + mCommissioningCallbacks.sessionEstablished(); + } +} + +void CastingServer::OnCommissioningSessionEstablishmentError(CHIP_ERROR err) +{ + ChipLogProgress(AppServer, "CastingServer::OnCommissioningSessionEstablishmentError"); + if (mCommissioningCallbacks.sessionEstablishmentError) + { + mCommissioningCallbacks.sessionEstablishmentError(err); + } +} + +void CastingServer::OnCommissioningSessionStopped() +{ + ChipLogProgress(AppServer, "CastingServer::OnCommissioningSessionStopped"); + if (mCommissioningCallbacks.sessionEstablishmentStopped) + { + mCommissioningCallbacks.sessionEstablishmentStopped(); + } +} + +void CastingServer::OnCommissioningSessionEstablishmentStarted() +{ + ChipLogProgress(AppServer, "CastingServer::OnCommissioningSessionEstablishmentStarted"); + if (mCommissioningCallbacks.sessionEstablishmentStarted) + { + mCommissioningCallbacks.sessionEstablishmentStarted(); + } +} + #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT CHIP_ERROR CastingServer::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner) { @@ -433,7 +478,10 @@ void CastingServer::DeviceEventCallback(const DeviceLayer::ChipDeviceEvent * eve { ChipLogError(AppServer, "CastingServer::DeviceEventCallback accessingFabricIndex: %d did not match bindings", event->BindingsChanged.fabricIndex); - CastingServer::GetInstance()->mCommissioningCompleteCallback(CHIP_ERROR_INCORRECT_STATE); + if (CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete) + { + CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete(CHIP_ERROR_INCORRECT_STATE); + } return; } } @@ -472,7 +520,10 @@ void CastingServer::DeviceEventCallback(const DeviceLayer::ChipDeviceEvent * eve ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); } - CastingServer::GetInstance()->mCommissioningCompleteCallback(err); + if (CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete) + { + CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete(err); + } } }