Line data Source code
1 : /*
2 : * Copyright (c) 2025 Project CHIP Authors
3 : * All rights reserved.
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 "SpanEndpointProvider.h"
18 :
19 : #include <app/ConcreteClusterPath.h>
20 : #include <app/server-cluster/ServerClusterContext.h>
21 : #include <clusters/Descriptor/ClusterId.h>
22 : #include <lib/core/CHIPError.h>
23 : #include <lib/support/Span.h>
24 : #include <lib/support/logging/CHIPLogging.h>
25 :
26 : namespace chip {
27 : namespace app {
28 :
29 : // Builder implementation
30 126 : SpanEndpointProvider::Builder::Builder(EndpointId id) : mEndpointId(id) {}
31 :
32 115 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetComposition(DataModel::EndpointCompositionPattern composition)
33 : {
34 115 : mComposition = composition;
35 115 : return *this;
36 : }
37 :
38 3 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetParentId(EndpointId parentId)
39 : {
40 3 : mParentId = parentId;
41 3 : return *this;
42 : }
43 :
44 124 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetServerClusters(Span<ServerClusterInterface *> serverClusters)
45 : {
46 124 : mServerClusters = serverClusters;
47 124 : return *this;
48 : }
49 :
50 3 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetClientClusters(Span<const ClusterId> clientClusters)
51 : {
52 3 : mClientClusters = clientClusters;
53 3 : return *this;
54 : }
55 :
56 3 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetSemanticTags(Span<const SemanticTag> semanticTags)
57 : {
58 3 : mSemanticTags = semanticTags;
59 3 : return *this;
60 : }
61 :
62 3 : SpanEndpointProvider::Builder & SpanEndpointProvider::Builder::SetDeviceTypes(Span<const DataModel::DeviceTypeEntry> deviceTypes)
63 : {
64 3 : mDeviceTypes = deviceTypes;
65 3 : return *this;
66 : }
67 :
68 126 : std::variant<SpanEndpointProvider, CHIP_ERROR> SpanEndpointProvider::Builder::build()
69 : {
70 126 : if (mEndpointId == kInvalidEndpointId || mServerClusters.empty())
71 : {
72 3 : return CHIP_ERROR_INVALID_ARGUMENT;
73 : }
74 :
75 : // Check that cluster list is not invalid and that it contains the Descriptor cluster
76 123 : bool foundDescriptor = false;
77 252 : for (auto * cluster : mServerClusters)
78 : {
79 130 : if (cluster == nullptr || cluster->GetPaths().empty())
80 : {
81 1 : ChipLogError(DataManagement, "Builder: Attempted to build with an invalid server cluster entry.");
82 1 : return CHIP_ERROR_INVALID_ARGUMENT;
83 : }
84 :
85 129 : if (cluster->GetPaths().front().mClusterId == chip::app::Clusters::Descriptor::Id)
86 : {
87 122 : foundDescriptor = true;
88 : }
89 : }
90 :
91 122 : if (!foundDescriptor)
92 : {
93 1 : ChipLogError(DataManagement, "Builder: Descriptor cluster is mandatory and was not found.");
94 1 : return CHIP_ERROR_INVALID_ARGUMENT;
95 : }
96 :
97 242 : return SpanEndpointProvider(mEndpointId, mComposition, mParentId, mServerClusters, mClientClusters, mSemanticTags,
98 121 : mDeviceTypes);
99 : }
100 :
101 : CHIP_ERROR
102 3 : SpanEndpointProvider::SemanticTags(
103 : ReadOnlyBufferBuilder<chip::app::Clusters::Descriptor::Structs::SemanticTagStruct::Type> & out) const
104 : {
105 3 : return out.ReferenceExisting(mSemanticTags);
106 : }
107 :
108 3 : CHIP_ERROR SpanEndpointProvider::DeviceTypes(ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out) const
109 : {
110 3 : return out.ReferenceExisting(mDeviceTypes);
111 : }
112 :
113 3 : CHIP_ERROR SpanEndpointProvider::ClientClusters(ReadOnlyBufferBuilder<ClusterId> & out) const
114 : {
115 3 : return out.ReferenceExisting(mClientClusters);
116 : }
117 :
118 7 : ServerClusterInterface * SpanEndpointProvider::GetServerCluster(ClusterId clusterId) const
119 : {
120 15 : for (auto * serverCluster : mServerClusters)
121 : {
122 : // Don't check for serverCluster != nullptr as it's checked in Register()
123 : // Don't check for serverCluster->GetPaths().empty() as it's guaranteed by the interface contract
124 13 : if (serverCluster->GetPaths().front().mClusterId == clusterId)
125 : {
126 5 : return serverCluster;
127 : }
128 : }
129 2 : return nullptr;
130 : }
131 :
132 3 : CHIP_ERROR SpanEndpointProvider::ServerClusterInterfaces(ReadOnlyBufferBuilder<ServerClusterInterface *> & out) const
133 : {
134 3 : return out.ReferenceExisting(mServerClusters);
135 : }
136 :
137 : // Private constructor for Builder
138 121 : SpanEndpointProvider::SpanEndpointProvider(EndpointId id, DataModel::EndpointCompositionPattern composition, EndpointId parentId,
139 : Span<ServerClusterInterface *> serverClusters, Span<const ClusterId> clientClusters,
140 : Span<const SemanticTag> semanticTags,
141 121 : Span<const DataModel::DeviceTypeEntry> deviceTypes) :
142 121 : mEndpointEntry({ id, parentId, composition }),
143 121 : mDeviceTypes(deviceTypes), mSemanticTags(semanticTags), mClientClusters(clientClusters), mServerClusters(serverClusters)
144 121 : {}
145 :
146 : } // namespace app
147 : } // namespace chip
|