From 4918b5e7d6f228684ecbadbd73828f1efff5bb61 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Tue, 21 May 2024 15:21:01 -0700 Subject: [PATCH] Addressed comments by andy31415 and sharadb-amazon --- .../jni/cpp/core/MatterCastingPlayer-JNI.cpp | 2 +- .../linux/simple-app-helper.cpp | 28 +++----- .../tv-casting-common/core/CastingPlayer.cpp | 22 +++++- .../tv-casting-common/core/CastingPlayer.h | 67 ++++++++++++++----- .../core/CommissionerDeclarationHandler.cpp | 2 +- .../tv-casting-common/core/Endpoint.h | 6 ++ 6 files changed, 92 insertions(+), 35 deletions(-) diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp index 1d6866589b0de1..b2597c883406d8 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp @@ -120,7 +120,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) matter::casting::core::ConnectionCallbacks connectionCallbacks; connectionCallbacks.mOnConnectionComplete = connectCallback; - castingPlayer->VerifyOrEstablishConnection(connectionCallbacks, static_cast(commissioningWindowTimeoutSec), + castingPlayer->VerifyOrEstablishConnection(connectionCallbacks, static_cast(commissioningWindowTimeoutSec), idOptions); return support::convertMatterErrorFromCppToJava(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 d2f970fe97c134..657824ca1af8f3 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -34,7 +34,7 @@ // VendorId of the Endpoint on the CastingPlayer that the CastingApp desires to interact with after connection const uint16_t kDesiredEndpointVendorId = 65521; // Indicates that the Commissioner-Generated passcode commissioning flow is in progress. -bool gCommissionerGeneratedPasscodeFlow = false; +bool gCommissionerGeneratedPasscodeFlowRunning = false; DiscoveryDelegateImpl * DiscoveryDelegateImpl::_discoveryDelegateImpl = nullptr; bool gAwaitingCommissionerPasscodeInput = false; @@ -246,19 +246,13 @@ CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & prov options.payload.discriminator.GetLongValue()); } -void PrintEndpointsVendorAndProductIDs( - const std::vector> & endpoints) +void LogEndpointsDetails(const std::vector> & endpoints) { - ChipLogProgress(AppServer, "simple-app-helper.cpp::PrintEndpointsVendorAndProductIDs() Number of Endpoints: %d", + ChipLogProgress(AppServer, "simple-app-helper.cpp::LogEndpointsDetails() Number of Endpoints: %d", static_cast(endpoints.size())); for (const auto & endpoint : endpoints) { - int endpointId = endpoint->GetId(); - int vendorId = endpoint->GetVendorId(); - int productId = endpoint->GetProductId(); - ChipLogProgress(AppServer, - "simple-app-helper.cpp::PrintEndpointsVendorAndProductIDs() Endpoint ID: %d, Vendor ID: %d, Product ID: %d", - endpointId, vendorId, productId); + endpoint->LogDetail(); } } @@ -274,7 +268,7 @@ void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * ca "simple-app-helper.cpp::ConnectionHandler(): Failed to connect to CastingPlayer (ID: %s) with err %" CHIP_ERROR_FORMAT, targetCastingPlayer->GetId(), err.Format())); - if (gCommissionerGeneratedPasscodeFlow) + if (gCommissionerGeneratedPasscodeFlowRunning) { ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler(): Successfully connected to CastingPlayer (ID: %s) using " @@ -293,15 +287,15 @@ void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * ca ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler(): Getting endpoints avaiable for demo interactions"); std::vector> endpoints = castingPlayer->GetEndpoints(); - PrintEndpointsVendorAndProductIDs(endpoints); + LogEndpointsDetails(endpoints); // Find the desired Endpoint and auto-trigger some Matter Casting demo interactions auto it = std::find_if(endpoints.begin(), endpoints.end(), [](const matter::casting::memory::Strong & endpoint) { - if (gCommissionerGeneratedPasscodeFlow) + if (gCommissionerGeneratedPasscodeFlowRunning) { // Since the tv-app with Vendor ID 1111 does not implement the endpoint with Vendor ID 65521 we - // will (temporarily) use the first available endpoint for demo interactions. See + // will (temporarily) use the endpoint with ID == 1 for demo interactions. See // connectedhomeip/examples/tv-app/tv-common/include/AppTv.h. return endpoint->GetId() == 1; } @@ -394,7 +388,7 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) ChipLogError(AppServer, "Invalid casting player index provided: %lu", index)); targetCastingPlayer = castingPlayers.at(index); - gCommissionerGeneratedPasscodeFlow = false; + gCommissionerGeneratedPasscodeFlowRunning = false; matter::casting::core::IdentificationDeclarationOptions idOptions; chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; targetAppInfo.vendorId = kDesiredEndpointVendorId; @@ -418,8 +412,8 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) // This tv-app target Vendor ID (1111), does not implement the AccountLogin cluster, which would otherwise auto // commission using the Commissionee-Generated passcode upon recieving the IdentificationDeclaration Message. // See connectedhomeip/examples/tv-app/tv-common/include/AppTv.h. - targetAppInfo.vendorId = 1111; - gCommissionerGeneratedPasscodeFlow = true; + targetAppInfo.vendorId = 1111; + gCommissionerGeneratedPasscodeFlowRunning = true; } else { 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 b4ca9895dedf7e..ce7653573c4089 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -29,7 +29,7 @@ namespace core { CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr; -void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCallbacks, uint64_t commissioningWindowTimeoutSec, +void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCallbacks, uint16_t commissioningWindowTimeoutSec, IdentificationDeclarationOptions idOptions) { ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called"); @@ -389,6 +389,26 @@ void CastingPlayer::LogDetail() const } } +CastingPlayer::CastingPlayer(const CastingPlayer & other) : + mEndpoints(other.mEndpoints), mConnectionState(other.mConnectionState), mAttributes(other.mAttributes), + mIdOptions(other.mIdOptions), mCommissioningWindowTimeoutSec(other.mCommissioningWindowTimeoutSec), + mOnCompleted(other.mOnCompleted) +{} + +CastingPlayer & CastingPlayer::operator=(const CastingPlayer & other) +{ + if (this != &other) + { + mAttributes = other.mAttributes; + mEndpoints = other.mEndpoints; + mConnectionState = other.mConnectionState; + mIdOptions = other.mIdOptions; + mCommissioningWindowTimeoutSec = other.mCommissioningWindowTimeoutSec; + mOnCompleted = other.mOnCompleted; + } + return *this; +} + ConnectionContext::ConnectionContext(void * clientContext, core::CastingPlayer * targetCastingPlayer, chip::OnDeviceConnected onDeviceConnectedFn, chip::OnDeviceConnectionFailure onDeviceConnectionFailureFn) 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 fb264ceb0001a2..d5bbcd46006920 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -39,7 +39,7 @@ namespace core { const int kPortMaxLength = 5; // port is uint16_t // +1 for the : between the hostname and the port. const int kIdMaxLength = chip::Dnssd::kHostNameMaxLength + kPortMaxLength + 1; -const uint64_t kCommissioningWindowTimeoutSec = 3 * 60; // 3 minutes +const uint16_t kCommissioningWindowTimeoutSec = 3 * 60; // 3 minutes /** * @brief Describes an Endpoint that the client wants to connect to @@ -111,41 +111,78 @@ class CastingPlayer : public std::enable_shared_from_this return (compareResult == 0) ? 1 : 0; } + /** + * @brief Define the copy constructor + */ + CastingPlayer(const CastingPlayer & other); + + /** + * @brief Define the assignment operator + */ + CastingPlayer & operator=(const CastingPlayer & other); + /** * @return true if this CastingPlayer is connected to the CastingApp */ bool IsConnected() const { return mConnectionState == CASTING_PLAYER_CONNECTED; } /** - * @brief Verifies that a connection exists with this CastingPlayer, or triggers a new session - * request. If the CastingApp does not have the nodeId and fabricIndex of this CastingPlayer cached on disk, - * this will execute the User Directed Commissioning (UDC) process. + * @brief Verifies that a connection exists with this CastingPlayer, or triggers a new commissioning session request. If the + * CastingApp does not have the nodeId and fabricIndex of this CastingPlayer cached on disk, this will execute the User Directed + * Commissioning (UDC) process by sending an IdentificationDeclaration message to the Commissioner. For certain UDC features, + * where a Commissioner reply is expected, this API needs to be followed up with the ContinueConnecting() API defiend below. See + * the Matter UDC specification or parameter class definitions for details on features not included in the description below. + * + * @param connectionCallbacks contains the ConnectCallback (Required) and CommissionerDeclarationCallback (Optional) defiend in + * ConnectCallbacks.h. + * + * ConnectCallback: The callback called when the connection process has ended, regardless of whether it was successful or not. + * + * CommissionerDeclarationCallback: The callback called when the Commissionee receives a CommissionerDeclaration message from + * the Commissioner. This callback is needed to support UDC features where a reply from the Commissioner is expected. It + * provides information indicating the Commissioner’s pre-commissioning state. + * + * For example: During Commissioner-Generated passcode commissioning, the Commissioner replies with a CommissionerDeclaration + * message with PasscodeDialogDisplayed and CommissionerPasscode set to true. Given these Commissioner state details, the client + * is expected to perform some actions, detailed in the ContinueConnecting() API below, and then call the ContinueConnecting() + * API to complete the process. * - * @param connectionCallbacks contains the ConnectCallback and CommissionerDeclarationCallback (Optional). * @param commissioningWindowTimeoutSec (Optional) time (in sec) to keep the commissioning window open, if commissioning is * required. Needs to be >= kCommissioningWindowTimeoutSec. + * * @param idOptions (Optional) Parameters in the IdentificationDeclaration message sent by the Commissionee to the Commissioner. * These parameters specify the information relating to the requested commissioning session. + * + * For example: To invoke the Commissioner-Generated passcode commissioning flow, the client would call this API with + * IdentificationDeclarationOptions containing CommissionerPasscode set to true. See IdentificationDeclarationOptions.h for a + * complete list of optional parameters. + * * Furthermore, attributes (such as VendorId) describe the TargetApp that the client wants to interact with after commissioning. * If this value is passed in, VerifyOrEstablishConnection() will force UDC, in case the desired * TargetApp is not found in the on-device CastingStore. */ void VerifyOrEstablishConnection(ConnectionCallbacks connectionCallbacks, - uint64_t commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec, + uint16_t commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec, IdentificationDeclarationOptions idOptions = IdentificationDeclarationOptions()); /** - * @brief Continues the UDC process during the Commissioner-Generated passcode commissioning flow by sending a second - * IdentificationDeclaration to Commissioner containing CommissionerPasscode and CommissionerPasscodeReady set to true. At this - * point it is assumed that the following have occurred: - * 1. Client has handled the Commissioner's CommissionerDecelration message with PasscodeDialogDisplayed and - * CommissionerPasscode set to true. - * 2. Client prompted user to input Passcode from Commissioner. - * 3. Client has updated the commissioning session's PAKE verifier using the user input Passcode by updating the CastingApps + * @brief This is a continuation of the Commissioner-Generated passcode commissioning flow started via the + * VerifyOrEstablishConnection() API above. It continues the UDC process by sending a second IdentificationDeclaration message + * to Commissioner containing CommissionerPasscode and CommissionerPasscodeReady set to true. At this point it is assumed that + * the following have occurred: + * + * 1. Client (Commissionee) has sent the first IdentificationDeclaration message, via VerifyOrEstablishConnection(), to the + * Commissioner containing CommissionerPasscode set to true. + * 2. Commissioner generated and displayed a passcode. + * 3. The Commissioner replied with a CommissionerDecelration message with PasscodeDialogDisplayed and CommissionerPasscode set + * to true. + * 3. Client has handled the Commissioner's CommissionerDecelration message. + * 4. Client prompted user to input Passcode from Commissioner. + * 5. Client has updated the commissioning session's PAKE verifier using the user input Passcode by updating the CastingApps * CommissionableDataProvider * (matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider(CommissionableDataProvider)). * - * The same connectionCallbacks and commissioningWindowTimeoutSec parameters passed in to VerifyOrEstablishConnection() will be + * The same connectionCallbacks and commissioningWindowTimeoutSec parameters passed into VerifyOrEstablishConnection() will be * used. */ void ContinueConnecting(); @@ -218,7 +255,7 @@ class CastingPlayer : public std::enable_shared_from_this CastingPlayerAttributes mAttributes; IdentificationDeclarationOptions mIdOptions; static CastingPlayer * mTargetCastingPlayer; - uint64_t mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; + uint16_t mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; ConnectCallback mOnCompleted = {}; /** diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp index bb9ecc3c4c57d9..22e7d49cdb7a5d 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp @@ -38,7 +38,7 @@ CommissionerDeclarationHandler * CommissionerDeclarationHandler::GetInstance() } // TODO: In the following PRs. Implement setHandler() for CommissionerDeclaration messages and expose messages to higher layers for -// Linux(DONE), Android(pending) and iOS(pending). +// Linux, Android and iOS. void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage( const chip::Transport::PeerAddress & source, chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) { diff --git a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h index 4da8cd56210b07..fc18267cf466be 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h +++ b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h @@ -145,6 +145,12 @@ class Endpoint : public std::enable_shared_from_this } return nullptr; } + + void LogDetail() const + { + ChipLogProgress(AppServer, "Endpoint::LogDetail() Endpoint ID: %d, Vendor ID: %d, Product ID: %d", mAttributes.mId, + mAttributes.mVendorId, mAttributes.mProductId); + } }; }; // namespace core