Linux tv-casting-app v1.3 IdentificationDeclaration message (#33283)
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java
index a706780..65d6705 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java
@@ -327,8 +327,9 @@
TAG,
"OnClickListener.onClick() called for CastingPlayer with deviceId: "
+ castingPlayer.getDeviceId());
- DiscoveryExampleFragment.Callback callback1 = (DiscoveryExampleFragment.Callback) context;
- callback1.handleConnectionButtonClicked(castingPlayer);
+ DiscoveryExampleFragment.Callback onClickCallback =
+ (DiscoveryExampleFragment.Callback) context;
+ onClickCallback.handleConnectionButtonClicked(castingPlayer);
};
playerDescription.setOnClickListener(clickListener);
return view;
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 caa64b4..1c4a949 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
@@ -53,9 +53,14 @@
CastingPlayer * castingPlayer = support::convertCastingPlayerFromJavaToCpp(thiz);
VerifyOrReturnValue(castingPlayer != nullptr, support::convertMatterErrorFromCppToJava(CHIP_ERROR_INVALID_ARGUMENT));
+ matter::casting::core::IdentificationDeclarationOptions idOptions;
+
+ // TODO: In the following PRs. Replace EndpointFilter Java class with IdentificationDeclarationOptions Java class.
matter::casting::core::EndpointFilter desiredEndpointFilter;
if (desiredEndpointFilterJavaObject != nullptr)
{
+ chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
+
// Convert the EndpointFilter Java class to a C++ EndpointFilter
jclass endpointFilterJavaClass = env->GetObjectClass(desiredEndpointFilterJavaObject);
jfieldID vendorIdFieldId = env->GetFieldID(endpointFilterJavaClass, "vendorId", "Ljava/lang/Integer;");
@@ -66,20 +71,28 @@
// "Ljava/util/List;");
// Value of 0 means unspecified
- desiredEndpointFilter.vendorId = vendorIdIntegerObject != nullptr
+ targetAppInfo.vendorId = vendorIdIntegerObject != nullptr
? static_cast<uint16_t>(env->CallIntMethod(
vendorIdIntegerObject, env->GetMethodID(env->GetObjectClass(vendorIdIntegerObject), "intValue", "()I")))
: 0;
- desiredEndpointFilter.productId = productIdIntegerObject != nullptr
+ targetAppInfo.productId = productIdIntegerObject != nullptr
? static_cast<uint16_t>(env->CallIntMethod(
productIdIntegerObject, env->GetMethodID(env->GetObjectClass(productIdIntegerObject), "intValue", "()I")))
: 0;
- // TODO: In following PRs. Translate the Java requiredDeviceTypes list to a C++ requiredDeviceTypes vector. For now we're
- // passing an empty list of DeviceTypeStruct.
+
+ CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo);
+ if (result != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer,
+ "MatterCastingPlayer-JNI::verifyOrEstablishConnection() failed to add targetAppInfo: %" CHIP_ERROR_FORMAT,
+ result.Format());
+ }
}
MatterCastingPlayerJNIMgr().mConnectionSuccessHandler.SetUp(env, jSuccessCallback);
MatterCastingPlayerJNIMgr().mConnectionFailureHandler.SetUp(env, jFailureCallback);
+
+ // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter.
castingPlayer->VerifyOrEstablishConnection(
[](CHIP_ERROR err, CastingPlayer * playerPtr) {
ChipLogProgress(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() ConnectCallback called");
@@ -96,7 +109,7 @@
MatterCastingPlayerJNIMgr().mConnectionFailureHandler.Handle(err);
}
},
- static_cast<unsigned long long int>(commissioningWindowTimeoutSec), desiredEndpointFilter);
+ static_cast<unsigned long long int>(commissioningWindowTimeoutSec), idOptions);
return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR);
}
diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm
index b69bbfb..3bc7223 100644
--- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm
+++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm
@@ -52,19 +52,29 @@
dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue];
dispatch_sync(workQueue, ^{
+ matter::casting::core::IdentificationDeclarationOptions idOptions;
+
+ // TODO: In the following PRs. Replace EndpointFilter objC class with IdentificationDeclarationOptions objC class.
__block matter::casting::core::EndpointFilter cppDesiredEndpointFilter;
if (desiredEndpointFilter != nil) {
- cppDesiredEndpointFilter.vendorId = desiredEndpointFilter.vendorId;
- cppDesiredEndpointFilter.productId = desiredEndpointFilter.productId;
+ chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
+ targetAppInfo.vendorId = desiredEndpointFilter.vendorId;
+ targetAppInfo.productId = desiredEndpointFilter.productId;
+
+ CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo);
+ if (result != CHIP_NO_ERROR) {
+ ChipLogError(AppServer, "MCCastingPlayer.verifyOrEstablishConnectionWithCompletionBlock failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format());
+ }
}
+ // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter.
_cppCastingPlayer->VerifyOrEstablishConnection(
[completion](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) {
dispatch_queue_t clientQueue = [[MCCastingApp getSharedInstance] getClientQueue];
dispatch_async(clientQueue, ^{
completion(err == CHIP_NO_ERROR ? nil : [MCErrorUtils NSErrorFromChipError:err]);
});
- }, timeout, cppDesiredEndpointFilter);
+ }, timeout, idOptions);
});
}
diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp
index de8c255..ceb6623 100644
--- a/examples/tv-casting-app/linux/simple-app-helper.cpp
+++ b/examples/tv-casting-app/linux/simple-app-helper.cpp
@@ -49,8 +49,10 @@
if (commissionersCount == 0)
{
ChipLogProgress(AppServer, "Select discovered Casting Player (start index = 0) to request commissioning");
+ ChipLogProgress(AppServer, "Include the cgp flag to attempt the Commissioner-Generated Passcode commissioning flow");
- ChipLogProgress(AppServer, "Example: cast request 0");
+ ChipLogProgress(AppServer, "Example1 Commissionee Passcode: cast request 0");
+ ChipLogProgress(AppServer, "Example2 Commissioner Passcode: cast request 0 cgp");
}
ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount);
++commissionersCount;
@@ -170,10 +172,12 @@
{
VerifyOrReturn(err == CHIP_NO_ERROR,
ChipLogProgress(AppServer,
- "ConnectionHandler: Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT,
+ "ConnectionHandler(): Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT,
castingPlayer->GetId(), err.Format()));
- ChipLogProgress(AppServer, "ConnectionHandler: Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId());
+ ChipLogProgress(AppServer, "ConnectionHandler(): Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId());
+ ChipLogProgress(AppServer, "ConnectionHandler(): Triggering demo interactions with CastingPlayer(ID: %s)",
+ castingPlayer->GetId());
std::vector<matter::casting::memory::Strong<matter::casting::core::Endpoint>> endpoints = castingPlayer->GetEndpoints();
// Find the desired Endpoint and auto-trigger some Matter Casting demo interactions
@@ -219,18 +223,18 @@
}
if (strcmp(argv[0], "discover") == 0)
{
- ChipLogProgress(AppServer, "discover");
+ ChipLogProgress(AppServer, "CommandHandler() discover");
return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
}
if (strcmp(argv[0], "stop-discovery") == 0)
{
- ChipLogProgress(AppServer, "stop-discovery");
+ ChipLogProgress(AppServer, "CommandHandler() stop-discovery");
return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery();
}
if (strcmp(argv[0], "request") == 0)
{
- ChipLogProgress(AppServer, "request");
+ ChipLogProgress(AppServer, "CommandHandler() request");
if (argc < 2)
{
return PrintAllCommands();
@@ -243,10 +247,40 @@
ChipLogError(AppServer, "Invalid casting player index provided: %lu", index));
std::shared_ptr<matter::casting::core::CastingPlayer> targetCastingPlayer = castingPlayers.at(index);
- matter::casting::core::EndpointFilter desiredEndpointFilter;
- desiredEndpointFilter.vendorId = kDesiredEndpointVendorId;
+ matter::casting::core::IdentificationDeclarationOptions idOptions;
+ if (argc == 3)
+ {
+ if (strcmp(argv[2], "cgp") == 0)
+ {
+ // Attempt Commissioner-Generated Passcode (cgp) commissioning flow only if the CastingPlayer indicates support for
+ // it.
+ if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode())
+ {
+ ChipLogProgress(
+ AppServer,
+ "CommandHandler() request %lu cgp. Attempting the Commissioner-Generated Passcode commissioning flow",
+ index);
+ idOptions.mCommissionerPasscode = true;
+ }
+ else
+ {
+ ChipLogError(AppServer,
+ "CommandHandler() request %lu cgp. Selected CastingPLayer does not support the "
+ "Commissioner-Generated Passcode commissioning flow",
+ index);
+ }
+ }
+ }
+ chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
+ targetAppInfo.vendorId = kDesiredEndpointVendorId;
+ CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo);
+ if (result != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format());
+ }
+
targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler, matter::casting::core::kCommissioningWindowTimeoutSec,
- desiredEndpointFilter);
+ idOptions);
return CHIP_NO_ERROR;
}
if (strcmp(argv[0], "print-bindings") == 0)
@@ -280,8 +314,12 @@
" delete-fabric <index> 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");
- streamer_printf(
- sout, " request <index> Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n");
+ streamer_printf(sout,
+ " request <index> Request connecting to discovered Casting Player with [index] using the "
+ "Commissionee-Generated Passcode commissioning flow. Usage: cast request 0\r\n");
+ streamer_printf(sout,
+ " request <index> cgp Request connecting to discovered Casting Player with [index] using the "
+ "Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n");
streamer_printf(sout, "\r\n");
return CHIP_NO_ERROR;
diff --git a/examples/tv-casting-app/linux/simple-app-helper.h b/examples/tv-casting-app/linux/simple-app-helper.h
index b1dbbe6..f8826b5 100644
--- a/examples/tv-casting-app/linux/simple-app-helper.h
+++ b/examples/tv-casting-app/linux/simple-app-helper.h
@@ -20,6 +20,7 @@
#include "core/CastingPlayer.h"
#include "core/CastingPlayerDiscovery.h"
+#include "core/IdentificationDeclarationOptions.h"
#include "core/Types.h"
#include <platform/CHIPDeviceLayer.h>
diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn
index 72f14fb..a58d272 100644
--- a/examples/tv-casting-app/tv-casting-common/BUILD.gn
+++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn
@@ -106,6 +106,7 @@
"core/CastingPlayerDiscovery.cpp",
"core/CastingPlayerDiscovery.h",
"core/Command.h",
+ "core/CommissionerDeclarationHandler.cpp",
"core/Endpoint.cpp",
"core/Endpoint.h",
"core/Types.h",
diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp
index f786591..7e00013 100644
--- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp
+++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp
@@ -18,6 +18,7 @@
#include "CastingApp.h"
+#include "CommissionerDeclarationHandler.h"
#include "support/CastingStore.h"
#include "support/ChipDeviceEventHandler.h"
@@ -100,6 +101,9 @@
// reconnect (or verify connection) to the CastingPlayer that the app was connected to before being stopped, if any
if (CastingPlayer::GetTargetCastingPlayer() != nullptr)
{
+ ChipLogProgress(
+ Discovery,
+ "CastingApp::Start() calling VerifyOrEstablishConnection() to reconnect (or verify connection) to a CastingPlayer");
CastingPlayer::GetTargetCastingPlayer()->VerifyOrEstablishConnection(
[](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) {
if (err != CHIP_NO_ERROR)
@@ -136,6 +140,12 @@
// Register DeviceEvent Handler
ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0));
+#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+ // Set a handler for Commissioner's CommissionerDeclaration messages.
+ chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(
+ CommissionerDeclarationHandler::GetInstance());
+#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+
mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING
return CHIP_NO_ERROR;
}
@@ -145,6 +155,11 @@
ChipLogProgress(Discovery, "CastingApp::Stop() called");
VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE);
+#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+ // Remove the handler previously set for Commissioner's CommissionerDeclaration messages.
+ chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr);
+#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+
// Shutdown the Matter server
chip::Server::GetInstance().Shutdown();
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 c9f938d..0f455d6 100644
--- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp
+++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp
@@ -30,7 +30,7 @@
CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;
void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec,
- EndpointFilter desiredEndpointFilter)
+ IdentificationDeclarationOptions idOptions)
{
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called");
@@ -50,12 +50,14 @@
mOnCompleted = onCompleted;
mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec;
mTargetCastingPlayer = this;
+ mIdOptions = idOptions;
// If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present
// in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any,
- // as per desiredEndpointFilter, simply Find or Re-establish the CASE session and return early
+ // as per IdentificationDeclarationOptions.mTargetAppInfos, simply Find or Re-establish the CASE session and return early.
if (cachedCastingPlayers.size() != 0)
{
+ ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Re-establishing CASE with cached CastingPlayer");
it = std::find_if(cachedCastingPlayers.begin(), cachedCastingPlayers.end(),
[this](const core::CastingPlayer & castingPlayerParam) { return castingPlayerParam == *this; });
@@ -63,7 +65,7 @@
if (it != cachedCastingPlayers.end())
{
unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it);
- if (ContainsDesiredEndpoint(&cachedCastingPlayers[index], desiredEndpointFilter))
+ if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.getTargetAppInfoList()))
{
ChipLogProgress(
AppServer,
@@ -163,14 +165,15 @@
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest()
{
+ ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest()");
chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest();
VerifyOrReturnValue(ipAddressToUse != nullptr, CHIP_ERROR_INCORRECT_STATE,
ChipLogError(AppServer, "No IP Address found to send UDC request to"));
ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true));
- // TODO: expose options to the higher layer
- chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
+ chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id = mIdOptions.buildIdentificationDeclarationMessage();
+
ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest(
chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id));
@@ -216,21 +219,27 @@
connectionContext->mOnConnectionFailureCallback);
}
-bool CastingPlayer::ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter)
+bool CastingPlayer::ContainsDesiredTargetApp(
+ core::CastingPlayer * cachedCastingPlayer,
+ std::vector<chip::Protocols::UserDirectedCommissioning::TargetAppInfo> desiredTargetApps)
{
std::vector<memory::Strong<Endpoint>> cachedEndpoints = cachedCastingPlayer->GetEndpoints();
- for (const auto & cachedEndpoint : cachedEndpoints)
+ for (size_t i = 0; i < desiredTargetApps.size(); i++)
{
- bool match = true;
- match = match && (desiredEndpointFilter.vendorId == 0 || cachedEndpoint->GetVendorId() == desiredEndpointFilter.vendorId);
- match =
- match && (desiredEndpointFilter.productId == 0 || cachedEndpoint->GetProductId() == desiredEndpointFilter.productId);
- // TODO: check deviceTypeList
- if (match)
+ for (const auto & cachedEndpoint : cachedEndpoints)
{
- return true;
+ bool match = true;
+ match = match && (desiredTargetApps[i].vendorId == 0 || cachedEndpoint->GetVendorId() == desiredTargetApps[i].vendorId);
+ match =
+ match && (desiredTargetApps[i].productId == 0 || cachedEndpoint->GetProductId() == desiredTargetApps[i].productId);
+ if (match)
+ {
+ ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer found");
+ return true;
+ }
}
}
+ ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer not found");
return false;
}
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 783d50f..2748eaf 100644
--- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h
+++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h
@@ -18,7 +18,9 @@
#pragma once
+#include "CommissionerDeclarationHandler.h"
#include "Endpoint.h"
+#include "IdentificationDeclarationOptions.h"
#include "Types.h"
#include "support/ChipDeviceEventHandler.h"
#include "support/EndpointListLoader.h"
@@ -123,13 +125,15 @@
* For failure - called back with an error and nullptr.
* @param commissioningWindowTimeoutSec (Optional) time (in sec) to keep the commissioning window open, if commissioning is
* required. Needs to be >= kCommissioningWindowTimeoutSec.
- * @param desiredEndpointFilter (Optional) Attributes (such as VendorId) describing an Endpoint that the client wants to
- * interact with after commissioning. If this value is passed in, the VerifyOrEstablishConnection will force User Directed
- * Commissioning, in case the desired Endpoint is not found in the on device CastingStore.
+ * @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.
+ * 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 User Directed Commissioning, in case the desired
+ * TargetApp is not found in the on-device CastingStore.
*/
void VerifyOrEstablishConnection(ConnectCallback onCompleted,
unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec,
- EndpointFilter desiredEndpointFilter = EndpointFilter());
+ IdentificationDeclarationOptions idOptions = IdentificationDeclarationOptions());
/**
* @brief Sets the internal connection state of this CastingPlayer to "disconnected"
@@ -197,6 +201,7 @@
std::vector<memory::Strong<Endpoint>> mEndpoints;
ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
CastingPlayerAttributes mAttributes;
+ IdentificationDeclarationOptions mIdOptions;
static CastingPlayer * mTargetCastingPlayer;
unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec;
ConnectCallback mOnCompleted = {};
@@ -217,12 +222,12 @@
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
/**
- * @brief Checks if the cachedCastingPlayer contains an Endpoint that matches the description of the desiredEndpointFilter
- *
- * @return true - cachedCastingPlayer contains at least one endpoint that matches all the (non-default) values in
- * desiredEndpointFilter, false otherwise
+ * @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list.
+ * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values for vendorID and
+ * productID as described in the desiredTargetApps list, false otherwise.
*/
- bool ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter);
+ bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer,
+ std::vector<chip::Protocols::UserDirectedCommissioning::TargetAppInfo> desiredTargetApps);
// ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with
// and connect to a CastingPlayer
diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp
new file mode 100644
index 0000000..1bedc6c
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (c) 2024 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.
+ */
+
+#include "CommissionerDeclarationHandler.h"
+
+#include "Types.h"
+
+namespace matter {
+namespace casting {
+namespace core {
+
+CommissionerDeclarationHandler * CommissionerDeclarationHandler::sCommissionerDeclarationHandler_ = nullptr;
+
+CommissionerDeclarationHandler * CommissionerDeclarationHandler::GetInstance()
+{
+ if (sCommissionerDeclarationHandler_ == nullptr)
+ {
+ sCommissionerDeclarationHandler_ = new CommissionerDeclarationHandler();
+ }
+ return sCommissionerDeclarationHandler_;
+}
+
+// TODO: In the following PRs. Implement setHandler() for CommissionerDeclaration messages and expose messages to higher layers for
+// Linux, Android and iOS.
+void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage(
+ const chip::Transport::PeerAddress & source, chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd)
+{
+ ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called TODO: handle message");
+ cd.DebugLog();
+}
+
+}; // namespace core
+}; // namespace casting
+}; // namespace matter
diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h
new file mode 100644
index 0000000..e84ca59
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (c) 2024 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Types.h"
+
+namespace matter {
+namespace casting {
+namespace core {
+
+/**
+ * @brief React to the Commissioner's CommissionerDeclaration messages with this singleton.
+ */
+class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler
+{
+public:
+ CommissionerDeclarationHandler(const CommissionerDeclarationHandler &) = delete;
+ void operator=(const CommissionerDeclarationHandler &) = delete;
+
+ static CommissionerDeclarationHandler * GetInstance();
+
+ void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source,
+ chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override;
+
+private:
+ static CommissionerDeclarationHandler * sCommissionerDeclarationHandler_;
+ CommissionerDeclarationHandler() {}
+ ~CommissionerDeclarationHandler() {}
+};
+
+}; // namespace core
+}; // namespace casting
+}; // namespace matter
diff --git a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h
new file mode 100644
index 0000000..af1ae2a
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h
@@ -0,0 +1,126 @@
+/*
+ *
+ * Copyright (c) 2024 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Types.h"
+#include <vector>
+
+namespace matter {
+namespace casting {
+namespace core {
+
+/**
+ * This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the
+ * Commissioner. The options specify information relating to the requested UDC commissioning session.
+ */
+class IdentificationDeclarationOptions
+{
+public:
+ /**
+ * Feature: Target Content Application
+ * Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message
+ * if a commissioning Passcode is needed.
+ */
+ bool mNoPasscode = false;
+ /**
+ * Feature: Coordinate Passcode Dialogs
+ * Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the
+ * Commissioner has been shown to the user.
+ */
+ bool mCdUponPasscodeDialog = false;
+ /**
+ * Feature: Commissioner-Generated Passcode
+ * Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning.
+ */
+ bool mCommissionerPasscode = false;
+ /**
+ * Feature: Commissioner-Generated Passcode
+ * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready
+ * for commissioning.
+ */
+ bool mCommissionerPasscodeReady = false;
+ /**
+ * Feature: Coordinate Passcode Dialogs
+ * Flag to indicate when the Commissionee user has decided to exit the commissioning process.
+ */
+ bool mCancelPasscode = false;
+
+ CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo & targetAppInfo)
+ {
+ if (mTargetAppInfos.size() >= CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS)
+ {
+ ChipLogError(AppServer,
+ "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %d",
+ CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS);
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ mTargetAppInfos.push_back(targetAppInfo);
+ return CHIP_NO_ERROR;
+ }
+
+ std::vector<chip::Protocols::UserDirectedCommissioning::TargetAppInfo> getTargetAppInfoList() const { return mTargetAppInfos; }
+
+ /**
+ * @brief Builds an IdentificationDeclaration message to be sent to a CastingPlayer, given the options state specified in this
+ * object.
+ */
+ chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration buildIdentificationDeclarationMessage()
+ {
+ ChipLogProgress(AppServer, "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage()");
+ chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
+
+ std::vector<chip::Protocols::UserDirectedCommissioning::TargetAppInfo> targetAppInfos = getTargetAppInfoList();
+ for (size_t i = 0; i < targetAppInfos.size(); i++)
+ {
+ id.AddTargetAppInfo(targetAppInfos[i]);
+ }
+ id.SetNoPasscode(mNoPasscode);
+ id.SetCdUponPasscodeDialog(mCdUponPasscodeDialog);
+ id.SetCancelPasscode(mCancelPasscode);
+
+ ChipLogProgress(AppServer,
+ "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscode: %s",
+ mCommissionerPasscode ? "true" : "false");
+ id.SetCommissionerPasscode(mCommissionerPasscode);
+
+ ChipLogProgress(AppServer,
+ "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscodeReady: %s",
+ mCommissionerPasscodeReady ? "true" : "false");
+ if (mCommissionerPasscodeReady)
+ {
+ id.SetCommissionerPasscodeReady(true);
+ mCommissionerPasscodeReady = false;
+ }
+ return id;
+ }
+
+private:
+ /**
+ * Feature: Target Content Application
+ * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication.
+ * Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the
+ * desired TargetApp is not found in the on-device CastingStore.
+ */
+ std::vector<chip::Protocols::UserDirectedCommissioning::TargetAppInfo> mTargetAppInfos;
+};
+
+}; // namespace core
+}; // namespace casting
+}; // namespace matter
diff --git a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h
index 74926b0..f5887bc 100644
--- a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h
+++ b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h
@@ -53,6 +53,10 @@
#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0
+// TVs can handle the memory impact of supporting a larger list of target apps. See
+// examples/tv-app/tv-common/include/CHIPProjectAppConfig.h
+#define CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS 10
+
// For casting, we need to allow more ACL entries, and more complex entries
#define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY 20
#define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY 20
diff --git a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h
index 9539a29..080011f 100644
--- a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h
+++ b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h
@@ -42,6 +42,7 @@
chip::Credentials::DeviceAttestationCredentialsProvider * deviceAttestationCredentialsProvider,
chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier,
ServerInitParamsProvider * serverInitParamsProvider)
+ // TODO: In the following PRs. Add CommissionerDeclarationHandler.
{
VerifyOrReturnError(commissionableDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(deviceAttestationCredentialsProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp
index 1ad98d2..ad085d5 100644
--- a/src/app/server/Server.cpp
+++ b/src/app/server/Server.cpp
@@ -621,7 +621,7 @@
CHIP_ERROR Server::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner,
Protocols::UserDirectedCommissioning::IdentificationDeclaration & id)
{
- ChipLogDetail(AppServer, "SendUserDirectedCommissioningRequest2");
+ ChipLogDetail(AppServer, "Server::SendUserDirectedCommissioningRequest()");
CHIP_ERROR err;
diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
index a06bffc..fb31049 100644
--- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
+++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
@@ -367,6 +367,7 @@
{
ChipLogProgress(AppServer, "TLV end of array");
ReturnErrorOnFailure(reader.ExitContainer(listContainerType));
+ err = CHIP_NO_ERROR;
}
}
break;