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 46e945a078efc4..7bef7c1117f0b4 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 @@ -29,11 +29,13 @@ import chip.platform.NsdManagerServiceBrowser; import chip.platform.NsdManagerServiceResolver; import chip.platform.PreferencesKeyValueStoreManager; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; public class TvCastingApp { private static final String TAG = TvCastingApp.class.getSimpleName(); @@ -42,7 +44,7 @@ public class TvCastingApp { Arrays.asList(35L); // Video player = 35; // cached players that were seen before this window (in days) will not be surfaced as "discovered" - private static final long CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_DAYS = 60; + private static final long CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_DAYS = 7; // delay before which we assume remaining cached players may be in STR mode private static final long CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC = 5; @@ -50,7 +52,6 @@ public class TvCastingApp { // time assumed to be required for player to wake up after sending WoL magic packet private static final long CHIP_DEVICE_CONFIG_STR_WAKE_UP_DELAY_SEC = 10; - private ScheduledFuture reportSleepingCommissionersFuture; private static TvCastingApp sInstance; private Context applicationContext; private ChipAppServer chipAppServer; @@ -58,6 +59,8 @@ public class TvCastingApp { private boolean discoveryStarted = false; private Object discoveryLock = new Object(); + private ScheduledFuture reportSleepingCommissionersFuture; + private WifiManager.MulticastLock multicastLock; private NsdManager nsdManager; private NsdDiscoveryListener nsdDiscoveryListener; @@ -148,6 +151,7 @@ public void discoverVideoPlayerCommissioners( multicastLock.setReferenceCounted(true); multicastLock.acquire(); + List discoveredPlayers = new ArrayList<>(); nsdManager = (NsdManager) applicationContext.getSystemService(Context.NSD_SERVICE); nsdDiscoveryListener = new NsdDiscoveryListener( @@ -155,7 +159,14 @@ public void discoverVideoPlayerCommissioners( DISCOVERY_TARGET_SERVICE_TYPE, DISCOVERY_TARGET_DEVICE_TYPE_FILTER, preCommissionedVideoPlayers, - discoverySuccessCallback, + new SuccessCallback() { + @Override + public void handle(DiscoveredNodeData commissioner) { + Log.d(TAG, "Commissioner added " + commissioner); + discoveredPlayers.add(commissioner); + discoverySuccessCallback.handle(commissioner); + } + }, discoveryFailureCallback, nsdManagerResolverAvailState); @@ -174,7 +185,7 @@ public void discoverVideoPlayerCommissioners( ? preCommissionedVideoPlayers.size() : 0)); reportSleepingCommissioners( - preCommissionedVideoPlayers, discoverySuccessCallback); + preCommissionedVideoPlayers, discoveredPlayers, discoverySuccessCallback); }, CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC * 1000, TimeUnit.MILLISECONDS); @@ -185,6 +196,7 @@ public void discoverVideoPlayerCommissioners( private void reportSleepingCommissioners( List cachedVideoPlayers, + List discoveredPlayers, SuccessCallback discoverySuccessCallback) { Log.d( TAG, @@ -200,8 +212,21 @@ private void reportSleepingCommissioners( && player.getLastDiscoveredMs() > System.currentTimeMillis() - STR_CACHE_LAST_DISCOVERED_DAYS * 24 * 60 * 60 * 1000*/ ) { - player.setIsAsleep(true); - discoverySuccessCallback.handle(new DiscoveredNodeData(player)); + boolean activelyDiscovered = + discoveredPlayers + .stream() + .anyMatch( + new Predicate() { + @Override + public boolean test(DiscoveredNodeData discoveredNodeData) { + return player.getHostName().equals(discoveredNodeData.getHostName()); + } + }); + if (!activelyDiscovered) { + Log.d(TAG, "Reporting sleeping player"); + player.setIsAsleep(true); + discoverySuccessCallback.handle(new DiscoveredNodeData(player)); + } } } } @@ -249,7 +274,7 @@ public native boolean openBasicCommissioningWindow( public native List readCachedVideoPlayers(); - public boolean verifyOrEstablishConnection( + /*public boolean verifyOrEstablishConnection( VideoPlayer targetVideoPlayer, SuccessCallback onConnectionSuccess, FailureCallback onConnectionFailure, @@ -294,15 +319,15 @@ public void handle(VideoPlayer response) { } return status; } - } + }*/ - private native boolean _verifyOrEstablishConnection( + public native boolean verifyOrEstablishConnection( VideoPlayer targetVideoPlayer, SuccessCallback onConnectionSuccess, FailureCallback onConnectionFailure, SuccessCallback onNewOrUpdatedEndpointCallback); - private native boolean _sendWakeOnLan(VideoPlayer targetVideoPlayer); + // private native boolean _sendWakeOnLan(VideoPlayer targetVideoPlayer); public native void shutdownAllSubscriptions(); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java index 01d9e1580757e2..302e24ccf389ce 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java @@ -61,6 +61,7 @@ public VideoPlayer( int port, long lastDiscoveredMs, String MACAddress, + boolean isAsleep, boolean isConnected) { this.nodeId = nodeId; this.fabricIndex = fabricIndex; @@ -77,6 +78,7 @@ public VideoPlayer( this.lastDiscoveredMs = lastDiscoveredMs; this.instanceName = instanceName; this.port = port; + this.isAsleep = isAsleep; this.isInitialized = true; } 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 a98e81abe9dfaa..e05937c2812c6b 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 @@ -171,6 +171,9 @@ CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, Targe jstring jMACAddress = static_cast(env->GetObjectField(videoPlayer, getMACAddressField)); const char * MACAddress = env->GetStringUTFChars(jMACAddress, 0); + jfieldID jIsAsleep = env->GetFieldID(jVideoPlayerClass, "isAsleep", "Z"); + bool isAsleep = static_cast(env->GetLongField(videoPlayer, jIsAsleep)); + outTargetVideoPlayerInfo.Initialize(nodeId, fabricIndex, nullptr, nullptr, vendorId, productId, deviceType, deviceName, hostName, 0, nullptr, port, instanceName, chip::System::Clock::Timestamp(lastDiscoveredMs)); @@ -180,6 +183,8 @@ CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, Targe outTargetVideoPlayerInfo.SetMACAddress(MACAddressSpan); } + outTargetVideoPlayerInfo.SetIsAsleep(isAsleep); + jfieldID jContentAppsField = env->GetFieldID(jVideoPlayerClass, "contentApps", "Ljava/util/List;"); jobject jContentApps = env->GetObjectField(videoPlayer, jContentAppsField); if (jContentApps == nullptr) @@ -277,12 +282,12 @@ CHIP_ERROR convertTargetVideoPlayerInfoToJVideoPlayer(TargetVideoPlayerInfo * ta } } - outVideoPlayer = env->NewObject(jVideoPlayerClass, jVideoPlayerConstructor, targetVideoPlayerInfo->GetNodeId(), - targetVideoPlayerInfo->GetFabricIndex(), deviceName, targetVideoPlayerInfo->GetVendorId(), - targetVideoPlayerInfo->GetProductId(), targetVideoPlayerInfo->GetDeviceType(), - jContentAppList, targetVideoPlayerInfo->GetNumIPs(), jIPAddressList, hostName, instanceName, - targetVideoPlayerInfo->GetPort(), targetVideoPlayerInfo->GetLastDiscovered().count(), - MACAddress, targetVideoPlayerInfo->GetOperationalDeviceProxy() != nullptr); + outVideoPlayer = env->NewObject( + jVideoPlayerClass, jVideoPlayerConstructor, targetVideoPlayerInfo->GetNodeId(), targetVideoPlayerInfo->GetFabricIndex(), + deviceName, targetVideoPlayerInfo->GetVendorId(), targetVideoPlayerInfo->GetProductId(), + targetVideoPlayerInfo->GetDeviceType(), jContentAppList, targetVideoPlayerInfo->GetNumIPs(), jIPAddressList, hostName, + instanceName, targetVideoPlayerInfo->GetPort(), targetVideoPlayerInfo->GetLastDiscovered().count(), MACAddress, + targetVideoPlayerInfo->IsAsleep(), targetVideoPlayerInfo->GetOperationalDeviceProxy() != nullptr); } return CHIP_NO_ERROR; } 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 0af7e0c030d253..ba56ae2b3fcaa5 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 @@ -282,7 +282,7 @@ JNI_METHOD(jboolean, _1verifyOrEstablishConnection) return (err == CHIP_NO_ERROR); } -JNI_METHOD(jboolean, _1sendWakeOnLan) +/*JNI_METHOD(jboolean, _1sendWakeOnLan) (JNIEnv * env, jobject, jobject videoPlayer) { chip::DeviceLayer::StackLock lock; @@ -302,7 +302,7 @@ JNI_METHOD(jboolean, _1sendWakeOnLan) exit: return (err == CHIP_NO_ERROR); -} +}*/ JNI_METHOD(void, shutdownAllSubscriptions)(JNIEnv * env, jobject) { diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm index ed33aa1f5f57ba..9bc3e3a8ac14c7 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm @@ -750,50 +750,38 @@ - (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer [ConversionUtils convertToCppTargetVideoPlayerInfoFrom:videoPlayer outTargetVideoPlayerInfo:targetVideoPlayerInfo]; - CHIP_ERROR err = CHIP_NO_ERROR; - if (videoPlayer.isAsleep) { - ChipLogProgress(AppServer, - "verifyOrEstablishConnection(): Sending WoL to sleeping VideoPlayer and waiting"); - err = CastingServer::GetInstance()->SendWakeOnLan(targetVideoPlayerInfo); - usleep(CHIP_DEVICE_CONFIG_STR_WAKE_UP_DELAY_SEC * 1000 * 1000); - } - - if (err == CHIP_NO_ERROR) { - err = CastingServer::GetInstance()->VerifyOrEstablishConnection( - targetVideoPlayerInfo, - [clientQueue, onConnectionSuccessCallback]( - TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { - VideoPlayer * videoPlayer = - [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onConnectionSuccessCallback" - block:^{ - onConnectionSuccessCallback(videoPlayer); - }]; - }, - [clientQueue, onConnectionFailureCallback](CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onConnectionFailureCallback" - block:^{ - onConnectionFailureCallback([[MatterError alloc] - initWithCode:err.AsInteger() - message:[NSString - stringWithUTF8String:err.AsString()]]); - }]; - }, - [clientQueue, onNewOrUpdatedEndpointCallback](TargetEndpointInfo * cppTargetEndpointInfo) { - ContentApp * contentApp = - [ConversionUtils convertToObjCContentAppFrom:cppTargetEndpointInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onNewOrUpdatedEndpointCallback" - block:^{ - onNewOrUpdatedEndpointCallback(contentApp); - }]; - }); - } + CHIP_ERROR err = CastingServer::GetInstance()->VerifyOrEstablishConnection( + targetVideoPlayerInfo, + [clientQueue, onConnectionSuccessCallback](TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { + VideoPlayer * videoPlayer = + [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"onConnectionSuccessCallback" + block:^{ + onConnectionSuccessCallback(videoPlayer); + }]; + }, + [clientQueue, onConnectionFailureCallback](CHIP_ERROR err) { + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"onConnectionFailureCallback" + block:^{ + onConnectionFailureCallback([[MatterError alloc] + initWithCode:err.AsInteger() + message:[NSString stringWithUTF8String:err.AsString()]]); + }]; + }, + [clientQueue, onNewOrUpdatedEndpointCallback](TargetEndpointInfo * cppTargetEndpointInfo) { + ContentApp * contentApp = + [ConversionUtils convertToObjCContentAppFrom:cppTargetEndpointInfo]; + [[CastingServerBridge getSharedInstance] + dispatchOnClientQueue:clientQueue + description:@"onNewOrUpdatedEndpointCallback" + block:^{ + onNewOrUpdatedEndpointCallback(contentApp); + }]; + }); dispatch_async(clientQueue, ^{ requestSentHandler( diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm index 06f5b53e617953..cc57c7c3c2a224 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm @@ -91,6 +91,7 @@ + (CHIP_ERROR)convertToCppTargetVideoPlayerInfoFrom:(VideoPlayer * _Nonnull)objC outTargetVideoPlayerInfo.SetMACAddress( chip::CharSpan([objCVideoPlayer.MACAddress UTF8String], objCVideoPlayer.MACAddress.length)); } + outTargetVideoPlayerInfo.SetIsAsleep(objCVideoPlayer.isAsleep); for (ContentApp * contentApp in objCVideoPlayer.contentApps) { TargetEndpointInfo * endpoint = outTargetVideoPlayerInfo.GetOrAddEndpoint(contentApp.endpointId); @@ -198,6 +199,7 @@ + (VideoPlayer *)convertToObjCVideoPlayerFrom:(TargetVideoPlayerInfo * _Nonnull) objCVideoPlayer.MACAddress = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetMACAddress()->data() encoding:NSUTF8StringEncoding]; } + objCVideoPlayer.isAsleep = cppTargetVideoPlayerInfo->IsAsleep(); objCVideoPlayer.lastDiscoveredMs = cppTargetVideoPlayerInfo->GetLastDiscovered().count(); objCVideoPlayer.instanceName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetInstanceName() encoding:NSUTF8StringEncoding]; diff --git a/examples/tv-casting-app/linux/CastingUtils.cpp b/examples/tv-casting-app/linux/CastingUtils.cpp index dca65f54d741b3..c3c2df893fa3fa 100644 --- a/examples/tv-casting-app/linux/CastingUtils.cpp +++ b/examples/tv-casting-app/linux/CastingUtils.cpp @@ -100,7 +100,8 @@ void InitCommissioningFlow(intptr_t commandArg) CastingServer::GetInstance()->GetDiscoveredCommissioner(i, associatedConnectableVideoPlayer); if (commissioner != nullptr) { - ChipLogProgress(AppServer, "Discovered Commissioner #%d", commissionerCount++); + ChipLogProgress(AppServer, "Discovered Commissioner #%d", commissionerCount); + commissionerCount++; commissioner->LogDetail(); if (associatedConnectableVideoPlayer.HasValue()) { 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 b1db088d3770ef..56995ca61566d8 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h +++ b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h @@ -444,6 +444,8 @@ class CastingServer : public AppDelegate void OnCommissioningWindowOpened() override {} void OnCommissioningWindowClosed() override {} + CHIP_ERROR ReadMACAddress(TargetEndpointInfo * endpoint); + /** * @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 diff --git a/examples/tv-casting-app/tv-casting-common/include/ConversionUtils.h b/examples/tv-casting-app/tv-casting-common/include/ConversionUtils.h index 2cc427d1ebf6cf..76f7077d8604f7 100644 --- a/examples/tv-casting-app/tv-casting-common/include/ConversionUtils.h +++ b/examples/tv-casting-app/tv-casting-common/include/ConversionUtils.h @@ -20,4 +20,4 @@ #include -CHIP_ERROR ConvertToDiscoveredNodeData(TargetVideoPlayerInfo * player, chip::Dnssd::DiscoveredNodeData & outNodeData); \ No newline at end of file +CHIP_ERROR ConvertToDiscoveredNodeData(TargetVideoPlayerInfo * inPlayer, chip::Dnssd::DiscoveredNodeData & outNodeData); 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 fb741530c65a46..09264276e81090 100644 --- a/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h +++ b/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h @@ -92,6 +92,8 @@ class TargetVideoPlayerInfo uint16_t GetPort() const { return mPort; } const char * GetInstanceName() const { return mInstanceName; } chip::CharSpan * GetMACAddress() { return &mMACAddress; } + void SetIsAsleep(bool isAsleep) { mIsAsleep = isAsleep; } + bool IsAsleep() { return mIsAsleep; } void SetLastDiscovered(chip::System::Clock::Timestamp lastDiscovered) { mLastDiscovered = lastDiscovered; } void SetMACAddress(chip::CharSpan MACAddress) { @@ -196,5 +198,6 @@ class TargetVideoPlayerInfo chip::CharSpan mMACAddress; char mMACAddressBuf[2 * chip::DeviceLayer::ConfigurationManager::kMaxMACAddressLength]; chip::System::Clock::Timestamp mLastDiscovered; + bool mIsAsleep = false; bool mInitialized = false; }; 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 0c0255a5635799..63151f7f764ad9 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -246,90 +246,19 @@ CHIP_ERROR CastingServer::SendUserDirectedCommissioningRequest(Dnssd::Discovered const Dnssd::DiscoveredNodeData * CastingServer::GetDiscoveredCommissioner(int index, chip::Optional & outAssociatedConnectableVideoPlayer) { - // get actively discovered commissioner at 'index', if any - const Dnssd::DiscoveredNodeData * activelyDiscoveredNodeData = mCommissionableNodeController.GetDiscoveredCommissioner(index); - - // return actively discovered commissioner, if any (+ associate it to a corresponding cached video player) - if (activelyDiscoveredNodeData != nullptr) + VerifyOrReturnValue(mInited, nullptr); + const Dnssd::DiscoveredNodeData * discoveredNodeData = mCommissionableNodeController.GetDiscoveredCommissioner(index); + if (discoveredNodeData != nullptr) { for (size_t i = 0; i < kMaxCachedVideoPlayers && mCachedTargetVideoPlayerInfo[i].IsInitialized(); i++) { - if (mCachedTargetVideoPlayerInfo[i].IsSameAs(activelyDiscoveredNodeData)) + if (mCachedTargetVideoPlayerInfo[i].IsSameAs(discoveredNodeData)) { outAssociatedConnectableVideoPlayer = MakeOptional(&mCachedTargetVideoPlayerInfo[i]); - - mCachedTargetVideoPlayerInfo[i].SetLastDiscovered(System::SystemClock().GetMonotonicMilliseconds64()); - CHIP_ERROR err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer(&mCachedTargetVideoPlayerInfo[i]); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); - } - } - } - - return activelyDiscoveredNodeData; - } - else // if no actively discovered commissioner at 'index', return a cached video player that supports STR/WoL - { - chip::Dnssd::DiscoveredNodeData * strNodeData = nullptr; - // count total number of actively discoverable commissioners - int discoveredCommissionerCount; - for (discoveredCommissionerCount = 0; - mCommissionableNodeController.GetDiscoveredCommissioner(discoveredCommissionerCount) != nullptr; - discoveredCommissionerCount++) - ; - - // counter used to determine which video player to return from the list of cached video players - int targetSTRVideoPlayerCounter = index - discoveredCommissionerCount; - if (targetSTRVideoPlayerCounter < 0) // cannot be less than 0 - { - ChipLogError(AppServer, "CastingServer::GetDiscoveredCommissioner encountered invalid targetSTRVideoPlayerCounter %d", - targetSTRVideoPlayerCounter); - return nullptr; - } - strNodeData = &mStrNodeDataList[targetSTRVideoPlayerCounter]; - - // search/loop through all the cached video players - for (size_t i = 0; i < kMaxCachedVideoPlayers && mCachedTargetVideoPlayerInfo[i].IsInitialized(); i++) - { - // search/loop through all actively discovered commissioners so we can skip mCachedTargetVideoPlayerInfo[i] if it is the - // same as an actively discovered commissioner - const Dnssd::DiscoveredNodeData * discoveredNodeData = nullptr; - for (int j = 0; j < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; j++) - { - discoveredNodeData = mCommissionableNodeController.GetDiscoveredCommissioner(j); - if (discoveredNodeData != nullptr && discoveredNodeData->resolutionData.IsValid()) - { - // consider a cached video player only if it was NOT in the list of actively discoverable commissioners - if (!mCachedTargetVideoPlayerInfo[i].IsSameAs(discoveredNodeData)) - { - // if this cached video player supports STR/WoL and was discoverable recently, convert it to a - // DiscoveredNodeData object and break out of the loop - if (mCachedTargetVideoPlayerInfo[i].GetMACAddress() != nullptr && - mCachedTargetVideoPlayerInfo[i].GetMACAddress()->size() > 0 -#ifdef CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_DAYS - && mCachedTargetVideoPlayerInfo[i].GetLastDiscovered().count() > - (System::SystemClock().GetMonotonicMilliseconds64().count() - - CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_DAYS * 24 * 60 * 60 * 1000) -#endif - ) - { - // ensure we are returning the cached video player at the correct index - if (targetSTRVideoPlayerCounter-- == 0) - { - if (ConvertToDiscoveredNodeData(&mCachedTargetVideoPlayerInfo[i], *strNodeData) == CHIP_NO_ERROR) - { - return nullptr; - } - } - break; - } - } - } } } - return strNodeData; } + return discoveredNodeData; } CHIP_ERROR CastingServer::SendWakeOnLan(TargetVideoPlayerInfo & targetVideoPlayerInfo) @@ -395,6 +324,40 @@ void CastingServer::ReadServerClusters(EndpointId endpointId) ChipLogProgress(Controller, "Sent descriptor read for remote endpoint=%d", endpointId); } +CHIP_ERROR CastingServer::ReadMACAddress(TargetEndpointInfo * endpoint) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + if (endpoint != nullptr && endpoint->HasCluster(chip::app::Clusters::WakeOnLan::Id)) + { + // Read MAC address + ChipLogProgress(AppServer, "Endpoint supports WoL. Reading Active VideoPlayer's MACAddress"); + mMACAddressReader.SetTarget(mActiveTargetVideoPlayerInfo, endpoint->GetEndpointId()); + err = mMACAddressReader.ReadAttribute( + &mActiveTargetVideoPlayerInfo, + [](void * context, const chip::app::Clusters::WakeOnLan::Attributes::MACAddress::TypeInfo::DecodableArgType response) { + ChipLogProgress(AppServer, "Read MACAddress successfully"); + TargetVideoPlayerInfo * videoPlayerInfo = static_cast(context); + if (response.data() != nullptr && response.size() > 0) + { + videoPlayerInfo->SetMACAddress(response); + ChipLogProgress(AppServer, "Updating cache of VideoPlayers with MACAddress: %.*s", + static_cast(response.size()), response.data()); + CHIP_ERROR err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer(videoPlayerInfo); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); + } + } + }, + [](void * context, CHIP_ERROR error) { ChipLogError(AppServer, "Failed to read MACAddress"); }); + } + else + { + err = CHIP_ERROR_INVALID_ARGUMENT; + } + return err; +} + void CastingServer::OnDescriptorReadSuccessResponse(void * context, const app::DataModel::DecodableList & responseList) { TargetEndpointInfo * endpointInfo = static_cast(context); @@ -417,31 +380,8 @@ void CastingServer::OnDescriptorReadSuccessResponse(void * context, const app::D ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); } - if (endpointInfo->HasCluster(chip::app::Clusters::WakeOnLan::Id)) - { - // Read MAC address - ChipLogProgress(AppServer, "Endpoint supports WoL. Reading VideoPlayer's MACAddress"); - CastingServer::GetInstance()->mMACAddressReader.SetTarget(CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo, - endpointInfo->GetEndpointId()); - CastingServer::GetInstance()->mMACAddressReader.ReadAttribute( - &CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo, - [](void * context, const chip::app::Clusters::WakeOnLan::Attributes::MACAddress::TypeInfo::DecodableArgType response) { - ChipLogProgress(AppServer, "Read MACAddress successfully"); - TargetVideoPlayerInfo * videoPlayerInfo = static_cast(context); - if (response.data() != nullptr && response.size() > 0) - { - videoPlayerInfo->SetMACAddress(response); - ChipLogProgress(AppServer, "Updating cache of VideoPlayers with MACAddress: %.*s", - static_cast(response.size()), response.data()); - CHIP_ERROR err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer(videoPlayerInfo); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); - } - } - }, - [](void * context, CHIP_ERROR error) { ChipLogError(AppServer, "Failed to read MACAddress"); }); - } + // Read WoL:MACAddress (if available from this endpoint) + CastingServer::GetInstance()->ReadMACAddress(endpointInfo); if (CastingServer::GetInstance()->mOnNewOrUpdatedEndpoint) { @@ -510,52 +450,21 @@ CHIP_ERROR CastingServer::VerifyOrEstablishConnection(TargetVideoPlayerInfo & ta prevDeviceProxy->Disconnect(); } + if (targetVideoPlayerInfo.IsAsleep()) + { + ChipLogProgress(AppServer, "CastingServer::VerifyOrEstablishConnection(): Sending WoL to sleeping VideoPlayer and waiting"); + ReturnErrorOnFailure(CastingServer::GetInstance()->SendWakeOnLan(targetVideoPlayerInfo)); + usleep(CHIP_DEVICE_CONFIG_STR_WAKE_UP_DELAY_SEC * 1000 * 1000); + } + CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo = targetVideoPlayerInfo; return CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo.FindOrEstablishCASESession( [](TargetVideoPlayerInfo * videoPlayer) { ChipLogProgress(AppServer, "CastingServer::OnConnectionSuccess lambda called"); CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo = *videoPlayer; - - // Read cached VideoPlayer endpoint (1) and check if it supports WoL - TargetEndpointInfo * endpoint = videoPlayer->GetEndpoint(1); - if (endpoint != nullptr && endpoint->HasCluster(chip::app::Clusters::WakeOnLan::Id)) - { - ChipLogProgress(AppServer, "Endpoint supports WoL. Reading VideoPlayer's MACAddress"); - - // Read MAC address - CastingServer::GetInstance()->mMACAddressReader.SetTarget(*videoPlayer, endpoint->GetEndpointId()); - CastingServer::GetInstance()->mMACAddressReader.ReadAttribute( - videoPlayer, - [](void * context, - const chip::app::Clusters::WakeOnLan::Attributes::MACAddress::TypeInfo::DecodableArgType response) { - ChipLogProgress(AppServer, "Read MACAddress successfully"); - TargetVideoPlayerInfo * videoPlayerInfo = static_cast(context); - if (response.data() != nullptr && response.size() > 0) - { - videoPlayerInfo->SetMACAddress(response); - ChipLogProgress(AppServer, "Updating cache of VideoPlayers with MACAddress: %.*s", - static_cast(response.size()), response.data()); - CHIP_ERROR err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer(videoPlayerInfo); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); - } - } - - CastingServer::GetInstance()->mOnConnectionSuccessClientCallback( - static_cast(context)); - }, - [](void * context, CHIP_ERROR error) { - ChipLogError(AppServer, "Failed to read MACAddress"); - CastingServer::GetInstance()->mOnConnectionSuccessClientCallback( - static_cast(context)); - }); - } - else - { - ChipLogProgress(AppServer, "TargetVideoPlayer does not support WoL"); - CastingServer::GetInstance()->mOnConnectionSuccessClientCallback(videoPlayer); - } + CastingServer::GetInstance()->ReadMACAddress( + videoPlayer->GetEndpoint(1)); // Read MACAddress from cached VideoPlayer endpoint (1) which supports WoL + CastingServer::GetInstance()->mOnConnectionSuccessClientCallback(videoPlayer); }, [onConnectionFailure](CHIP_ERROR err) { ChipLogProgress(AppServer, "Deleting VideoPlayer from cache after connection failure: %" CHIP_ERROR_FORMAT, diff --git a/examples/tv-casting-app/tv-casting-common/src/ConversionUtils.cpp b/examples/tv-casting-app/tv-casting-common/src/ConversionUtils.cpp index ebb3597107b590..322e9d46bec8c4 100644 --- a/examples/tv-casting-app/tv-casting-common/src/ConversionUtils.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/ConversionUtils.cpp @@ -18,17 +18,17 @@ #include "ConversionUtils.h" -CHIP_ERROR ConvertToDiscoveredNodeData(TargetVideoPlayerInfo * player, chip::Dnssd::DiscoveredNodeData & outNodeData) +CHIP_ERROR ConvertToDiscoveredNodeData(TargetVideoPlayerInfo * inPlayer, chip::Dnssd::DiscoveredNodeData & outNodeData) { - if (player == nullptr) + if (inPlayer == nullptr) return CHIP_ERROR_INVALID_ARGUMENT; - outNodeData.commissionData.vendorId = player->GetVendorId(); - outNodeData.commissionData.productId = static_cast(player->GetProductId()); - outNodeData.commissionData.deviceType = player->GetDeviceType(); - outNodeData.resolutionData.numIPs = player->GetNumIPs(); + outNodeData.commissionData.vendorId = inPlayer->GetVendorId(); + outNodeData.commissionData.productId = static_cast(inPlayer->GetProductId()); + outNodeData.commissionData.deviceType = inPlayer->GetDeviceType(); + outNodeData.resolutionData.numIPs = inPlayer->GetNumIPs(); - const chip::Inet::IPAddress * ipAddresses = player->GetIpAddresses(); + const chip::Inet::IPAddress * ipAddresses = inPlayer->GetIpAddresses(); if (ipAddresses != nullptr) { for (size_t i = 0; i < outNodeData.resolutionData.numIPs && i < chip::Dnssd::CommonResolutionData::kMaxIPAddresses; i++) @@ -37,8 +37,9 @@ CHIP_ERROR ConvertToDiscoveredNodeData(TargetVideoPlayerInfo * player, chip::Dns } } - chip::Platform::CopyString(outNodeData.commissionData.deviceName, chip::Dnssd::kMaxDeviceNameLen + 1, player->GetDeviceName()); - chip::Platform::CopyString(outNodeData.resolutionData.hostName, chip::Dnssd::kHostNameMaxLength + 1, player->GetHostName()); + chip::Platform::CopyString(outNodeData.commissionData.deviceName, chip::Dnssd::kMaxDeviceNameLen + 1, + inPlayer->GetDeviceName()); + chip::Platform::CopyString(outNodeData.resolutionData.hostName, chip::Dnssd::kHostNameMaxLength + 1, inPlayer->GetHostName()); return CHIP_NO_ERROR; -} \ No newline at end of file +} diff --git a/examples/tv-casting-app/tv-casting-common/src/WakeOnLan.cpp b/examples/tv-casting-app/tv-casting-common/src/WakeOnLan.cpp index b6734f5108e282..cf44c413a70c03 100644 --- a/examples/tv-casting-app/tv-casting-common/src/WakeOnLan.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/WakeOnLan.cpp @@ -81,4 +81,4 @@ CHIP_ERROR SendWakeOnLanPacket(chip::CharSpan * MACAddress) close(sockfd); return CHIP_NO_ERROR; -} \ No newline at end of file +}