Skip to content

Commit e222838

Browse files
Linux tv-casting-app v1.3 IdentificationDeclaration message
1 parent 9db03ee commit e222838

File tree

8 files changed

+165
-36
lines changed

8 files changed

+165
-36
lines changed

examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ JNI_METHOD(jobject, verifyOrEstablishConnection)
8080

8181
MatterCastingPlayerJNIMgr().mConnectionSuccessHandler.SetUp(env, jSuccessCallback);
8282
MatterCastingPlayerJNIMgr().mConnectionFailureHandler.SetUp(env, jFailureCallback);
83+
84+
// TODO: In the following PRs. Removed desiredEndpointFilter to fix Android app build issue. Replace desiredEndpointFilter with
85+
// optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter.
8386
castingPlayer->VerifyOrEstablishConnection(
8487
[](CHIP_ERROR err, CastingPlayer * playerPtr) {
8588
ChipLogProgress(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() ConnectCallback called");
@@ -96,7 +99,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection)
9699
MatterCastingPlayerJNIMgr().mConnectionFailureHandler.Handle(err);
97100
}
98101
},
99-
static_cast<unsigned long long int>(commissioningWindowTimeoutSec), desiredEndpointFilter);
102+
static_cast<unsigned long long int>(commissioningWindowTimeoutSec));
100103
return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR);
101104
}
102105

examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,14 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError
5858
cppDesiredEndpointFilter.productId = desiredEndpointFilter.productId;
5959
}
6060

61+
// TODO: In the following PRs. Removed desiredEndpointFilter to fix iOS app build issue. Replace desiredEndpointFilter with optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter.
6162
_cppCastingPlayer->VerifyOrEstablishConnection(
6263
[completion](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) {
6364
dispatch_queue_t clientQueue = [[MCCastingApp getSharedInstance] getClientQueue];
6465
dispatch_async(clientQueue, ^{
6566
completion(err == CHIP_NO_ERROR ? nil : [MCErrorUtils NSErrorFromChipError:err]);
6667
});
67-
}, timeout, cppDesiredEndpointFilter);
68+
}, timeout);
6869
});
6970
}
7071

examples/tv-casting-app/linux/simple-app-helper.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,12 @@ void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * ca
170170
{
171171
VerifyOrReturn(err == CHIP_NO_ERROR,
172172
ChipLogProgress(AppServer,
173-
"ConnectionHandler: Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT,
173+
"ConnectionHandler(): Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT,
174174
castingPlayer->GetId(), err.Format()));
175175

176-
ChipLogProgress(AppServer, "ConnectionHandler: Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId());
176+
ChipLogProgress(AppServer, "ConnectionHandler(): Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId());
177+
ChipLogProgress(AppServer, "ConnectionHandler(): Triggering demo interactions with CastingPlayer(ID: %s)",
178+
castingPlayer->GetId());
177179

178180
std::vector<matter::casting::memory::Strong<matter::casting::core::Endpoint>> endpoints = castingPlayer->GetEndpoints();
179181
// Find the desired Endpoint and auto-trigger some Matter Casting demo interactions
@@ -230,7 +232,7 @@ CHIP_ERROR CommandHandler(int argc, char ** argv)
230232
}
231233
if (strcmp(argv[0], "request") == 0)
232234
{
233-
ChipLogProgress(AppServer, "request");
235+
ChipLogProgress(AppServer, "CommandHandler() request");
234236
if (argc < 2)
235237
{
236238
return PrintAllCommands();
@@ -243,10 +245,17 @@ CHIP_ERROR CommandHandler(int argc, char ** argv)
243245
ChipLogError(AppServer, "Invalid casting player index provided: %lu", index));
244246
std::shared_ptr<matter::casting::core::CastingPlayer> targetCastingPlayer = castingPlayers.at(index);
245247

246-
matter::casting::core::EndpointFilter desiredEndpointFilter;
247-
desiredEndpointFilter.vendorId = kDesiredEndpointVendorId;
248+
matter::casting::core::IdentificationDeclarationOptions idOptions;
249+
idOptions.mNumTargetAppInfos = 1;
250+
idOptions.mTargetAppInfos[0].vendorId = kDesiredEndpointVendorId;
251+
// Attempt Commissioner-Generated Passcode commissioning flow only if the CastingPlayer indicates support for it.
252+
if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode())
253+
{
254+
idOptions.mCommissionerPasscode = true;
255+
}
256+
248257
targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler, matter::casting::core::kCommissioningWindowTimeoutSec,
249-
desiredEndpointFilter);
258+
idOptions);
250259
return CHIP_NO_ERROR;
251260
}
252261
if (strcmp(argv[0], "print-bindings") == 0)

examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ CHIP_ERROR CastingApp::Start()
100100
// reconnect (or verify connection) to the CastingPlayer that the app was connected to before being stopped, if any
101101
if (CastingPlayer::GetTargetCastingPlayer() != nullptr)
102102
{
103+
ChipLogProgress(
104+
Discovery,
105+
"CastingApp::Start() calling VerifyOrEstablishConnection() to reconnect (or verify connection) to a CastingPlayer");
103106
CastingPlayer::GetTargetCastingPlayer()->VerifyOrEstablishConnection(
104107
[](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) {
105108
if (err != CHIP_NO_ERROR)

examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp

+51-17
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace core {
3030
CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;
3131

3232
void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec,
33-
EndpointFilter desiredEndpointFilter)
33+
IdentificationDeclarationOptions idOptions)
3434
{
3535
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called");
3636

@@ -46,24 +46,27 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns
4646
ChipLogError(
4747
AppServer,
4848
"CastingPlayer::VerifyOrEstablishConnection() called while already connecting/connected to this CastingPlayer"));
49-
mConnectionState = CASTING_PLAYER_CONNECTING;
50-
mOnCompleted = onCompleted;
51-
mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec;
52-
mTargetCastingPlayer = this;
49+
mConnectionState = CASTING_PLAYER_CONNECTING;
50+
mOnCompleted = onCompleted;
51+
mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec;
52+
mTargetCastingPlayer = this;
53+
mIdOptions = idOptions;
54+
mUdcCommissionerPasscodeEnabled = idOptions.mCommissionerPasscode;
5355

5456
// If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present
5557
// in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any,
56-
// as per desiredEndpointFilter, simply Find or Re-establish the CASE session and return early
58+
// as per IdentificationDeclarationOptions.mTargetAppInfos, simply Find or Re-establish the CASE session and return early.
5759
if (cachedCastingPlayers.size() != 0)
5860
{
61+
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Re-establishing CASE with cached CastingPlayer");
5962
it = std::find_if(cachedCastingPlayers.begin(), cachedCastingPlayers.end(),
6063
[this](const core::CastingPlayer & castingPlayerParam) { return castingPlayerParam == *this; });
6164

6265
// found the CastingPlayer in cache
6366
if (it != cachedCastingPlayers.end())
6467
{
6568
unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it);
66-
if (ContainsDesiredEndpoint(&cachedCastingPlayers[index], desiredEndpointFilter))
69+
if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.mTargetAppInfos, idOptions.mNumTargetAppInfos))
6770
{
6871
ChipLogProgress(
6972
AppServer,
@@ -163,14 +166,39 @@ void CastingPlayer::RegisterEndpoint(const memory::Strong<Endpoint> endpoint)
163166
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
164167
CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest()
165168
{
169+
ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() creating IdentificationDeclaration message");
166170
chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest();
167171
VerifyOrReturnValue(ipAddressToUse != nullptr, CHIP_ERROR_INCORRECT_STATE,
168172
ChipLogError(AppServer, "No IP Address found to send UDC request to"));
169173

170174
ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true));
171175

172-
// TODO: expose options to the higher layer
173176
chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
177+
for (size_t i = 0; i < mIdOptions.mNumTargetAppInfos; i++)
178+
{
179+
id.AddTargetAppInfo(mIdOptions.mTargetAppInfos[i]);
180+
}
181+
id.SetNoPasscode(mIdOptions.mNoPasscode);
182+
id.SetCdUponPasscodeDialog(mIdOptions.mCdUponPasscodeDialog);
183+
id.SetCancelPasscode(mIdOptions.mCancelPasscode);
184+
185+
ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() mUdcCommissionerPasscodeEnabled: %s",
186+
mUdcCommissionerPasscodeEnabled ? "true" : "false");
187+
if (mUdcCommissionerPasscodeEnabled)
188+
{
189+
id.SetCommissionerPasscode(true);
190+
if (mUdcCommissionerPasscodeReady)
191+
{
192+
id.SetCommissionerPasscodeReady(true);
193+
mUdcCommissionerPasscodeReady = false;
194+
}
195+
}
196+
197+
// TODO: In the following PRs. Implement handler for CommissionerDeclaration messages and expose messages to higher layers for
198+
// Linux, Android and iOS.
199+
chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(
200+
mCommissionerDeclarationHandler);
201+
174202
ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest(
175203
chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id));
176204

