Skip to content

Commit 7614353

Browse files
Linux tv-casting-app: simplified Endpoints APIs
1 parent b3ef405 commit 7614353

File tree

11 files changed

+612
-34
lines changed

11 files changed

+612
-34
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,24 @@ chip_data_model("tv-casting-common") {
9393

9494
# Add simplified casting API files here
9595
sources += [
96+
#"core/Attribute.h",
9697
"core/CastingApp.cpp",
9798
"core/CastingApp.h",
9899
"core/CastingPlayer.cpp",
99100
"core/CastingPlayer.h",
100101
"core/CastingPlayerDiscovery.cpp",
101102
"core/CastingPlayerDiscovery.h",
103+
"core/Cluster.h",
104+
"core/Endpoint.h",
102105
"core/Types.h",
103106
"support/AppParameters.h",
104107
"support/CastingStore.cpp",
105108
"support/CastingStore.h",
106109
"support/ChipDeviceEventHandler.cpp",
107110
"support/ChipDeviceEventHandler.h",
108111
"support/DataProvider.h",
112+
"support/EndpointListLoader.cpp",
113+
"support/EndpointListLoader.h",
109114
]
110115

111116
deps = [
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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 "Cluster.h"
22+
#include "Types.h"
23+
24+
#include "lib/support/logging/CHIPLogging.h"
25+
26+
namespace matter {
27+
namespace casting {
28+
namespace core {
29+
30+
enum ReadAttributeError
31+
{
32+
READ_ATTRIBUTE_NO_ERROR
33+
};
34+
35+
enum WriteAttributeError
36+
{
37+
WRITE_ATTRIBUTE_NO_ERROR
38+
};
39+
40+
template <typename ValueType>
41+
using ReadAttributeCallback = std::function<void(Optional<ValueType> before, ValueType after, ReadAttributeError)>;
42+
43+
using WriteAttributeCallback = std::function<void(WriteAttributeError)>;
44+
45+
class BaseCluster;
46+
47+
template <typename ValueType>
48+
class Attribute
49+
{
50+
private:
51+
memory::Weak<BaseCluster> cluster;
52+
ValueType value;
53+
54+
public:
55+
Attribute(memory::Weak<BaseCluster> cluster) { this->cluster = cluster; }
56+
57+
~Attribute() {}
58+
59+
Attribute() = delete;
60+
Attribute(Attribute & other) = delete;
61+
void operator=(const Attribute &) = delete;
62+
63+
protected:
64+
memory::Strong<BaseCluster> GetCluster() const { return cluster.lock(); }
65+
66+
public:
67+
ValueType GetValue();
68+
void Read(ReadAttributeCallback<ValueType> onRead);
69+
void Write(ValueType value, WriteAttributeCallback onWrite);
70+
bool SubscribeAttribute(AttributeId attributeId, ReadAttributeCallback<ValueType> callback);
71+
bool UnsubscribeAttribute(AttributeId attributeId, ReadAttributeCallback<ValueType> callback);
72+
};
73+
74+
}; // namespace core
75+
}; // namespace casting
76+
}; // namespace matter

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

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818

1919
#include "CastingPlayer.h"
20+
#include "Endpoint.h"
21+
2022
#include "support/CastingStore.h"
2123

2224
#include <app/server/Server.h>
@@ -27,7 +29,8 @@ namespace core {
2729

2830
CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;
2931

30-
void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec)
32+
void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec,
33+
EndpointFilter * desiredEndpointFilter)
3134
{
3235
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection called");
3336

@@ -46,40 +49,48 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns
4649
mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec;
4750
mTargetCastingPlayer = this;
4851

49-
// If this CastingPlayer is the cache of CastingPlayers the app previously connected to (and has nodeId and fabricIndex of),
50-
// simply Find or Re-establish the CASE session and return early
52+
// If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present
53+
// in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any,
54+
// as per desiredEndpointFilter, simply Find or Re-establish the CASE session and return early
5155
if (cachedCastingPlayers.size() != 0)
5256
{
5357
it = std::find_if(cachedCastingPlayers.begin(), cachedCastingPlayers.end(),
5458
[this](const core::CastingPlayer & castingPlayerParam) { return castingPlayerParam == *this; });
5559

60+
// found the CastingPlayer in cache
5661
if (it != cachedCastingPlayers.end())
5762
{
5863
unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it);
59-
*this = cachedCastingPlayers[index];
60-
61-
FindOrEstablishSession(
62-
nullptr,
63-
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
64-
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection Connection to CastingPlayer successful");
65-
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_CONNECTED;
66-
support::CastingStore::GetInstance()->AddOrUpdate(*CastingPlayer::GetTargetCastingPlayer());
67-
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
68-
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_NO_ERROR, CastingPlayer::GetTargetCastingPlayer());
69-
},
70-
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
71-
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection Connection to CastingPlayer failed");
72-
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
73-
support::CastingStore::GetInstance()->Delete(*CastingPlayer::GetTargetCastingPlayer());
74-
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
75-
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(error, nullptr);
76-
mTargetCastingPlayer = nullptr;
77-
});
78-
return; // FindOrEstablishSession called. Return early.
64+
if (desiredEndpointFilter == nullptr || ContainsDesiredEndpoint(&cachedCastingPlayers[index], desiredEndpointFilter))
65+
{
66+
*this = cachedCastingPlayers[index];
67+
68+
FindOrEstablishSession(
69+
nullptr,
70+
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
71+
ChipLogProgress(AppServer,
72+
"CastingPlayer::VerifyOrEstablishConnection Connection to CastingPlayer successful");
73+
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_CONNECTED;
74+
support::CastingStore::GetInstance()->AddOrUpdate(*CastingPlayer::GetTargetCastingPlayer());
75+
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
76+
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_NO_ERROR,
77+
CastingPlayer::GetTargetCastingPlayer());
78+
},
79+
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
80+
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection Connection to CastingPlayer failed");
81+
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
82+
support::CastingStore::GetInstance()->Delete(*CastingPlayer::GetTargetCastingPlayer());
83+
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
84+
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(error, nullptr);
85+
mTargetCastingPlayer = nullptr;
86+
});
87+
return; // FindOrEstablishSession called. Return early.
88+
}
7989
}
8090
}
8191

