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 : #pragma once
19 :
20 : #include <app-common/zap-generated/cluster-objects.h>
21 : #include <lib/core/CHIPPersistentStorageDelegate.h>
22 : #include <lib/core/CHIPVendorIdentifiers.hpp>
23 : #include <lib/core/NodeId.h>
24 : #include <vector>
25 :
26 : namespace chip {
27 : namespace app {
28 :
29 : /**
30 : * A struct which extends the DatastoreNodeInformationEntry type with FriendlyName buffer reservation.
31 : */
32 : struct GenericDatastoreNodeInformationEntry
33 : : public Clusters::JointFabricDatastore::Structs::DatastoreNodeInformationEntryStruct::Type
34 : {
35 0 : GenericDatastoreNodeInformationEntry(NodeId nodeId = 0,
36 : Clusters::JointFabricDatastore::DatastoreStateEnum state =
37 : Clusters::JointFabricDatastore::DatastoreStateEnum::kUnknownEnumValue,
38 : Optional<CharSpan> label = NullOptional)
39 0 : {
40 0 : Set(nodeId, state, label);
41 0 : }
42 :
43 0 : GenericDatastoreNodeInformationEntry(const GenericDatastoreNodeInformationEntry & op) { *this = op; }
44 :
45 0 : GenericDatastoreNodeInformationEntry & operator=(const GenericDatastoreNodeInformationEntry & op)
46 : {
47 0 : Set(op.nodeID, op.commissioningStatusEntry.state, MakeOptional(op.friendlyName));
48 0 : return *this;
49 : }
50 :
51 0 : void Set(NodeId nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum state, Optional<CharSpan> label = NullOptional)
52 : {
53 0 : this->nodeID = nodeId;
54 0 : this->commissioningStatusEntry.state = state;
55 0 : Set(label);
56 0 : }
57 :
58 0 : void Set(Optional<CharSpan> label = NullOptional)
59 : {
60 0 : if (label.HasValue())
61 : {
62 0 : memset(mFriendlyNameBuffer, 0, sizeof(mFriendlyNameBuffer));
63 0 : if (label.Value().size() > sizeof(mFriendlyNameBuffer))
64 : {
65 0 : memcpy(mFriendlyNameBuffer, label.Value().data(), sizeof(mFriendlyNameBuffer));
66 0 : this->friendlyName = CharSpan(mFriendlyNameBuffer, sizeof(mFriendlyNameBuffer));
67 : }
68 : else
69 : {
70 0 : memcpy(mFriendlyNameBuffer, label.Value().data(), label.Value().size());
71 0 : this->friendlyName = CharSpan(mFriendlyNameBuffer, label.Value().size());
72 : }
73 : }
74 : else
75 : {
76 0 : this->friendlyName = CharSpan();
77 : }
78 0 : }
79 :
80 : private:
81 : static constexpr size_t kFriendlyNameMaxSize = 32u;
82 :
83 : char mFriendlyNameBuffer[kFriendlyNameMaxSize];
84 : };
85 :
86 : class JointFabricDatastore
87 : {
88 : public:
89 : static JointFabricDatastore & GetInstance()
90 : {
91 : static JointFabricDatastore sInstance;
92 : return sInstance;
93 : }
94 :
95 : CHIP_ERROR SetAdministratorFabricIndex(FabricIndex fabricIndex)
96 : {
97 : mAdministratorFabricIndex = fabricIndex;
98 : return CHIP_NO_ERROR;
99 : }
100 : FabricIndex GetAdministratorFabricIndex() { return mAdministratorFabricIndex; }
101 :
102 : CHIP_ERROR SetAnchorNodeId(NodeId anchorNodeId)
103 : {
104 : mAnchorNodeId = anchorNodeId;
105 : return CHIP_NO_ERROR;
106 : }
107 : NodeId GetAnchorNodeId() { return mAnchorNodeId; }
108 :
109 : CHIP_ERROR SetAnchorVendorId(VendorId anchorVendorId)
110 : {
111 : mAnchorVendorId = anchorVendorId;
112 : return CHIP_NO_ERROR;
113 : }
114 : VendorId GetAnchorVendorId() { return mAnchorVendorId; }
115 :
116 : CHIP_ERROR AddPendingNode(NodeId nodeId, const CharSpan & friendlyName);
117 : CHIP_ERROR UpdateNode(NodeId nodeId, const CharSpan & friendlyName);
118 : CHIP_ERROR RemoveNode(NodeId nodeId);
119 : CHIP_ERROR RefreshNode(NodeId nodeId);
120 :
121 : CHIP_ERROR SetNode(NodeId nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum state);
122 :
123 : CHIP_ERROR AddGroupKeySetEntry(Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet);
124 : bool IsGroupKeySetEntryPresent(uint16_t groupKeySetId);
125 : CHIP_ERROR RemoveGroupKeySetEntry(uint16_t groupKeySetId);
126 : CHIP_ERROR UpdateGroupKeySetEntry(Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet);
127 :
128 : CHIP_ERROR AddAdmin(Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type & adminId);
129 : bool IsAdminEntryPresent(NodeId nodeId);
130 : CHIP_ERROR UpdateAdmin(NodeId nodeId, CharSpan friendlyName, ByteSpan icac);
131 : CHIP_ERROR RemoveAdmin(NodeId nodeId);
132 :
133 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> & GetGroupKeySetList()
134 : {
135 : return mGroupKeySetList;
136 : }
137 : const std::vector<GenericDatastoreNodeInformationEntry> & GetNodeInformationEntries() { return mNodeInformationEntries; }
138 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type> &
139 : GetAdminEntries()
140 : {
141 : return mAdminEntries;
142 : }
143 :
144 : /**
145 : * Used to notify of changes in the node list and more TODO.
146 : */
147 : class Listener
148 : {
149 : public:
150 : virtual ~Listener() = default;
151 :
152 : /**
153 : * Notifies of a change in the node list.
154 : */
155 : virtual void MarkNodeListChanged() = 0;
156 :
157 : private:
158 : Listener * mNext = nullptr;
159 :
160 : friend class JointFabricDatastore;
161 : };
162 :
163 : /**
164 : * Add a listener to be notified of changes in the Joint Fabric Datastore.
165 : *
166 : * @param [in] listener The listener to add.
167 : */
168 : void AddListener(Listener & listener);
169 :
170 : /**
171 : * Remove a listener from being notified of changes in the Joint Fabric Datastore.
172 : *
173 : * @param [in] listener The listener to remove.
174 : */
175 : void RemoveListener(Listener & listener);
176 :
177 : private:
178 : static constexpr size_t kMaxNodes = 256;
179 : static constexpr size_t kMaxAdminNodes = 32;
180 : static constexpr size_t kMaxGroups = kMaxNodes / 16;
181 : static constexpr size_t kMaxGroupKeySet = kMaxGroups * 16;
182 :
183 : FabricIndex mAdministratorFabricIndex = kUndefinedFabricIndex;
184 :
185 : NodeId mAnchorNodeId = kUndefinedNodeId;
186 : VendorId mAnchorVendorId = VendorId::NotSpecified;
187 :
188 : std::vector<GenericDatastoreNodeInformationEntry> mNodeInformationEntries;
189 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> mGroupKeySetList;
190 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type> mAdminEntries;
191 :
192 : Listener * mListeners = nullptr;
193 :
194 : CHIP_ERROR IsNodeIDInDatastore(NodeId nodeId, size_t & index);
195 : };
196 :
197 : } // namespace app
198 : } // namespace chip
|