Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux tv-casting-app v1.3 IdentificationDeclaration message #33283

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,9 @@ public View getView(int i, View view, ViewGroup viewGroup) {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,14 @@ JNI_METHOD(jobject, verifyOrEstablishConnection)
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;");
Expand All @@ -66,20 +71,28 @@ JNI_METHOD(jobject, verifyOrEstablishConnection)
// "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");
Expand All @@ -96,7 +109,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection)
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,29 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError

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);
});
}

Expand Down
60 changes: 49 additions & 11 deletions examples/tv-casting-app/linux/simple-app-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong<matter
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;
Expand Down Expand Up @@ -170,10 +172,12 @@ void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * ca
{
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
Expand Down Expand Up @@ -219,18 +223,18 @@ CHIP_ERROR CommandHandler(int argc, char ** argv)
}
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();
Expand All @@ -243,10 +247,40 @@ CHIP_ERROR CommandHandler(int argc, char ** argv)
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)
Expand Down Expand Up @@ -280,8 +314,12 @@ CHIP_ERROR PrintAllCommands()
" 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;
Expand Down
1 change: 1 addition & 0 deletions examples/tv-casting-app/linux/simple-app-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "core/CastingPlayer.h"
#include "core/CastingPlayerDiscovery.h"
#include "core/IdentificationDeclarationOptions.h"
#include "core/Types.h"
#include <platform/CHIPDeviceLayer.h>

Expand Down
1 change: 1 addition & 0 deletions examples/tv-casting-app/tv-casting-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ chip_data_model("tv-casting-common") {
"core/CastingPlayerDiscovery.cpp",
"core/CastingPlayerDiscovery.h",
"core/Command.h",
"core/CommissionerDeclarationHandler.cpp",
"core/Endpoint.cpp",
"core/Endpoint.h",
"core/Types.h",
Expand Down
11 changes: 11 additions & 0 deletions examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "CastingApp.h"

#include "CommissionerDeclarationHandler.h"
#include "support/CastingStore.h"
#include "support/ChipDeviceEventHandler.h"

Expand Down Expand Up @@ -100,6 +101,9 @@ CHIP_ERROR CastingApp::Start()
// 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)
Expand Down Expand Up @@ -136,6 +140,10 @@ CHIP_ERROR CastingApp::PostStartRegistrations()
// Register DeviceEvent Handler
ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0));

// Set a handler for Commissioner's CommissionerDeclaration messages.
chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(
CommissionerDeclarationHandler::GetInstance());

mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING
return CHIP_NO_ERROR;
}
Expand All @@ -145,6 +153,9 @@ CHIP_ERROR CastingApp::Stop()
ChipLogProgress(Discovery, "CastingApp::Stop() called");
VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE);

// Remove the handler previously set for Commissioner's CommissionerDeclaration messages.
chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr);

// Shutdown the Matter server
chip::Server::GetInstance().Shutdown();

Expand Down
37 changes: 23 additions & 14 deletions examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace core {
CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;

void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec,
EndpointFilter desiredEndpointFilter)
IdentificationDeclarationOptions idOptions)
{
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called");

Expand All @@ -50,20 +50,22 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns
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; });

// found the CastingPlayer in cache
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,
Expand Down Expand Up @@ -163,14 +165,15 @@ void CastingPlayer::RegisterEndpoint(const memory::Strong<Endpoint> endpoint)
#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));

Expand Down Expand Up @@ -216,21 +219,27 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC
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;
}

Expand Down
Loading
Loading