82-
// this CastingPlayer is not in the list of cached CastingPlayers previously connected to. This VerifyOrEstablishConnection call
92+
// this CastingPlayer is not in the list of cached CastingPlayers previously connected to or the cached data
93+
// does not contain the endpoint the client desires to interact with. So, this VerifyOrEstablishConnection call
8394
// will require User Directed Commissioning.
8495
if (chip::Server::GetInstance().GetFailSafeContext().IsFailSafeArmed())
8596
{
@@ -101,13 +112,13 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns
101112
exit:
102113
if (err != CHIP_NO_ERROR)
103114
{
115+
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection failed with %" CHIP_ERROR_FORMAT, err.Format());
104116
support::ChipDeviceEventHandler::SetUdcStatus(false);
105117
mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
106118
mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec;
107-
mOnCompleted = nullptr;
108119
mTargetCastingPlayer = nullptr;
109-
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection failed with %" CHIP_ERROR_FORMAT, err.Format());
110120
mOnCompleted(err, nullptr);
121+
mOnCompleted = nullptr;
111122
}
112123
}
113124

@@ -165,6 +176,24 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC
165176
connectionContext->mOnConnectionFailureCallback);
166177
}
167178

179+
bool CastingPlayer::ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter * desiredEndpointFilter)
180+
{
181+
std::vector<memory::Strong<Endpoint>> cachedEndpoints = cachedCastingPlayer->GetEndpoints();
182+
for (const auto & cachedEndpoint : cachedEndpoints)
183+
{
184+
bool match = true;
185+
match = match && (desiredEndpointFilter->vendorId == 0 || cachedEndpoint->GetVendorId() == desiredEndpointFilter->vendorId);
186+
match =
187+
match && (desiredEndpointFilter->productId == 0 || cachedEndpoint->GetProductId() == desiredEndpointFilter->productId);
188+
// TODO: check deviceTypeList and clusterList as well
189+
if (match)
190+
{
191+
return true;
192+
}
193+
}
194+
return false;
195+
}
196+
168197
void CastingPlayer::LogDetail() const
169198
{
170199
if (strlen(mAttributes.id) != 0)

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
#pragma once
2020

21+
#include "Endpoint.h"
2122
#include "Types.h"
2223
#include "support/ChipDeviceEventHandler.h"
24+
#include "support/EndpointListLoader.h"
2325

2426
#include "lib/support/logging/CHIPLogging.h"
2527
#include <inet/IPAddress.h>
@@ -36,6 +38,13 @@ const int kPortMaxLength = 5; // port is uint16_t
3638
const int kIdMaxLength = chip::Dnssd::kHostNameMaxLength + kPortMaxLength + 1;
3739
const unsigned long long int kCommissioningWindowTimeoutSec = 3 * 60; // 3 minutes
3840

41+
struct EndpointFilter
42+
{
43+
uint16_t vendorId = 0;
44+
uint16_t productId = 0;
45+
std::vector<chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::DecodableType> deviceTypeList;
46+
};
47+
3948
class CastingPlayerAttributes
4049
{
4150
public:
@@ -55,6 +64,8 @@ class CastingPlayerAttributes
5564
chip::FabricIndex fabricIndex = 0;
5665
};
5766

67+
class Endpoint;
68+
5869
/**
5970
* @brief Represents CastingPlayer ConnectionState.
6071
*
@@ -109,7 +120,8 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
109120
* Defaults to kCommissioningWindowTimeoutSec.
110121
*/
111122
void VerifyOrEstablishConnection(ConnectCallback onCompleted,
112-
unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec);
123+
unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec,
124+
EndpointFilter * desiredEndpointFilter = nullptr);
113125
void LogDetail() const;
114126

