Skip to content

Commit 79c2dbd

Browse files
sayondeepesp
authored and
esp
committed
initial implementation of pushav server
1 parent a5971fa commit 79c2dbd

File tree

6 files changed

+668
-37
lines changed

6 files changed

+668
-37
lines changed

src/app/chip_data_model.gni

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,11 @@ template("chip_data_model") {
456456
"${_app_root}/clusters/${cluster}/ArlEncoder.cpp",
457457
"${_app_root}/clusters/${cluster}/ArlEncoder.h",
458458
]
459+
} else if (cluster == "push-av-stream-transport-server") {
460+
sources += [
461+
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
462+
"${_app_root}/clusters/${cluster}/${cluster}.h",
463+
]
459464
} else {
460465
sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ]
461466
}
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
/**
2+
*
3+
* Copyright (c) 2025 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+
*/
18+
19+
#include <app/AttributeAccessInterface.h>
20+
#include <app/AttributeAccessInterfaceRegistry.h>
21+
#include <app/CommandHandlerInterfaceRegistry.h>
22+
#include <app/InteractionModelEngine.h>
23+
#include <app/clusters/push-av-stream-transport-server/push-av-stream-transport-server.h>
24+
#include <app/reporting/reporting.h>
25+
#include <app/util/attribute-storage.h>
26+
#include <app/util/util.h>
27+
#include <lib/core/CHIPSafeCasts.h>
28+
#include <lib/support/DefaultStorageKeyAllocator.h>
29+
#include <protocols/interaction_model/StatusCode.h>
30+
31+
#define MAX_PUSH_TRANSPORT_CONNECTION_ID 65535
32+
33+
using namespace chip;
34+
using namespace chip::app;
35+
using namespace chip::app::Clusters;
36+
using namespace chip::app::Clusters::PushAvStreamTransport;
37+
using namespace chip::app::Clusters::PushAvStreamTransport::Structs;
38+
using namespace chip::app::Clusters::PushAvStreamTransport::Attributes;
39+
using namespace Protocols::InteractionModel;
40+
41+
namespace chip {
42+
namespace app {
43+
namespace Clusters {
44+
namespace PushAvStreamTransport {
45+
46+
PushAvStreamTransportServer::PushAvStreamTransportServer(EndpointId aEndpointId, PushAvStreamTransportDelegate & aDelegate,
47+
const BitFlags<Feature> aFeature,
48+
PersistentStorageDelegate & aPersistentStorage) :
49+
CommandHandlerInterface(MakeOptional(aEndpointId), CameraAvStreamManagement::Id),
50+
AttributeAccessInterface(MakeOptional(aEndpointId), CameraAvStreamManagement::Id), mDelegate(aDelegate),
51+
mEndpointId(aEndpointId), mFeature(aFeature)
52+
{
53+
mDelegate.SetPushAvStreamTransportServer(this);
54+
}
55+
56+
PushAvStreamTransportServer::~PushAvStreamTransportServer()
57+
{
58+
// Explicitly set the PushAvStreamTransportServer pointer in the Delegate to null.
59+
60+
mDelegate.SetPushAvStreamTransportServer(nullptr);
61+
62+
// Unregister command handler and attribute access interfaces
63+
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
64+
AttributeAccessInterfaceRegistry::Instance().Unregister(this);
65+
}
66+
67+
CHIP_ERROR PushAvStreamTransportServer::Init()
68+
{
69+
LoadPersistentAttributes();
70+
71+
VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL);
72+
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
73+
return CHIP_NO_ERROR;
74+
}
75+
76+
bool PushAvStreamTransportServer::HasFeature(Feature feature) const
77+
{
78+
return mFeature.Has(feature);
79+
}
80+
81+
CHIP_ERROR PushAvStreamTransportServer::ReadAndEncodeCurrentConnections(const AttributeValueEncoder::ListEncodeHelper & encoder)
82+
{
83+
for (const auto & currentConnections : mCurrentConnections)
84+
{
85+
ReturnErrorOnFailure(encoder.Encode(currentConnections));
86+
}
87+
88+
return CHIP_NO_ERROR;
89+
}
90+
91+
CHIP_ERROR PushAvStreamTransportServer::AddStreamTransportConnection(const uint16_t transportConnectionId)
92+
{
93+
mCurrentConnections.push_back(transportConnectionId);
94+
auto path = ConcreteAttributePath(mEndpointId, PushAvStreamTransport::Id, Attributes::CurrentConnections::Id);
95+
mDelegate.OnAttributeChanged(Attributes::CurrentConnections::Id);
96+
MatterReportingAttributeChangeCallback(path);
97+
98+
return CHIP_NO_ERROR;
99+
}
100+
101+
CHIP_ERROR PushAvStreamTransportServer::RemoveStreamTransportConnection(const uint16_t transportConnectionId)
102+
{
103+
mCurrentConnections.erase(std::remove_if(mCurrentConnections.begin(), mCurrentConnections.end(),
104+
[&](const uint16_t connectionID) { return connectionID == transportConnectionId; }),
105+
mCurrentConnections.end());
106+
auto path = ConcreteAttributePath(mEndpointId, PushAvStreamTransport::Id, Attributes::CurrentConnections::Id);
107+
mDelegate.OnAttributeChanged(Attributes::CurrentConnections::Id);
108+
MatterReportingAttributeChangeCallback(path);
109+
110+
return CHIP_NO_ERROR;
111+
}
112+
113+
CHIP_ERROR PushAvStreamTransportServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
114+
{
115+
VerifyOrDie(aPath.mClusterId == PushAvStreamTransport::Id);
116+
ChipLogError(Zcl, "Push AV Stream Transport: Reading");
117+
118+
switch (aPath.mAttributeId)
119+
{
120+
case FeatureMap::Id:
121+
ReturnErrorOnFailure(aEncoder.Encode(mFeature));
122+
break;
123+
124+
case SupportedContainerFormats::Id:
125+
ReturnErrorOnFailure(aEncoder.Encode(mSupportedContainerFormats));
126+
break;
127+
128+
case SupportedIngestMethods::Id:
129+
ReturnErrorOnFailure(aEncoder.Encode(mSupportedIngestMethods));
130+
break;
131+
132+
case CurrentConnections::Id:
133+
ReturnErrorOnFailure(aEncoder.EncodeList(
134+
[this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeCurrentConnections(encoder); }));
135+
break;
136+
}
137+
138+
return CHIP_NO_ERROR;
139+
}
140+
141+
CHIP_ERROR PushAvStreamTransportServer::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
142+
{
143+
VerifyOrDie(aPath.mClusterId == PushAvStreamTransport::Id);
144+
145+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
146+
}
147+
148+
void PushAvStreamTransportServer::LoadPersistentAttributes()
149+
{
150+
CHIP_ERROR err = CHIP_NO_ERROR;
151+
152+
// Load currentConnections
153+
mDelegate.LoadCurrentConnections(mCurrentConnections);
154+
155+
// Signal delegate that all persistent configuration attributes have been loaded.
156+
mDelegate.PersistentAttributesLoadedCallback();
157+
}
158+
159+
// CommandHandlerInterface
160+
void PushAvStreamTransportServer::InvokeCommand(HandlerContext & handlerContext)
161+
{
162+
ChipLogDetail(Zcl, "PushAV: InvokeCommand");
163+
switch (handlerContext.mRequestPath.mCommandId)
164+
{
165+
case Commands::AllocatePushTransport::Id:
166+
ChipLogDetail(Zcl, "PushAVStreamTransport: Allocating Push Transport");
167+
168+
HandleCommand<Commands::AllocatePushTransport::DecodableType>(
169+
handlerContext,
170+
[this](HandlerContext & ctx, const auto & commandData) { HandleAllocatePushTransport(ctx, commandData); });
171+
172+
break;
173+
174+
case Commands::DeallocatePushTransport::Id:
175+
ChipLogDetail(Zcl, "PushAVStreamTransport: Deallocating Push Transport");
176+
177+
HandleCommand<Commands::DeallocatePushTransport::DecodableType>(
178+
handlerContext,
179+
[this](HandlerContext & ctx, const auto & commandData) { HandleDeallocatePushTransport(ctx, commandData); });
180+
181+
break;
182+
183+
case Commands::ModifyPushTransport::Id:
184+
ChipLogDetail(Zcl, "PushAVStreamTransport: Modifying Push Transport");
185+
186+
HandleCommand<Commands::ModifyPushTransport::DecodableType>(
187+
handlerContext,
188+
[this](HandlerContext & ctx, const auto & commandData) { HandleModifyPushTransport(ctx, commandData); });
189+
190+
break;
191+
192+
case Commands::SetTransportStatus::Id:
193+
ChipLogDetail(Zcl, "PushAVStreamTransport: Setting Push Transport Status");
194+
195+
HandleCommand<Commands::SetTransportStatus::DecodableType>(
196+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleSetTransportStatus(ctx, commandData); });
197+
198+
break;
199+
200+
case Commands::ManuallyTriggerTransport::Id:
201+
ChipLogDetail(Zcl, "PushAVStreamTransport: Manually Triggered Push Transport");
202+
203+
HandleCommand<Commands::ManuallyTriggerTransport::DecodableType>(
204+
handlerContext,
205+
[this](HandlerContext & ctx, const auto & commandData) { HandleManuallyTriggerTransport(ctx, commandData); });
206+
207+
break;
208+
209+
case Commands::FindTransport::Id:
210+
ChipLogDetail(Zcl, "PushAVStreamTransport: Finding Push Transport");
211+
212+
HandleCommand<Commands::FindTransport::DecodableType>(
213+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleFindTransport(ctx, commandData); });
214+
215+
break;
216+
}
217+
}
218+
219+
bool PushAvStreamTransportServer::FindStreamTransportConnection(const uint16_t connectionID)
220+
{
221+
for (auto & id : mCurrentConnections)
222+
{
223+
if (id == connectionID)
224+
return true;
225+
}
226+
return false;
227+
}
228+
229+
uint16_t PushAvStreamTransportServer::GenerateConnectionID()
230+
{
231+
static uint16_t assignedConnectionID = 0;
232+
uint16_t nextConnectionID;
233+
234+
if (assignedConnectionID == MAX_PUSH_TRANSPORT_CONNECTION_ID)
235+
nextConnectionID = 0;
236+
else
237+
nextConnectionID = assignedConnectionID + 1;
238+
239+
while (FindStreamTransportConnection(nextConnectionID) != false)
240+
{
241+
if (nextConnectionID == MAX_PUSH_TRANSPORT_CONNECTION_ID)
242+
nextConnectionID = 0;
243+
else
244+
nextConnectionID = nextConnectionID + 1;
245+
}
246+
return nextConnectionID;
247+
}
248+
249+
void PushAvStreamTransportServer::HandleAllocatePushTransport(HandlerContext & ctx,
250+
const Commands::AllocatePushTransport::DecodableType & commandData)
251+
{
252+
Status status = Status::Success;
253+
Commands::AllocatePushTransportResponse::Type response;
254+
auto & transportOptions = commandData.transportOptions;
255+
256+
uint16_t connectionID = GenerateConnectionID();
257+
TransportStatusEnum outTranportStatus = TransportStatusEnum::kUnknownEnumValue;
258+
259+
// call the delegate
260+
status = mDelegate.AllocatePushTransport(connectionID, transportOptions, outTranportStatus);
261+
262+
if (status == Status::Success)
263+
{
264+
response.connectionID = connectionID;
265+
response.transportOptions = transportOptions;
266+
response.transportStatus = outTranportStatus;
267+
268+
// add connection to CurrentConnections
269+
AddStreamTransportConnection(connectionID);
270+
271+
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
272+
}
273+
else
274+
{
275+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
276+
}
277+
}
278+
279+
void PushAvStreamTransportServer::HandleDeallocatePushTransport(
280+
HandlerContext & ctx, const Commands::DeallocatePushTransport::DecodableType & commandData)
281+
{
282+
Status status = Status::Success;
283+
uint16_t connectionID = commandData.connectionID;
284+
285+
// Call the delegate
286+
status = mDelegate.DeallocatePushTransport(connectionID);
287+
288+
if (status == Status::Success)
289+
// Remove connection form CurrentConnections
290+
RemoveStreamTransportConnection(connectionID);
291+
292+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
293+
}
294+
295+
void PushAvStreamTransportServer::HandleModifyPushTransport(HandlerContext & ctx,
296+
const Commands::ModifyPushTransport::DecodableType & commandData)
297+
{
298+
Status status = Status::Success;
299+
uint16_t connectionID = commandData.connectionID;
300+
auto & outTransportOptions = commandData.transportOptions;
301+
302+
// Call the delegate
303+
status = mDelegate.ModifyPushTransport(connectionID, outTransportOptions);
304+
305+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
306+
}
307+
308+
void PushAvStreamTransportServer::HandleSetTransportStatus(HandlerContext & ctx,
309+
const Commands::SetTransportStatus::DecodableType & commandData)
310+
{
311+
Status status = Status::Success;
312+
uint16_t connectionID = commandData.connectionID;
313+
auto & transportOptions = commandData.transportOptions;
314+
315+
// Call the delegate
316+
status = mDelegate.SetTransportStatus(connectionID, transportOptions);
317+
318+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
319+
}
320+
321+
void PushAvStreamTransportServer::HandleManuallyTriggerTransport(
322+
HandlerContext & ctx, const Commands::ManuallyTriggerTransport::DecodableType & commandData)
323+
{
324+
Status status = Status::Success;
325+
uint16_t connectionID = commandData.connectionID;
326+
auto & activationReason = commandData.activationReason;
327+
auto & timeControl = commandData.timeControl;
328+
329+
// Call the delegate
330+
status = mDelegate.ManuallyTriggerTransport(connectionID, activationReason, timeControl);
331+
332+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
333+
}
334+
335+
void PushAvStreamTransportServer::HandleFindTransport(HandlerContext & ctx,
336+
const Commands::FindTransport::DecodableType & commandData)
337+
{
338+
Status status = Status::Success;
339+
Commands::FindTransportResponse::Type response;
340+
341+
Optional<DataModel::Nullable<uint16_t>> connectionID = commandData.connectionID;
342+
343+
DataModel::List<TransportConfigurationStruct> outStreamConfigurations;
344+
345+
// Call the delegate
346+
status = mDelegate.FindTransport(connectionID, outStreamConfigurations);
347+
if (status == Status::Success)
348+
{
349+
response.streamConfigurations = outStreamConfigurations;
350+
351+
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
352+
}
353+
else
354+
{
355+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
356+
}
357+
}
358+
359+
} // namespace PushAvStreamTransport
360+
} // namespace Clusters
361+
} // namespace app
362+
} // namespace chip
363+
364+
/** @brief Push AV Stream Transport Cluster Server Init
365+
*
366+
* Server Init
367+
*
368+
*/
369+
void MatterPushAvStreamTransportPluginServerInitCallback() {}

0 commit comments

Comments
 (0)