@@ -216,21 +244,27 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC
216244
connectionContext->mOnConnectionFailureCallback);
217245
}
218246

219-
bool CastingPlayer::ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter)
247+
bool CastingPlayer::ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer,
248+
chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps,
249+
uint8_t numTargetApps)
220250
{
221251
std::vector<memory::Strong<Endpoint>> cachedEndpoints = cachedCastingPlayer->GetEndpoints();
222-
for (const auto & cachedEndpoint : cachedEndpoints)
252+
for (size_t i = 0; i < numTargetApps; i++)
223253
{
224-
bool match = true;
225-
match = match && (desiredEndpointFilter.vendorId == 0 || cachedEndpoint->GetVendorId() == desiredEndpointFilter.vendorId);
226-
match =
227-
match && (desiredEndpointFilter.productId == 0 || cachedEndpoint->GetProductId() == desiredEndpointFilter.productId);
228-
// TODO: check deviceTypeList
229-
if (match)
254+
for (const auto & cachedEndpoint : cachedEndpoints)
230255
{
231-
return true;
256+
bool match = true;
257+
match = match && (desiredTargetApps[i].vendorId == 0 || cachedEndpoint->GetVendorId() == desiredTargetApps[i].vendorId);
258+
match =
259+
match && (desiredTargetApps[i].productId == 0 || cachedEndpoint->GetProductId() == desiredTargetApps[i].productId);
260+
if (match)
261+
{
262+
ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer found");
263+
return true;
264+
}
232265
}
233266
}
267+
ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer not found");
234268
return false;
235269
}
236270

examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h

+88-10
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,65 @@ class CastingPlayerAttributes
6969
chip::FabricIndex fabricIndex = 0;
7070
};
7171

72+
/**
73+
* This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the
74+
* Commissioner. The options specify information relating to the requested UDC commissioning session.
75+
*/
76+
class IdentificationDeclarationOptions
77+
{
78+
public:
79+
constexpr static size_t kMaxTargetAppInfos = 10;
80+
uint8_t mNumTargetAppInfos = 0; // The number of TargetAppInfos included.
81+
/**
82+
* Feature: Target Content Application
83+
* The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication.
84+
* Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the
85+
* desired TargetApp is not found in the on-device CastingStore.
86+
*/
87+
chip::Protocols::UserDirectedCommissioning::TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos];
88+
89+
/**
90+
* Feature: Target Content Application
91+
* Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message
92+
* if a commissioning Passcode is needed.
93+
*/
94+
bool mNoPasscode = false;
95+
/**
96+
* Feature: Coordinate Passcode Dialogs
97+
* Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the
98+
* Commissioner has been shown to the user.
99+
*/
100+
bool mCdUponPasscodeDialog = false;
101+
/**
102+
* Feature: Commissioner-Generated Passcode
103+
* Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning.
104+
*/
105+
bool mCommissionerPasscode = false;
106+
/**
107+
* Feature: Commissioner-Generated Passcode
108+
* Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready
109+
* for commissioning.
110+
*/
111+
bool mCommissionerPasscodeReady = false;
112+
/**
113+
* Feature: Coordinate Passcode Dialogs
114+
* Flag to indicate when the Commissionee user has decided to exit the commissioning process.
115+
*/
116+
bool mCancelPasscode = false;
117+
};
118+
119+
// TODO: In the following PRs. This is work in progress. Break out to a seperate cpp file.
120+
class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler
121+
{
122+
public:
123+
void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source,
124+
chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override
125+
{
126+
ChipLogProgress(AppServer, "CastingPlayer::CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called");
127+
cd.DebugLog();
128+
}
129+
};
130+
72131
class Endpoint;
73132