115127
const char * GetId() const { return mAttributes.id; }
@@ -140,12 +152,12 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
140152

141153
void SetFabricIndex(chip::FabricIndex fabricIndex) { mAttributes.fabricIndex = fabricIndex; }
142154

143-
// void RegisterEndpoint(const memory::Strong<Endpoint> endpoint) { endpoints.push_back(endpoint); }
155+
void RegisterEndpoint(const memory::Strong<Endpoint> endpoint) { endpoints.push_back(endpoint); }
144156

145-
// const std::vector<memory::Strong<Endpoint>> GetEndpoints() const { return endpoints; }
157+
const std::vector<memory::Strong<Endpoint>> GetEndpoints() const { return endpoints; }
146158

147159
private:
148-
// std::vector<memory::Strong<Endpoint>> endpoints;
160+
std::vector<memory::Strong<Endpoint>> endpoints;
149161
ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
150162
CastingPlayerAttributes mAttributes;
151163
static CastingPlayer * mTargetCastingPlayer;
@@ -184,10 +196,13 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
184196
void FindOrEstablishSession(void * clientContext, chip::OnDeviceConnected onDeviceConnected,
185197
chip::OnDeviceConnectionFailure onDeviceConnectionFailure);
186198

199+
bool ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter * desiredEndpointFilter);
200+
187201
// ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with
188202
// and connect to a CastingPlayer
189203
friend class support::ChipDeviceEventHandler;
190204
friend class ConnectionContext;
205+
friend class support::EndpointListLoader;
191206
};
192207

193208
class ConnectionContext
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 "Endpoint.h"
22+
#include "Types.h"
23+
24+
#include "lib/support/logging/CHIPLogging.h"
25+
26+
namespace matter {
27+
namespace casting {
28+
namespace core {
29+
30+
class Endpoint;
31+
32+
// Base cluster class
33+
class BaseCluster
34+
{
35+
private:
36+
protected:
37+
memory::Weak<Endpoint> endpoint;
38+
39+
public:
40+
BaseCluster(memory::Weak<Endpoint> endpoint) { this->endpoint = endpoint; }
41+
42+
virtual ~BaseCluster() {}
43+
44+
BaseCluster() = delete;
45+
BaseCluster(BaseCluster & other) = delete;
46+
void operator=(const BaseCluster &) = delete;
47+
48+
protected:
49+
memory::Weak<Endpoint> GetEndpoint() const { return endpoint.lock(); }
50+
};
51+
52+
}; // namespace core
53+
}; // namespace casting
54+
}; // namespace matter

0 commit comments

Comments
 (0)