Line data Source code
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 : #include <app/server/JointFabricDatastore.h>
19 :
20 : namespace chip {
21 : namespace app {
22 :
23 0 : void JointFabricDatastore::AddListener(Listener & listener)
24 : {
25 0 : if (mListeners == nullptr)
26 : {
27 0 : mListeners = &listener;
28 0 : listener.mNext = nullptr;
29 0 : return;
30 : }
31 :
32 0 : for (Listener * l = mListeners; /**/; l = l->mNext)
33 : {
34 0 : if (l == &listener)
35 : {
36 0 : return;
37 : }
38 :
39 0 : if (l->mNext == nullptr)
40 : {
41 0 : l->mNext = &listener;
42 0 : listener.mNext = nullptr;
43 0 : return;
44 : }
45 : }
46 : }
47 :
48 0 : void JointFabricDatastore::RemoveListener(Listener & listener)
49 : {
50 0 : if (mListeners == &listener)
51 : {
52 0 : mListeners = listener.mNext;
53 0 : listener.mNext = nullptr;
54 0 : return;
55 : }
56 :
57 0 : for (Listener * l = mListeners; l != nullptr; l = l->mNext)
58 : {
59 0 : if (l->mNext == &listener)
60 : {
61 0 : l->mNext = listener.mNext;
62 0 : listener.mNext = nullptr;
63 0 : return;
64 : }
65 : }
66 : }
67 :
68 0 : CHIP_ERROR JointFabricDatastore::AddPendingNode(NodeId nodeId, const CharSpan & friendlyName)
69 : {
70 0 : VerifyOrReturnError(mNodeInformationEntries.size() < kMaxNodes, CHIP_ERROR_NO_MEMORY);
71 :
72 0 : mNodeInformationEntries.push_back(GenericDatastoreNodeInformationEntry(
73 0 : nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum::kPending, MakeOptional(friendlyName)));
74 :
75 0 : for (Listener * listener = mListeners; listener != nullptr; listener = listener->mNext)
76 : {
77 0 : listener->MarkNodeListChanged();
78 : }
79 :
80 0 : return CHIP_NO_ERROR;
81 : }
82 :
83 0 : CHIP_ERROR JointFabricDatastore::UpdateNode(NodeId nodeId, const CharSpan & friendlyName)
84 : {
85 0 : for (auto & entry : mNodeInformationEntries)
86 : {
87 0 : if (entry.nodeID == nodeId)
88 : {
89 0 : entry.Set(MakeOptional(friendlyName));
90 :
91 0 : for (Listener * listener = mListeners; listener != nullptr; listener = listener->mNext)
92 : {
93 0 : listener->MarkNodeListChanged();
94 : }
95 :
96 0 : return CHIP_NO_ERROR;
97 : }
98 : }
99 :
100 0 : return CHIP_ERROR_KEY_NOT_FOUND;
101 : }
102 :
103 0 : CHIP_ERROR JointFabricDatastore::RemoveNode(NodeId nodeId)
104 : {
105 0 : for (auto it = mNodeInformationEntries.begin(); it != mNodeInformationEntries.end(); ++it)
106 : {
107 0 : if (it->nodeID == nodeId)
108 : {
109 0 : mNodeInformationEntries.erase(it);
110 :
111 0 : for (Listener * listener = mListeners; listener != nullptr; listener = listener->mNext)
112 : {
113 0 : listener->MarkNodeListChanged();
114 : }
115 :
116 0 : return CHIP_NO_ERROR;
117 : }
118 : }
119 :
120 0 : return CHIP_ERROR_KEY_NOT_FOUND;
121 : }
122 :
123 0 : CHIP_ERROR JointFabricDatastore::RefreshNode(NodeId nodeId)
124 : {
125 : // 1. && 2.
126 0 : ReturnErrorOnFailure(SetNode(nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum::kPending));
127 :
128 : // 3. TODO: Read the PartsList of the Descriptor cluster from the Node.
129 :
130 : // 4. TODO
131 :
132 : // 5. TODO
133 :
134 : // 6.
135 0 : ReturnErrorOnFailure(SetNode(nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum::kCommitted));
136 :
137 0 : for (Listener * listener = mListeners; listener != nullptr; listener = listener->mNext)
138 : {
139 0 : listener->MarkNodeListChanged();
140 : }
141 :
142 0 : return CHIP_NO_ERROR;
143 : }
144 :
145 0 : CHIP_ERROR JointFabricDatastore::SetNode(NodeId nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum state)
146 : {
147 0 : size_t index = 0;
148 0 : ReturnErrorOnFailure(IsNodeIDInDatastore(nodeId, index));
149 0 : mNodeInformationEntries[index].commissioningStatusEntry.state = state;
150 0 : return CHIP_NO_ERROR;
151 : }
152 :
153 0 : CHIP_ERROR JointFabricDatastore::IsNodeIDInDatastore(NodeId nodeId, size_t & index)
154 : {
155 0 : for (auto & entry : mNodeInformationEntries)
156 : {
157 0 : if (entry.nodeID == nodeId)
158 : {
159 0 : index = static_cast<size_t>(&entry - &mNodeInformationEntries[0]);
160 0 : return CHIP_NO_ERROR;
161 : }
162 : }
163 :
164 0 : return CHIP_ERROR_KEY_NOT_FOUND;
165 : }
166 :
167 : CHIP_ERROR
168 0 : JointFabricDatastore::AddGroupKeySetEntry(Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet)
169 : {
170 0 : VerifyOrReturnError(IsGroupKeySetEntryPresent(groupKeySet.groupKeySetID) == false, CHIP_ERROR_INVALID_ARGUMENT);
171 0 : VerifyOrReturnError(mGroupKeySetList.size() < kMaxGroupKeySet, CHIP_ERROR_NO_MEMORY);
172 :
173 0 : mGroupKeySetList.push_back(groupKeySet);
174 :
175 0 : return CHIP_NO_ERROR;
176 : }
177 :
178 0 : bool JointFabricDatastore::IsGroupKeySetEntryPresent(uint16_t groupKeySetId)
179 : {
180 0 : for (auto & entry : mGroupKeySetList)
181 : {
182 0 : if (entry.groupKeySetID == groupKeySetId)
183 : {
184 0 : return true;
185 : }
186 : }
187 :
188 0 : return false;
189 : }
190 :
191 0 : CHIP_ERROR JointFabricDatastore::RemoveGroupKeySetEntry(uint16_t groupKeySetId)
192 : {
193 0 : for (auto it = mGroupKeySetList.begin(); it != mGroupKeySetList.end(); ++it)
194 : {
195 0 : if (it->groupKeySetID == groupKeySetId)
196 : {
197 0 : mGroupKeySetList.erase(it);
198 0 : return CHIP_NO_ERROR;
199 : }
200 : }
201 :
202 0 : return CHIP_ERROR_KEY_NOT_FOUND;
203 : }
204 :
205 : CHIP_ERROR
206 0 : JointFabricDatastore::UpdateGroupKeySetEntry(
207 : Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet)
208 : {
209 0 : for (auto & entry : mGroupKeySetList)
210 : {
211 0 : if (entry.groupKeySetID == groupKeySet.groupKeySetID)
212 : {
213 0 : entry = groupKeySet;
214 :
215 : // TODO: RefreshNodes
216 :
217 0 : return CHIP_NO_ERROR;
218 : }
219 : }
220 :
221 0 : return CHIP_ERROR_KEY_NOT_FOUND;
222 : }
223 :
224 : CHIP_ERROR
225 0 : JointFabricDatastore::AddAdmin(
226 : Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type & adminId)
227 : {
228 0 : VerifyOrReturnError(IsAdminEntryPresent(adminId.nodeID) == false, CHIP_ERROR_INVALID_ARGUMENT);
229 0 : VerifyOrReturnError(mAdminEntries.size() < kMaxAdminNodes, CHIP_ERROR_NO_MEMORY);
230 :
231 0 : mAdminEntries.push_back(adminId);
232 :
233 0 : return CHIP_NO_ERROR;
234 : }
235 :
236 0 : bool JointFabricDatastore::IsAdminEntryPresent(NodeId nodeId)
237 : {
238 0 : for (auto & entry : mAdminEntries)
239 : {
240 0 : if (entry.nodeID == nodeId)
241 : {
242 0 : return true;
243 : }
244 : }
245 :
246 0 : return false;
247 : }
248 :
249 0 : CHIP_ERROR JointFabricDatastore::UpdateAdmin(NodeId nodeId, CharSpan friendlyName, ByteSpan icac)
250 : {
251 0 : for (auto & entry : mAdminEntries)
252 : {
253 0 : if (entry.nodeID == nodeId)
254 : {
255 0 : entry.friendlyName = friendlyName;
256 0 : entry.icac = icac;
257 0 : return CHIP_NO_ERROR;
258 : }
259 : }
260 :
261 0 : return CHIP_ERROR_KEY_NOT_FOUND;
262 : }
263 :
264 0 : CHIP_ERROR JointFabricDatastore::RemoveAdmin(NodeId nodeId)
265 : {
266 0 : for (auto it = mAdminEntries.begin(); it != mAdminEntries.end(); ++it)
267 : {
268 0 : if (it->nodeID == nodeId)
269 : {
270 0 : mAdminEntries.erase(it);
271 0 : return CHIP_NO_ERROR;
272 : }
273 : }
274 :
275 0 : return CHIP_ERROR_KEY_NOT_FOUND;
276 : }
277 :
278 : } // namespace app
279 : } // namespace chip
|