diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingApp-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingApp-JNI.cpp index 984287af8c30fd..90a36bbfec92ca 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingApp-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingApp-JNI.cpp @@ -21,7 +21,10 @@ #include "../JNIDACProvider.h" #include "../support/ErrorConverter-JNI.h" #include "../support/RotatingDeviceIdUniqueIdProvider-JNI.h" -#include "core/CastingApp.h" // from tv-casting-common + +// from tv-casting-common +#include "core/CastingApp.h" +#include "support/ChipDeviceEventHandler.h" #include #include @@ -79,20 +82,25 @@ JNI_METHOD(jobject, finishStartup)(JNIEnv *, jobject) { chip::DeviceLayer::StackLock lock; ChipLogProgress(AppServer, "JNI_METHOD CastingAppJNI.finishStartup called"); - auto & server = chip::Server::GetInstance(); + + CHIP_ERROR err = CHIP_NO_ERROR; + auto & server = chip::Server::GetInstance(); // TODO: Set AppDelegate // &server.GetCommissioningWindowManager().SetAppDelegate(??); // Initialize binding handlers - chip::BindingManager::GetInstance().Init( + err = chip::BindingManager::GetInstance().Init( { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); + VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(err), + ChipLogError(AppServer, "Failed to init BindingManager %" CHIP_ERROR_FORMAT, err.Format())); // TODO: Set FabricDelegate // chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&mPersistenceManager); - // TODO: Add DeviceEvent Handler - // ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(DeviceEventCallback, 0)); + err = chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(support::ChipDeviceEventHandler::Handle, 0); + VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(err), + ChipLogError(AppServer, "Failed to register ChipDeviceEventHandler %" CHIP_ERROR_FORMAT, err.Format())); return support::createJMatterError(CHIP_NO_ERROR); } diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index 5ad12ef3421cf4..2f92e5f146dfa0 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -38,23 +38,23 @@ DiscoveryDelegateImpl * DiscoveryDelegateImpl::GetInstance() return _discoveryDelegateImpl; } -void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong player) +void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong player) +{ + if (commissionersCount == 0) { - if (commissionersCount == 0) - { - ChipLogProgress(AppServer, "Select discovered Casting Player (start index = 0) to request commissioning"); + ChipLogProgress(AppServer, "Select discovered Casting Player (start index = 0) to request commissioning"); - ChipLogProgress(AppServer, "Example: cast request 0"); - } - ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount); - ++commissionersCount; - player->LogDetail(); + ChipLogProgress(AppServer, "Example: cast request 0"); } + ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount); + ++commissionersCount; + player->LogDetail(); +} - void DiscoveryDelegateImpl::HandleOnUpdated(matter::casting::memory::Strong player) - { - ChipLogProgress(AppServer, "Updated CastingPlayer with ID: %s", player->GetId()); - } +void DiscoveryDelegateImpl::HandleOnUpdated(matter::casting::memory::Strong player) +{ + ChipLogProgress(AppServer, "Updated CastingPlayer with ID: %s", player->GetId()); +} static CHIP_ERROR PrintAllCommands() { @@ -62,7 +62,8 @@ static CHIP_ERROR PrintAllCommands() streamer_printf(sout, " help Usage: cast \r\n"); streamer_printf(sout, " print-bindings Usage: cast print-bindings\r\n"); streamer_printf(sout, " print-fabrics Usage: cast print-fabrics\r\n"); - streamer_printf(sout, + streamer_printf( + sout, " delete-fabric Delete a fabric from the casting client's fabric store. Usage: cast delete-fabric 1\r\n"); streamer_printf(sout, " discover Discover Casting Players. Usage: cast discover\r\n"); streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n"); @@ -104,9 +105,9 @@ void PrintFabrics() } } -void ConnectionHandler(matter::casting::core::ConnectionError err) +void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { - ChipLogProgress(AppServer, "ConnectionHandler called with %d", err); + ChipLogProgress(AppServer, "ConnectionHandler called with %" CHIP_ERROR_FORMAT, err.Format()); } static CHIP_ERROR CommandHandler(int argc, char ** argv) @@ -136,9 +137,10 @@ static CHIP_ERROR CommandHandler(int argc, char ** argv) } char * eptr; unsigned long index = static_cast(strtol(argv[1], &eptr, 10)); - std::vector> castingPlayers = matter::casting::core::CastingPlayerDiscovery::GetInstance()->GetCastingPlayers(); + std::vector> castingPlayers = + matter::casting::core::CastingPlayerDiscovery::GetInstance()->GetCastingPlayers(); VerifyOrReturnValue(0 <= index && index < castingPlayers.size(), CHIP_ERROR_INVALID_ARGUMENT, - ChipLogError(AppServer, "Invalid casting player index provided: %lu", index)); + ChipLogError(AppServer, "Invalid casting player index provided: %lu", index)); std::shared_ptr targetCastingPlayer = castingPlayers.at(index); targetCastingPlayer->Connect(ConnectionHandler); return CHIP_NO_ERROR; @@ -165,7 +167,8 @@ static CHIP_ERROR CommandHandler(int argc, char ** argv) void RegisterCommands() { - static const chip::Shell::shell_command_t sDeviceComand = { &CommandHandler, "cast", "Casting commands. Usage: cast [command_name]" }; + static const chip::Shell::shell_command_t sDeviceComand = { &CommandHandler, "cast", + "Casting commands. Usage: cast [command_name]" }; // Register the root `device` command with the top-level shell. chip::Shell::Engine::Root().RegisterCommands(&sDeviceComand, 1); diff --git a/examples/tv-casting-app/linux/simple-app-helper.h b/examples/tv-casting-app/linux/simple-app-helper.h index b03c4e2f2c88cb..2b0041a5435fc9 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.h +++ b/examples/tv-casting-app/linux/simple-app-helper.h @@ -30,7 +30,7 @@ class DiscoveryDelegateImpl : public matter::casting::core::DiscoveryDelegate { private: - DiscoveryDelegateImpl() {}; + DiscoveryDelegateImpl(){}; static DiscoveryDelegateImpl * _discoveryDelegateImpl; int commissionersCount = 0; diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index 87daeb6a7967ee..c02ce5b9aabd0b 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -24,12 +24,29 @@ namespace matter { namespace casting { namespace core { +CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr; + void CastingPlayer::Connect(ConnectCallback onCompleted, const chip::System::Clock::Seconds16 commissioningWindowTimeout) { chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest(); - ReturnOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP( - *ipAddressToUse, mAttributes.port, mAttributes.interfaceId))); - ReturnOnFailure(chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(kCommissioningWindowTimeout)); + CHIP_ERROR err = ipAddressToUse != nullptr ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE; + VerifyOrExit(ipAddressToUse != nullptr, ChipLogError(AppServer, "No IP Address found to send UDC request to")); + + SuccessOrExit(err = support::ChipDeviceEventHandler::SetUdcStatus(true)); + mOnCompleted = onCompleted; + mTargetCastingPlayer = this; + + SuccessOrExit(err = chip::Server::GetInstance().SendUserDirectedCommissioningRequest( + chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId))); + SuccessOrExit(err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow( + kCommissioningWindowTimeout)); + +exit: + if (err != CHIP_NO_ERROR) + { + support::ChipDeviceEventHandler::SetUdcStatus(false); + ChipLogError(AppServer, "CastingPlayer::Connect failed with %" CHIP_ERROR_FORMAT, err.Format()); + } } void CastingPlayer::LogDetail() const diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h index fe5c5b713e96da..01cb5c2e31db27 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -19,8 +19,9 @@ #pragma once #include "Types.h" -#include "lib/support/logging/CHIPLogging.h" +#include "support/ChipDeviceEventHandler.h" +#include "lib/support/logging/CHIPLogging.h" #include #include #include @@ -30,13 +31,8 @@ namespace matter { namespace casting { namespace core { -enum ConnectionError -{ - NO_CONNECTION_ERROR = 0, - FAILED_TO_CONNECT = 1 -}; - -using ConnectCallback = std::function; +class CastingPlayer; +using ConnectCallback = std::function; const int kPortMaxLength = 5; // port is uint16_t // +1 for the : between the hostname and the port. @@ -69,11 +65,18 @@ class CastingPlayer : public std::enable_shared_from_this // std::vector> endpoints; bool mConnected = false; CastingPlayerAttributes mAttributes; + static CastingPlayer * mTargetCastingPlayer; + ConnectCallback mOnCompleted; chip::Inet::IPAddress * GetIpAddressForUDCRequest(); + friend class support::ChipDeviceEventHandler; + public: CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; } + + static CastingPlayer * GetTargetCastingPlayer() { return mTargetCastingPlayer; } + const char * GetId() const { return mAttributes.id; } const char * GetDeviceName() const { return mAttributes.deviceName; } diff --git a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp index d31b190daadba2..9a469b9eafb53d 100644 --- a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp +++ b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp @@ -18,15 +18,138 @@ #include "ChipDeviceEventHandler.h" +#include "core/CastingPlayer.h" +#include "core/Types.h" + +#include "app/clusters/bindings/BindingManager.h" + namespace matter { namespace casting { namespace support { +using namespace matter::casting::core; + +bool ChipDeviceEventHandler::sUdcInProgress = false; + void ChipDeviceEventHandler::Handle(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { + ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle called"); + + bool runPostCommissioning = false; + chip::NodeId targetPeerNodeId = 0; + chip::FabricIndex targetFabricIndex = 0; + if (event->Type == chip::DeviceLayer::DeviceEventType::kBindingsChangedViaCluster && + CastingPlayer::GetTargetCastingPlayer() != nullptr) + { + HandleBindingsChangedViaCluster(event, arg, runPostCommissioning, targetPeerNodeId, targetFabricIndex); + } + else if (event->Type == chip::DeviceLayer::DeviceEventType::kCommissioningComplete) + { + HandleCommissioningComplete(event, arg, runPostCommissioning, targetPeerNodeId, targetFabricIndex); + } + if (runPostCommissioning) + { + ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle will connect with nodeId=0x" ChipLogFormatX64 " fabricIndex=%d", + ChipLogValueX64(targetPeerNodeId), targetFabricIndex); + // TODO + /*CHIP_ERROR err = CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->Initialize( + targetPeerNodeId, targetFabricIndex, CastingServer::GetInstance()->mOnConnectionSuccessClientCallback, + CastingServer::GetInstance()->mOnConnectionFailureClientCallback, + CastingServer::GetInstance()->mTargetVideoPlayerVendorId, CastingServer::GetInstance()->mTargetVideoPlayerProductId, + CastingServer::GetInstance()->mTargetVideoPlayerDeviceType, CastingServer::GetInstance()->mTargetVideoPlayerDeviceName, + CastingServer::GetInstance()->mTargetVideoPlayerHostName, CastingServer::GetInstance()->mTargetVideoPlayerNumIPs, + CastingServer::GetInstance()->mTargetVideoPlayerIpAddress); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to initialize target video player"); + } + + err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer( + &CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "AddVideoPlayer(ToCache) error: %" CHIP_ERROR_FORMAT, err.Format()); + } + + if (CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete) + { + CastingServer::GetInstance()->mCommissioningCallbacks.commissioningComplete(err); + }*/ + } +} + +void ChipDeviceEventHandler::HandleBindingsChangedViaCluster(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg, + bool & runPostCommissioning, chip::NodeId & targetPeerNodeId, + chip::FabricIndex & targetFabricIndex) +{ + ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleBindingsChangedViaCluster called"); + + if (CastingPlayer::GetTargetCastingPlayer()->IsConnected()) + { + ChipLogProgress( + AppServer, + "ChipDeviceEventHandler::HandleBindingsChangedViaCluster already connected to video player, reading server clusters"); + /* TODO + CastingServer::GetInstance()->ReadServerClustersForNode( + CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->GetNodeId());*/ + } + else if (sUdcInProgress) + { + ChipLogProgress(AppServer, + "ChipDeviceEventHandler::HandleBindingsChangedViaCluster UDC is in progress while handling " + "kBindingsChangedViaCluster with " + "fabricIndex: %d", + event->BindingsChanged.fabricIndex); + sUdcInProgress = false; + + // find targetPeerNodeId from binding table by matching the binding's fabricIndex with the accessing fabricIndex + // received in BindingsChanged event + for (const auto & binding : chip::BindingTable::GetInstance()) + { + ChipLogProgress(AppServer, + "ChipDeviceEventHandler::HandleBindingsChangedViaCluster Read cached binding type=%d fabrixIndex=%d " + "nodeId=0x" ChipLogFormatX64 + " groupId=%d local endpoint=%d remote endpoint=%d cluster=" ChipLogFormatMEI, + binding.type, binding.fabricIndex, ChipLogValueX64(binding.nodeId), binding.groupId, binding.local, + binding.remote, ChipLogValueMEI(binding.clusterId.ValueOr(0))); + if (binding.type == EMBER_UNICAST_BINDING && event->BindingsChanged.fabricIndex == binding.fabricIndex) + { + ChipLogProgress(AppServer, + "ChipDeviceEventHandler::HandleBindingsChangedViaCluster Matched accessingFabricIndex with " + "nodeId=0x" ChipLogFormatX64, + ChipLogValueX64(binding.nodeId)); + targetPeerNodeId = binding.nodeId; + targetFabricIndex = binding.fabricIndex; + runPostCommissioning = true; + break; + } + } + + if (targetPeerNodeId == 0 && runPostCommissioning == false) + { + ChipLogError(AppServer, + "ChipDeviceEventHandler::HandleBindingsChangedViaCluster accessingFabricIndex: %d did not match bindings", + event->BindingsChanged.fabricIndex); + CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_ERROR_INCORRECT_STATE, + CastingPlayer::GetTargetCastingPlayer()); + return; + } + } +} + +void ChipDeviceEventHandler::HandleCommissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg, + bool & runPostCommissioning, chip::NodeId & targetPeerNodeId, + chip::FabricIndex & targetFabricIndex) +{ + ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleCommissioningComplete called"); + sUdcInProgress = false; + targetPeerNodeId = event->CommissioningComplete.nodeId; + targetFabricIndex = event->CommissioningComplete.fabricIndex; + runPostCommissioning = true; } }; // namespace support }; // namespace casting -}; // namespace matter \ No newline at end of file +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.h b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.h index 8ce43f367c8643..5c3363cd4109bc 100644 --- a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.h +++ b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.h @@ -28,6 +28,27 @@ class ChipDeviceEventHandler { public: static void Handle(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + static CHIP_ERROR SetUdcStatus(bool udcInProgress) + { + if (sUdcInProgress == udcInProgress) + { + ChipLogError(AppServer, "UDC in progress state is already %d", sUdcInProgress); + return CHIP_ERROR_INCORRECT_STATE; + } + sUdcInProgress = udcInProgress; + return CHIP_NO_ERROR; + } + +private: + static void HandleBindingsChangedViaCluster(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg, + bool & runPostCommissioning, chip::NodeId & targetPeerNodeId, + chip::FabricIndex & targetFabricIndex); + + static void HandleCommissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg, + bool & runPostCommissioning, chip::NodeId & targetPeerNodeId, + chip::FabricIndex & targetFabricIndex); + + static bool sUdcInProgress; }; }; // namespace support