diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/CertTestFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/CertTestFragment.java index 7540c3a3f8b6c1..16070eb1dfe59e 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/CertTestFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/CertTestFragment.java @@ -81,8 +81,12 @@ public void onClick(View v) { private void runCertTests(Activity activity) { CertTestMatterSuccessFailureCallback successFailureCallback = new CertTestMatterSuccessFailureCallback(activity); - CertTestMatterSuccessFailureCallbackInteger successFailureCallbackInteger = - new CertTestMatterSuccessFailureCallbackInteger(successFailureCallback); + CertTestMatterSuccessCallback successCallback = + new CertTestMatterSuccessCallback(successFailureCallback); + CertTestMatterFailureCallback failureCallback = + new CertTestMatterFailureCallback(successFailureCallback); + CertTestMatterSuccessCallbackInteger successCallbackInteger = + new CertTestMatterSuccessCallbackInteger(successFailureCallback); CertTestMatterCallbackHandler callback = new CertTestMatterCallbackHandler(successFailureCallback); @@ -269,7 +273,7 @@ private void runCertTests(Activity activity) { successFailureCallback, () -> { tvCastingApp.applicationBasic_readApplicationVersion( - kContentApp, successFailureCallback, successFailureCallback); + kContentApp, successCallback, failureCallback); }); runAndWait( @@ -277,7 +281,7 @@ private void runCertTests(Activity activity) { successFailureCallback, () -> { tvCastingApp.applicationBasic_readVendorName( - kContentApp, successFailureCallback, successFailureCallback); + kContentApp, successCallback, failureCallback); }); runAndWait( @@ -285,7 +289,7 @@ private void runCertTests(Activity activity) { successFailureCallback, () -> { tvCastingApp.applicationBasic_readApplicationName( - kContentApp, successFailureCallback, successFailureCallback); + kContentApp, successCallback, failureCallback); }); runAndWait( @@ -293,7 +297,7 @@ private void runCertTests(Activity activity) { successFailureCallback, () -> { tvCastingApp.applicationBasic_readVendorID( - kContentApp, successFailureCallbackInteger, successFailureCallbackInteger); + kContentApp, successCallbackInteger, failureCallback); }); runAndWait( @@ -301,7 +305,7 @@ private void runCertTests(Activity activity) { successFailureCallback, () -> { tvCastingApp.applicationBasic_readProductID( - kContentApp, successFailureCallbackInteger, successFailureCallbackInteger); + kContentApp, successCallbackInteger, failureCallback); }); runAndWait( @@ -320,7 +324,7 @@ public void handle(MediaPlaybackTypes.PlaybackStateEnum response) { activity, MatterError.NO_ERROR, "mediaPlayback_subscribeToCurrentState"); } }, - successFailureCallback, + failureCallback, 0, 20, new SubscriptionEstablishedCallback() { @@ -415,8 +419,7 @@ public void handle(MatterError error) { } } - class CertTestMatterSuccessFailureCallback extends FailureCallback - implements SuccessCallback { + class CertTestMatterSuccessFailureCallback { private Activity activity; private String testMethod; private CountDownLatch cdl; @@ -433,7 +436,6 @@ public void setCountDownLatch(CountDownLatch cdl) { this.cdl = cdl; } - @Override public void handle(MatterError error) { try { cdl.countDown(); @@ -446,7 +448,6 @@ public void handle(MatterError error) { } } - @Override public void handle(String response) { try { cdl.countDown(); @@ -460,18 +461,38 @@ public void handle(String response) { } } - class CertTestMatterSuccessFailureCallbackInteger extends FailureCallback - implements SuccessCallback { + class CertTestMatterSuccessCallback extends SuccessCallback { + private CertTestMatterSuccessFailureCallback delegate; + + CertTestMatterSuccessCallback(CertTestMatterSuccessFailureCallback delegate) { + this.delegate = delegate; + } + + @Override + public void handle(String response) { + delegate.handle(response); + } + } + class CertTestMatterFailureCallback extends FailureCallback { private CertTestMatterSuccessFailureCallback delegate; - CertTestMatterSuccessFailureCallbackInteger(CertTestMatterSuccessFailureCallback delegate) { + CertTestMatterFailureCallback(CertTestMatterSuccessFailureCallback delegate) { this.delegate = delegate; } @Override - public void handle(MatterError error) { - delegate.handle(error); + public void handle(MatterError err) { + delegate.handle(err); + } + } + + class CertTestMatterSuccessCallbackInteger extends SuccessCallback { + + private CertTestMatterSuccessFailureCallback delegate; + + CertTestMatterSuccessCallbackInteger(CertTestMatterSuccessFailureCallback delegate) { + this.delegate = delegate; } @Override diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MediaPlaybackFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MediaPlaybackFragment.java index 7e9070665b74b4..325b33e85b79f4 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MediaPlaybackFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MediaPlaybackFragment.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import com.chip.casting.ContentApp; import com.chip.casting.FailureCallback; import com.chip.casting.MatterError; @@ -63,13 +64,16 @@ public void onClick(View v) { TextView currentStateValue = getView().findViewById(R.id.currentStateValue); SuccessCallback successCallback = - playbackStateEnum -> { - Log.d( - TAG, - "handle() called on SuccessCallback with " - + playbackStateEnum); - getActivity() - .runOnUiThread( + new SuccessCallback() { + @Override + public void handle(MediaPlaybackTypes.PlaybackStateEnum playbackStateEnum) { + Log.d( + TAG, + "handle() called on SuccessCallback with " + + playbackStateEnum); + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.runOnUiThread( new Runnable() { @Override public void run() { @@ -78,6 +82,8 @@ public void run() { } } }); + } + } }; FailureCallback failureCallback = @@ -97,18 +103,22 @@ public void run() { }; SubscriptionEstablishedCallback subscriptionEstablishedCallback = - (SubscriptionEstablishedCallback) - () -> { - Log.d(TAG, "handle() called on SubscriptionEstablishedCallback"); - getActivity() - .runOnUiThread( - new Runnable() { - @Override - public void run() { - subscriptionStatus.setText("Subscription established!"); - } - }); - }; + new SubscriptionEstablishedCallback() { + @Override + public void handle() { + Log.d(TAG, "handle() called on SubscriptionEstablishedCallback"); + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.runOnUiThread( + new Runnable() { + @Override + public void run() { + subscriptionStatus.setText("Subscription established!"); + } + }); + } + } + }; boolean retVal = tvCastingApp.mediaPlayback_subscribeToCurrentState( diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/FailureCallback.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/FailureCallback.java index 1d6b4097e77cbc..698d091ca06896 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/FailureCallback.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/FailureCallback.java @@ -17,10 +17,18 @@ */ package com.chip.casting; +import android.util.Log; + public abstract class FailureCallback { + private static final String TAG = FailureCallback.class.getSimpleName(); + public abstract void handle(MatterError err); - public final void handle(int errorCode, String errorMessage) { - handle(new MatterError(errorCode, errorMessage)); + private final void handleInternal(int errorCode, String errorMessage) { + try { + handle(new MatterError(errorCode, errorMessage)); + } catch (Throwable t) { + Log.e(TAG, "FailureCallback::Caught an unhandled Throwable from the client: " + t); + } } } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/MatterCallbackHandler.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/MatterCallbackHandler.java index a06f12248883db..8eb3d2c4f1318e 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/MatterCallbackHandler.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/MatterCallbackHandler.java @@ -17,10 +17,18 @@ */ package com.chip.casting; +import android.util.Log; + public abstract class MatterCallbackHandler { + private static final String TAG = MatterCallbackHandler.class.getSimpleName(); + public abstract void handle(MatterError err); - public final void handle(int errorCode, String errorMessage) { - handle(new MatterError(errorCode, errorMessage)); + private final void handleInternal(int errorCode, String errorMessage) { + try { + handle(new MatterError(errorCode, errorMessage)); + } catch (Throwable t) { + Log.e(TAG, "MatterCallbackHandler::Caught an unhandled Throwable from the client: " + t); + } } } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SubscriptionEstablishedCallback.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SubscriptionEstablishedCallback.java index e182c80e7ccdef..6bac295871e18c 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SubscriptionEstablishedCallback.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SubscriptionEstablishedCallback.java @@ -17,6 +17,20 @@ */ package com.chip.casting; -public interface SubscriptionEstablishedCallback { - void handle(); +import android.util.Log; + +public abstract class SubscriptionEstablishedCallback { + private static final String TAG = SubscriptionEstablishedCallback.class.getSimpleName(); + + public abstract void handle(); + + private void handleInternal() { + try { + handle(); + } catch (Throwable t) { + Log.e( + TAG, + "SubscriptionEstablishedCallback::Caught an unhandled Throwable from the client: " + t); + } + } } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SuccessCallback.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SuccessCallback.java index 125ce4daabfc90..8f10aa72cce16e 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SuccessCallback.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SuccessCallback.java @@ -17,6 +17,18 @@ */ package com.chip.casting; -public interface SuccessCallback { - void handle(R response); +import android.util.Log; + +public abstract class SuccessCallback { + private static final String TAG = SuccessCallback.class.getSimpleName(); + + public abstract void handle(R response); + + public void handleInternal(R response) { + try { + handle(response); + } catch (Throwable t) { + Log.e(TAG, "SuccessCallback::Caught an unhandled Throwable from the client: " + t); + } + } } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp index cff8ddd8ba9677..3b5832af055963 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp @@ -61,6 +61,7 @@ CHIP_ERROR convertJAppParametersToCppAppParams(jobject appParameters, AppParams CHIP_ERROR convertJContentAppToTargetEndpointInfo(jobject contentApp, TargetEndpointInfo & outTargetEndpointInfo) { ChipLogProgress(AppServer, "convertJContentAppToTargetEndpointInfo called"); + VerifyOrReturnError(contentApp != nullptr, CHIP_ERROR_INVALID_ARGUMENT); JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); jclass jContentAppClass; @@ -124,6 +125,7 @@ CHIP_ERROR convertTargetEndpointInfoToJContentApp(TargetEndpointInfo * targetEnd CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, TargetVideoPlayerInfo & outTargetVideoPlayerInfo) { ChipLogProgress(AppServer, "convertJVideoPlayerToTargetVideoPlayerInfo called"); + VerifyOrReturnError(videoPlayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); jclass jVideoPlayerClass; @@ -241,6 +243,7 @@ CHIP_ERROR convertJDiscoveredNodeDataToCppDiscoveredNodeData(jobject jDiscovered chip::Dnssd::DiscoveredNodeData & outCppDiscoveredNodeData) { ChipLogProgress(AppServer, "convertJDiscoveredNodeDataToCppDiscoveredNodeData called"); + VerifyOrReturnError(jDiscoveredNodeData != nullptr, CHIP_ERROR_INVALID_ARGUMENT); JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.cpp index eb19010ea33853..0c841c4f19039f 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.cpp @@ -31,10 +31,10 @@ CHIP_ERROR CallbackBaseJNI::SetUp(JNIEnv * env, jobject inHandler) mClazz = env->GetObjectClass(mObject); VerifyOrExit(mClazz != nullptr, ChipLogError(AppServer, "Failed to get handler Java class")); - mMethod = env->GetMethodID(mClazz, "handle", mMethodSignature); + mMethod = env->GetMethodID(mClazz, "handleInternal", mMethodSignature); if (mMethod == nullptr) { - ChipLogError(AppServer, "Failed to access 'handle' method with signature %s", mMethodSignature); + ChipLogError(AppServer, "Failed to access 'handleInternal' method with signature %s", mMethodSignature); env->ExceptionClear(); } 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 ae049529c753e9..8672a747f4442d 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB873C286A593700771BAD /* ConversionUtils.hpp */; }; 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 */; }; 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 */ @@ -60,6 +61,7 @@ 3CCB873C286A593700771BAD /* ConversionUtils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ConversionUtils.hpp; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -128,6 +130,7 @@ 3C26AC8F2927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm */, 3C0D9CDF2920A30C00D3332B /* CommissionableDataProviderImpl.hpp */, 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */, + 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */, ); path = MatterTvCastingBridge; sourceTree = ""; @@ -139,6 +142,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */, 3C26AC8C2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp in Headers */, 3CCB8740286A593700771BAD /* CastingServerBridge.h in Headers */, 3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */, diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h index b306e39072d617..0a8fa240e6e1c1 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h @@ -45,7 +45,8 @@ @param discoveryRequestSentHandler Handler to call after the Commissioner discovery request has been sent */ - (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue - discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler; + discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler; /*! @brief Retrieve a discovered commissioner TV diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm index 9d37390b084023..3b9204cdaf5436 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm @@ -19,6 +19,7 @@ #import "CastingServer.h" #import "CommissionableDataProviderImpl.hpp" +#import "CommissionerDiscoveryDelegateImpl.h" #import "ConversionUtils.hpp" #import "DeviceAttestationCredentialsProviderImpl.hpp" #import "MatterCallbacks.h" @@ -44,6 +45,8 @@ @interface CastingServerBridge () @property chip::CommonCaseDeviceServerInitParams * serverInitParams; +@property CommissionerDiscoveryDelegateImpl * commissionerDiscoveryDelegate; + @property TargetVideoPlayerInfo * previouslyConnectedVideoPlayer; // queue used to serialize all work performed by the CastingServerBridge @@ -98,6 +101,8 @@ - (instancetype)init return nil; } + _commissionerDiscoveryDelegate = new CommissionerDiscoveryDelegateImpl(); + _commandResponseCallbacks = [NSMutableDictionary dictionary]; _subscriptionEstablishedCallbacks = [NSMutableDictionary dictionary]; _subscriptionReadSuccessCallbacks = [NSMutableDictionary dictionary]; @@ -268,12 +273,19 @@ - (MatterError *)initializeApp:(AppParameters * _Nullable)appParameters } - (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue - discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler + discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData *))discoveredCommissionerHandler { ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() called"); dispatch_async(_chipWorkQueue, ^{ bool discoveryRequestStatus = true; - CHIP_ERROR err = CastingServer::GetInstance()->DiscoverCommissioners(); + + if (discoveredCommissionerHandler != nil) { + TargetVideoPlayerInfo * cachedTargetVideoPlayerInfos = CastingServer::GetInstance()->ReadCachedTargetVideoPlayerInfos(); + self->_commissionerDiscoveryDelegate->SetUp(clientQueue, discoveredCommissionerHandler, cachedTargetVideoPlayerInfos); + } + CHIP_ERROR err = CastingServer::GetInstance()->DiscoverCommissioners( + discoveredCommissionerHandler != nil ? self->_commissionerDiscoveryDelegate : nullptr); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() failed: %" CHIP_ERROR_FORMAT, err.Format()); discoveryRequestStatus = false; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h new file mode 100644 index 00000000000000..56ac24526d831c --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#ifndef CommissionerDiscoveryDelegateImpl_h +#define CommissionerDiscoveryDelegateImpl_h + +#import "ConversionUtils.hpp" +#include + +class CommissionerDiscoveryDelegateImpl : public chip::Controller::DeviceDiscoveryDelegate { +public: + void SetUp(dispatch_queue_t _Nonnull clientQueue, + void (^_Nonnull objCDiscoveredCommissionerHandler)(DiscoveredNodeData * _Nonnull), + TargetVideoPlayerInfo * cachedTargetVideoPlayerInfos) + { + mClientQueue = clientQueue; + mObjCDiscoveredCommissionerHandler = objCDiscoveredCommissionerHandler; + mCachedTargetVideoPlayerInfos = cachedTargetVideoPlayerInfos; + } + + void OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & nodeData) + { + ChipLogProgress(AppServer, "CommissionerDiscoveryDelegateImpl().OnDiscoveredDevice() called"); + __block const chip::Dnssd::DiscoveredNodeData cppNodeData = nodeData; + dispatch_async(mClientQueue, ^{ + DiscoveredNodeData * objCDiscoveredNodeData = [ConversionUtils convertToObjCDiscoveredNodeDataFrom:&cppNodeData]; + + // set associated connectable video player from cache, if any + if (mCachedTargetVideoPlayerInfos != nullptr) { + for (size_t i = 0; i < kMaxCachedVideoPlayers && mCachedTargetVideoPlayerInfos[i].IsInitialized(); i++) { + if (mCachedTargetVideoPlayerInfos[i].IsSameAs(&cppNodeData)) { + VideoPlayer * connectableVideoPlayer = + [ConversionUtils convertToObjCVideoPlayerFrom:&mCachedTargetVideoPlayerInfos[i]]; + [objCDiscoveredNodeData setConnectableVideoPlayer:connectableVideoPlayer]; + } + } + } + + // make the callback + mObjCDiscoveredCommissionerHandler(objCDiscoveredNodeData); + }); + } + +private: + void (^_Nonnull mObjCDiscoveredCommissionerHandler)(DiscoveredNodeData * _Nonnull); + dispatch_queue_t _Nonnull mClientQueue; + TargetVideoPlayerInfo * mCachedTargetVideoPlayerInfos; +}; + +#endif /* CommissionerDiscoveryDelegateImpl_h */ diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift index 5defa202520d7a..4438759922949f 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift @@ -29,15 +29,33 @@ class CommissionerDiscoveryViewModel: ObservableObject { func discoverAndUpdate() { if let castingServerBridge = CastingServerBridge.getSharedInstance() { - castingServerBridge.discoverCommissioners(DispatchQueue.main, discoveryRequestSentHandler: { (result: Bool) -> () in - self.discoveryRequestStatus = result - }) + castingServerBridge.discoverCommissioners(DispatchQueue.main, + discoveryRequestSentHandler: { (result: Bool) -> () in + self.discoveryRequestStatus = result + }, + discoveredCommissionerHandler: { (commissioner: DiscoveredNodeData) -> () in + self.Log.info("discoveredCommissionerHandler called with \(commissioner)") + if(self.commissioners.contains(commissioner)) + { + self.Log.info("Skipping previously discovered commissioner \(commissioner.description)") + } + else if(commissioner.numIPs == 0) + { + self.Log.info("Skipping commissioner because it does not have any resolved IP addresses \(commissioner.description)") + } + else + { + self.commissioners.append(commissioner) + } + } + ) } - Task { + /* Deprecated usage + Task { try? await Task.sleep(nanoseconds: 5_000_000_000) // Wait for commissioners to respond updateCommissioners() - } + }*/ } private func updateCommissioners() { 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 205978e1788cf4..f67b4d9df93456 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h +++ b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h @@ -57,7 +57,7 @@ class CastingServer CHIP_ERROR Init(AppParams * AppParams = nullptr); CHIP_ERROR InitBindingHandlers(); - CHIP_ERROR DiscoverCommissioners(); + CHIP_ERROR DiscoverCommissioners(chip::Controller::DeviceDiscoveryDelegate * deviceDiscoveryDelegate = nullptr); const chip::Dnssd::DiscoveredNodeData * GetDiscoveredCommissioner(int index, chip::Optional & outAssociatedConnectableVideoPlayer); CHIP_ERROR OpenBasicCommissioningWindow(std::function commissioningCompleteCallback, 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 2c7a34e92795f5..56c6845eb5bbf7 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -112,7 +112,7 @@ CHIP_ERROR CastingServer::TargetVideoPlayerInfoInit(NodeId nodeId, FabricIndex f mOnConnectionFailureClientCallback); } -CHIP_ERROR CastingServer::DiscoverCommissioners() +CHIP_ERROR CastingServer::DiscoverCommissioners(DeviceDiscoveryDelegate * deviceDiscoveryDelegate) { TargetVideoPlayerInfo * connectableVideoPlayerList = ReadCachedTargetVideoPlayerInfos(); if (connectableVideoPlayerList == nullptr || !connectableVideoPlayerList[0].IsInitialized()) @@ -120,6 +120,8 @@ CHIP_ERROR CastingServer::DiscoverCommissioners() ChipLogProgress(AppServer, "No cached video players found during discovery"); } + mCommissionableNodeController.RegisterDeviceDiscoveryDelegate(deviceDiscoveryDelegate); + // Send discover commissioners request return mCommissionableNodeController.DiscoverCommissioners( Dnssd::DiscoveryFilter(Dnssd::DiscoveryFilterType::kDeviceType, static_cast(35))); diff --git a/src/controller/CHIPCommissionableNodeController.h b/src/controller/CHIPCommissionableNodeController.h index f6bf2532b53b09..a31e14309af367 100644 --- a/src/controller/CHIPCommissionableNodeController.h +++ b/src/controller/CHIPCommissionableNodeController.h @@ -39,6 +39,7 @@ class DLL_EXPORT CommissionableNodeController : public AbstractDnssdDiscoveryCon CommissionableNodeController(chip::Dnssd::Resolver * resolver = nullptr) : mResolver(resolver) {} ~CommissionableNodeController() override; + void RegisterDeviceDiscoveryDelegate(DeviceDiscoveryDelegate * delegate) { mDeviceDiscoveryDelegate = delegate; } CHIP_ERROR DiscoverCommissioners(Dnssd::DiscoveryFilter discoveryFilter = Dnssd::DiscoveryFilter()); /**