Skip to content

Commit 1941919

Browse files
sharadb-amazonpull[bot]
authored andcommitted
Linux tv-casting-app: simplified CastingPlayer.VerifyOrEstablishConnection API
1 parent 13f7924 commit 1941919

16 files changed

+1466
-131
lines changed

examples/tv-casting-app/APIs.md

+33-2
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ func initialize() -> MatterError {
405405

406406
### Discover Casting Players
407407

408-
_{Complete Discovery examples: [Linux](linux/simple-app.cpp)}_
408+
_{Complete Discovery examples: [Linux](linux/simple-app-helper.cpp)}_
409409

410410
The Casting Client discovers `CastingPlayers` using Matter Commissioner
411411
discovery over DNS-SD by listening for `CastingPlayer` events as they are
@@ -444,12 +444,14 @@ singleton instance. Then, call `StartDiscovery` by optionally specifying the
444444
`kTargetPlayerDeviceType` to filter results by.
445445

446446
```c
447+
const uint64_t kTargetPlayerDeviceType = 35; // 35 represents device type of Matter Video Player
448+
...
449+
...
447450
DiscoveryDelegateImpl delegate;
448451
CastingPlayerDiscovery::GetInstance()->SetDelegate(&delegate);
449452
VerifyOrReturnValue(err == CHIP_NO_ERROR, 0,
450453
ChipLogError(AppServer, "CastingPlayerDiscovery::SetDelegate failed %" CHIP_ERROR_FORMAT, err.Format()));
451454

452-
const uint64_t kTargetPlayerDeviceType = 35; // 35 represents device type of Matter Video Player
453455
err = CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
454456
VerifyOrReturnValue(err == CHIP_NO_ERROR, 0,
455457
ChipLogError(AppServer, "CastingPlayerDiscovery::StartDiscovery failed %" CHIP_ERROR_FORMAT, err.Format()));
@@ -459,6 +461,35 @@ chip::DeviceLayer::PlatformMgr().RunEventLoop();
459461

460462
### Connect to a Casting Player
461463

464+
_{Complete Connection examples: [Linux](linux/simple-app-helper.cpp)}_
465+
466+
Each `CastingPlayer` object created during
467+
[Discovery](#discover-casting-players) contains information such as
468+
`deviceName`, `vendorId`, `productId`, etc. which can help the user pick the
469+
right `CastingPlayer`. A Casting Client can attempt to connect to the
470+
`selectedCastingPlayer` using
471+
[Matter User Directed Commissioning (UDC)](https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/rendezvous/UserDirectedCommissioning.adoc).
472+
The Matter TV Casting library locally caches information required to reconnect
473+
to a `CastingPlayer`, once the Casting client has been commissioned by it. After
474+
that, the Casting client is able to skip the full UDC process by establishing
475+
CASE with the `CastingPlayer` directly. Once connected, the `CastingPlayer`
476+
object will contain the list of available Endpoints on that `CastingPlayer`.
477+
478+
On Linux, the Casting Client can connect to a `CastingPlayer` by successfully
479+
calling `VerifyOrEstablishConnection` on it.
480+
481+
```c
482+
void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer)
483+
{
484+
ChipLogProgress(AppServer, "ConnectionHandler called with %" CHIP_ERROR_FORMAT, err.Format());
485+
}
486+
487+
...
488+
// targetCastingPlayer is a discovered CastingPlayer
489+
targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler);
490+
...
491+
```
492+
462493
### Select an Endpoint on the Casting Player
463494

464495
## Interacting with a Casting Endpoint

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
#include "../JNIDACProvider.h"
2222
#include "../support/ErrorConverter-JNI.h"
2323
#include "../support/RotatingDeviceIdUniqueIdProvider-JNI.h"
24-
#include "core/CastingApp.h" // from tv-casting-common
24+
25+
// from tv-casting-common
26+
#include "core/CastingApp.h"
27+
#include "support/ChipDeviceEventHandler.h"
2528

2629
#include <app/clusters/bindings/BindingManager.h>
2730
#include <app/server/Server.h>
@@ -79,20 +82,25 @@ JNI_METHOD(jobject, finishStartup)(JNIEnv *, jobject)
7982
{
8083
chip::DeviceLayer::StackLock lock;
8184
ChipLogProgress(AppServer, "JNI_METHOD CastingAppJNI.finishStartup called");
82-
auto & server = chip::Server::GetInstance();
85+
86+
CHIP_ERROR err = CHIP_NO_ERROR;
87+
auto & server = chip::Server::GetInstance();
8388

8489
// TODO: Set AppDelegate
8590
// &server.GetCommissioningWindowManager().SetAppDelegate(??);
8691

8792
// Initialize binding handlers
88-
chip::BindingManager::GetInstance().Init(
93+
err = chip::BindingManager::GetInstance().Init(
8994
{ &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() });
95+
VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(err),
96+
ChipLogError(AppServer, "Failed to init BindingManager %" CHIP_ERROR_FORMAT, err.Format()));
9097

9198
// TODO: Set FabricDelegate
9299
// chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&mPersistenceManager);
93100

94-
// TODO: Add DeviceEvent Handler
95-
// ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(DeviceEventCallback, 0));
101+
err = chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(support::ChipDeviceEventHandler::Handle, 0);
102+
VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(err),
103+
ChipLogError(AppServer, "Failed to register ChipDeviceEventHandler %" CHIP_ERROR_FORMAT, err.Format()));
96104

97105
return support::createJMatterError(CHIP_NO_ERROR);
98106
}

examples/tv-casting-app/linux/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ executable("chip-tv-casting-app") {
2727
if (chip_casting_simplified) {
2828
sources = [
2929
"${chip_root}/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h",
30+
"simple-app-helper.cpp",
31+
"simple-app-helper.h",
3032
"simple-app.cpp",
3133
]
3234
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#include "simple-app-helper.h"
18+
19+
#include "app/clusters/bindings/BindingManager.h"
20+
#include <inttypes.h>
21+
#include <lib/core/CHIPCore.h>
22+
#include <lib/shell/Commands.h>
23+
#include <lib/shell/Engine.h>
24+
#include <lib/shell/commands/Help.h>
25+
#include <lib/support/CHIPArgParser.hpp>
26+
#include <lib/support/CHIPMem.h>
27+
#include <lib/support/CodeUtils.h>
28+
#include <platform/CHIPDeviceLayer.h>
29+
30+
DiscoveryDelegateImpl * DiscoveryDelegateImpl::_discoveryDelegateImpl = nullptr;
31+
32+
DiscoveryDelegateImpl * DiscoveryDelegateImpl::GetInstance()
33+
{
34+
if (_discoveryDelegateImpl == nullptr)
35+
{
36+
_discoveryDelegateImpl = new DiscoveryDelegateImpl();
37+
}
38+
return _discoveryDelegateImpl;
39+
}
40+
41+
void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player)
42+
{
43+
if (commissionersCount == 0)
44+
{
45+
ChipLogProgress(AppServer, "Select discovered Casting Player (start index = 0) to request commissioning");
46+
47+
ChipLogProgress(AppServer, "Example: cast request 0");
48+
}
49+
ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount);
50+
++commissionersCount;
51+
player->LogDetail();
52+
}
53+
54+
void DiscoveryDelegateImpl::HandleOnUpdated(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player)
55+
{
56+
ChipLogProgress(AppServer, "Updated CastingPlayer with ID: %s", player->GetId());
57+
}
58+
59+
void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer)
60+
{
61+
ChipLogProgress(AppServer, "ConnectionHandler called with %" CHIP_ERROR_FORMAT, err.Format());
62+
}
63+
64+
#if defined(ENABLE_CHIP_SHELL)
65+
void RegisterCommands()
66+
{
67+
static const chip::Shell::shell_command_t sDeviceComand = { &CommandHandler, "cast",
68+
"Casting commands. Usage: cast [command_name]" };
69+
70+
// Register the root `device` command with the top-level shell.
71+
chip::Shell::Engine::Root().RegisterCommands(&sDeviceComand, 1);
72+
}
73+
74+
CHIP_ERROR CommandHandler(int argc, char ** argv)
75+
{
76+
if (argc == 0 || strcmp(argv[0], "help") == 0)
77+
{
78+
return PrintAllCommands();
79+
}
80+
if (strcmp(argv[0], "discover") == 0)
81+
{
82+
ChipLogProgress(AppServer, "discover");
83+
84+
return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
85+
}
86+
if (strcmp(argv[0], "stop-discovery") == 0)
87+
{
88+
ChipLogProgress(AppServer, "stop-discovery");
89+
return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery();
90+
}
91+
if (strcmp(argv[0], "request") == 0)
92+
{
93+
ChipLogProgress(AppServer, "request");
94+
if (argc < 2)
95+
{
96+
return PrintAllCommands();
97+
}
98+
char * eptr;
99+
unsigned long index = static_cast<unsigned long>(strtol(argv[1], &eptr, 10));
100+
std::vector<matter::casting::memory::Strong<matter::casting::core::CastingPlayer>> castingPlayers =
101+
matter::casting::core::CastingPlayerDiscovery::GetInstance()->GetCastingPlayers();
102+
VerifyOrReturnValue(0 <= index && index < castingPlayers.size(), CHIP_ERROR_INVALID_ARGUMENT,
103+
ChipLogError(AppServer, "Invalid casting player index provided: %lu", index));
104+
std::shared_ptr<matter::casting::core::CastingPlayer> targetCastingPlayer = castingPlayers.at(index);
105+
targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler);
106+
return CHIP_NO_ERROR;
107+
}
108+
if (strcmp(argv[0], "print-bindings") == 0)
109+
{
110+
PrintBindings();
111+
return CHIP_NO_ERROR;
112+
}
113+
if (strcmp(argv[0], "print-fabrics") == 0)
114+
{
115+
PrintFabrics();
116+
return CHIP_NO_ERROR;
117+
}
118+
if (strcmp(argv[0], "delete-fabric") == 0)
119+
{
120+
char * eptr;
121+
chip::FabricIndex fabricIndex = (chip::FabricIndex) strtol(argv[1], &eptr, 10);
122+
chip::Server::GetInstance().GetFabricTable().Delete(fabricIndex);
123+
return CHIP_NO_ERROR;
124+
}
125+
return CHIP_ERROR_INVALID_ARGUMENT;
126+
}
127+
128+
CHIP_ERROR PrintAllCommands()
129+
{
130+
chip::Shell::streamer_t * sout = chip::Shell::streamer_get();
131+
streamer_printf(sout, " help Usage: cast <subcommand>\r\n");
132+
streamer_printf(sout, " print-bindings Usage: cast print-bindings\r\n");
133+
streamer_printf(sout, " print-fabrics Usage: cast print-fabrics\r\n");
134+
streamer_printf(
135+
sout,
136+
" delete-fabric <index> Delete a fabric from the casting client's fabric store. Usage: cast delete-fabric 1\r\n");
137+
streamer_printf(sout, " discover Discover Casting Players. Usage: cast discover\r\n");
138+
streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n");
139+
streamer_printf(
140+
sout, " request <index> Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n");
141+
streamer_printf(sout, "\r\n");
142+
143+
return CHIP_NO_ERROR;
144+
}
145+
146+
void PrintBindings()
147+
{
148+
for (const auto & binding : chip::BindingTable::GetInstance())
149+
{
150+
ChipLogProgress(AppServer,
151+
"Binding type=%d fab=%d nodeId=0x" ChipLogFormatX64
152+
" groupId=%d local endpoint=%d remote endpoint=%d cluster=" ChipLogFormatMEI,
153+
binding.type, binding.fabricIndex, ChipLogValueX64(binding.nodeId), binding.groupId, binding.local,
154+
binding.remote, ChipLogValueMEI(binding.clusterId.ValueOr(0)));
155+
}
156+
}
157+
158+
void PrintFabrics()
159+
{
160+
// set fabric to be the first in the list
161+
for (const auto & fb : chip::Server::GetInstance().GetFabricTable())
162+
{
163+
chip::FabricIndex fabricIndex = fb.GetFabricIndex();
164+
ChipLogError(AppServer, "Next Fabric index=%d", fabricIndex);
165+
if (!fb.IsInitialized())
166+
{
167+
ChipLogError(AppServer, " -- Not initialized");
168+
continue;
169+
}
170+
chip::NodeId myNodeId = fb.GetNodeId();
171+
ChipLogProgress(AppServer,
172+
"---- Current Fabric nodeId=0x" ChipLogFormatX64 " fabricId=0x" ChipLogFormatX64 " fabricIndex=%d",
173+
ChipLogValueX64(myNodeId), ChipLogValueX64(fb.GetFabricId()), fabricIndex);
174+
}
175+
}
176+
177+
#endif // ENABLE_CHIP_SHELL
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include "core/CastingPlayer.h"
22+
#include "core/CastingPlayerDiscovery.h"
23+
#include "core/Types.h"
24+
25+
#include <platform/CHIPDeviceLayer.h>
26+
27+
/**
28+
* @brief Matter deviceType that the Linux tv-casting-app will discover over Commissionable Node discovery (DNS-SD)
29+
*
30+
* 35 represents device type of Matter Video Player
31+
*/
32+
const uint64_t kTargetPlayerDeviceType = 35;
33+
34+
/**
35+
* @brief Singleton that reacts to CastingPlayer discovery results
36+
*/
37+
class DiscoveryDelegateImpl : public matter::casting::core::DiscoveryDelegate
38+
{
39+
private:
40+
DiscoveryDelegateImpl(){};
41+
static DiscoveryDelegateImpl * _discoveryDelegateImpl;
42+
int commissionersCount = 0;
43+
44+
public:
45+
static DiscoveryDelegateImpl * GetInstance();
46+
47+
/**
48+
* @brief Called when a new CastingPlayer is discovered
49+
*
50+
* @param player the discovered CastingPlayer
51+
*/
52+
void HandleOnAdded(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player) override;
53+
54+
/**
55+
* @brief Called when there are updates to the Attributes of a previously discovered CastingPlayer
56+
*
57+
* @param player the updated CastingPlayer
58+
*/
59+
void HandleOnUpdated(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player) override;
60+
};
61+
62+
/**
63+
* @brief Linux tv-casting-app's onCompleted handler for CastingPlayer.VerifyOrEstablishConnection API
64+
*/
65+
void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer);
66+
67+
#if defined(ENABLE_CHIP_SHELL)
68+
/**
69+
* @brief Register CHIP Shell commands for the Linux tv-casting-app CLI
70+
*/
71+
void RegisterCommands();
72+
73+
/**
74+
* @brief Top level handler that parses text entered on the Linux tv-casting-app CLI and invokes the appropriate handler
75+
*/
76+
CHIP_ERROR CommandHandler(int argc, char ** argv);
77+
78+
/**
79+
* @brief Prints all the commands available on the Linux tv-casting-app CLI
80+
*/
81+
CHIP_ERROR PrintAllCommands();
82+
83+
/**
84+
* @brief Implements the "print-bindings" command
85+
*/
86+
void PrintBindings();
87+
88+
/**
89+
* @brief Implements the "print-fabrics" command
90+
*/
91+
void PrintFabrics();
92+
#endif

0 commit comments

Comments
 (0)