74133
/**
@@ -93,7 +152,11 @@ using ConnectCallback = std::function<void(CHIP_ERROR, CastingPlayer *)>;
93152
class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
94153
{
95154
public:
96-
CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; }
155+
CastingPlayer(CastingPlayerAttributes playerAttributes)
156+
{
157+
mAttributes = playerAttributes;
158+
mCommissionerDeclarationHandler = new CommissionerDeclarationHandler();
159+
}
97160

98161
/**
99162
* @brief Get the CastingPlayer object targeted currently (may not be connected)
@@ -123,13 +186,15 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
123186
* For failure - called back with an error and nullptr.
124187
* @param commissioningWindowTimeoutSec (Optional) time (in sec) to keep the commissioning window open, if commissioning is
125188
* required. Needs to be >= kCommissioningWindowTimeoutSec.
126-
* @param desiredEndpointFilter (Optional) Attributes (such as VendorId) describing an Endpoint that the client wants to
127-
* interact with after commissioning. If this value is passed in, the VerifyOrEstablishConnection will force User Directed
128-
* Commissioning, in case the desired Endpoint is not found in the on device CastingStore.
189+
* @param idOptions (Optional) Parameters in the IdentificationDeclaration message sent by the Commissionee to the Commissioner.
190+
* These parameters specify the information relating to the requested commissioning session.
191+
* Furthermore, attributes (such as VendorId) describe the TargetApp that the client wants to interact with after commissioning.
192+
* If this value is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the desired
193+
* TargetApp is not found in the on-device CastingStore.
129194
*/
130195
void VerifyOrEstablishConnection(ConnectCallback onCompleted,
131196
unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec,
132-
EndpointFilter desiredEndpointFilter = EndpointFilter());
197+
IdentificationDeclarationOptions idOptions = IdentificationDeclarationOptions());
133198

134199
/**
135200
* @brief Sets the internal connection state of this CastingPlayer to "disconnected"
@@ -197,6 +262,17 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
197262
std::vector<memory::Strong<Endpoint>> mEndpoints;
198263
ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
199264
CastingPlayerAttributes mAttributes;
265+
IdentificationDeclarationOptions mIdOptions;
266+
/**
267+
* Flag to indicate whether or not the Commissionee (tv-casting-app) is enabled for the Commissioner-Generated Passcode flow.
268+
*/
269+
bool mUdcCommissionerPasscodeEnabled = false;
270+
/**
271+
* Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready
272+
* for commissioning.
273+
*/
274+
bool mUdcCommissionerPasscodeReady = false;
275+
CommissionerDeclarationHandler * mCommissionerDeclarationHandler;
200276
static CastingPlayer * mTargetCastingPlayer;
201277
unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec;
202278
ConnectCallback mOnCompleted = {};
@@ -217,12 +293,14 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
217293
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
218294

219295
/**
220-
* @brief Checks if the cachedCastingPlayer contains an Endpoint that matches the description of the desiredEndpointFilter
221-
*
222-
* @return true - cachedCastingPlayer contains at least one endpoint that matches all the (non-default) values in
223-
* desiredEndpointFilter, false otherwise
296+
* @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list.
297+
* @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values as described in the
298+
* desiredTargetApps list, false otherwise.
299+
* @param numTargetApps Specifies the number of TargetAppInfos passed in the desiredTargetApps array.
224300
*/
225-
bool ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter);
301+
bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer,
302+
chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps,
303+
uint8_t numTargetApps);
226304

227305
// ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with
228306
// and connect to a CastingPlayer

0 commit comments

Comments
 (0)