Skip to content

Commit 48ff8e0

Browse files
sayondeepesp
authored andcommitted
initial implementation of pushav server
1 parent a5971fa commit 48ff8e0

File tree

6 files changed

+637
-37
lines changed

6 files changed

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

0 commit comments

Comments
 (0)