Line data Source code
1 : /*
2 : * Copyright (c) 2024 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 : #pragma once
18 :
19 : #include <cstdint>
20 : #include <optional>
21 :
22 : #include <access/Privilege.h>
23 : #include <app-common/zap-generated/cluster-objects.h>
24 : #include <app/AttributePathParams.h>
25 : #include <app/ConcreteAttributePath.h>
26 : #include <app/ConcreteClusterPath.h>
27 : #include <app/ConcreteCommandPath.h>
28 : #include <app/data-model/List.h>
29 : #include <lib/core/DataModelTypes.h>
30 : #include <lib/support/BitFlags.h>
31 : #include <lib/support/BitMask.h>
32 :
33 : namespace chip {
34 : namespace app {
35 : namespace DataModel {
36 :
37 : /// Represents various endpoint composition patters as defined in the spec
38 : /// as `9.2.1. Endpoint Composition patterns`
39 : enum class EndpointCompositionPattern : uint8_t
40 : {
41 : // Tree pattern supports a general tree of endpoints. Commonly used for
42 : // device types that support physical device composition (e.g. Refrigerator)
43 : kTree = 0x1,
44 :
45 : // A full-family pattern is a list fo all descendant endpoints, with no
46 : // imposed hierarchy.
47 : //
48 : // For example the Root Node and Aggregator device types use the full-familiy
49 : // pattern, as defined in their device type specification
50 : kFullFamily = 0x2,
51 : };
52 :
53 : struct EndpointInfo
54 : {
55 : // kInvalidEndpointId if there is no explicit parent endpoint (which means the parent is endpoint 0,
56 : // for endpoints other than endpoint 0).
57 : EndpointId parentId;
58 : EndpointCompositionPattern compositionPattern;
59 :
60 74 : explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamily) {}
61 153 : EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {}
62 : };
63 :
64 : struct EndpointEntry
65 : {
66 : EndpointId id;
67 : EndpointInfo info;
68 :
69 1 : bool IsValid() const { return id != kInvalidEndpointId; }
70 : static const EndpointEntry kInvalid;
71 : };
72 :
73 : enum class ClusterQualityFlags : uint32_t
74 : {
75 : kDiagnosticsData = 0x0001, // `K` quality, may be filtered out in subscriptions
76 : };
77 :
78 : struct ClusterInfo
79 : {
80 : DataVersion dataVersion; // current cluster data version,
81 : BitFlags<ClusterQualityFlags> flags;
82 :
83 : /// Constructor that marks data version as mandatory
84 : /// for this structure.
85 5295 : ClusterInfo(DataVersion version) : dataVersion(version) {}
86 : };
87 :
88 : struct ClusterEntry
89 : {
90 : ConcreteClusterPath path;
91 : ClusterInfo info;
92 :
93 472 : bool IsValid() const { return path.HasValidIds(); }
94 :
95 : static const ClusterEntry kInvalid;
96 : };
97 :
98 : enum class AttributeQualityFlags : uint32_t
99 : {
100 : kListAttribute = 0x0004, // This attribute is a list attribute
101 : kFabricScoped = 0x0008, // 'F' quality on attributes
102 : kFabricSensitive = 0x0010, // 'S' quality on attributes
103 : kChangesOmitted = 0x0020, // `C` quality on attributes
104 : kTimed = 0x0040, // `T` quality on attributes (writes require timed interactions)
105 : };
106 :
107 : struct AttributeInfo
108 : {
109 : BitFlags<AttributeQualityFlags> flags;
110 :
111 : // read/write access will be missing if read/write is NOT allowed
112 : std::optional<Access::Privilege> readPrivilege; // generally defaults to View if readable
113 : std::optional<Access::Privilege> writePrivilege; // generally defaults to Operate if writable
114 : };
115 :
116 : struct AttributeEntry
117 : {
118 : ConcreteAttributePath path;
119 : AttributeInfo info;
120 :
121 2978 : bool IsValid() const { return path.HasValidIds(); }
122 :
123 : static const AttributeEntry kInvalid;
124 : };
125 :
126 : // Bitmask values for different Command qualities.
127 : enum class CommandQualityFlags : uint32_t
128 : {
129 : kFabricScoped = 0x0001,
130 : kTimed = 0x0002, // `T` quality on commands
131 : kLargeMessage = 0x0004, // `L` quality on commands
132 : };
133 :
134 : struct CommandInfo
135 : {
136 : BitFlags<CommandQualityFlags> flags;
137 : Access::Privilege invokePrivilege = Access::Privilege::kOperate;
138 : };
139 :
140 : struct CommandEntry
141 : {
142 : ConcreteCommandPath path;
143 : CommandInfo info;
144 :
145 : bool IsValid() const { return path.HasValidIds(); }
146 :
147 : static const CommandEntry kInvalid;
148 : };
149 :
150 : /// Represents a device type that resides on an endpoint
151 : struct DeviceTypeEntry
152 : {
153 : DeviceTypeId deviceTypeId;
154 : uint8_t deviceTypeRevision;
155 :
156 : bool operator==(const DeviceTypeEntry & other) const
157 : {
158 : return (deviceTypeId == other.deviceTypeId) && (deviceTypeRevision == other.deviceTypeRevision);
159 : }
160 : };
161 :
162 : /// Provides metadata information for a data model
163 : ///
164 : /// The data model can be viewed as a tree of endpoint/cluster/(attribute+commands+events)
165 : /// where each element can be iterated through independently.
166 : ///
167 : /// Iteration rules:
168 : /// - Invalid paths will be returned when iteration ends (IDs will be kInvalid* and in particular
169 : /// mEndpointId will be kInvalidEndpointId). See `::kInvalid` constants for entries and
170 : /// can use ::IsValid() to determine if the entry is valid or not.
171 : /// - Global Attributes are NOT returned since they are implied
172 : /// - Any internal iteration errors are just logged (callers do not handle iteration CHIP_ERROR)
173 : /// - Iteration order is NOT guaranteed globally. Only the following is guaranteed:
174 : /// - Complete tree iteration (e.g. when iterating an endpoint, ALL clusters of that endpoint
175 : /// are returned, when iterating over a cluster, all attributes/commands are iterated over)
176 : /// - uniqueness and completeness (iterate over all possible distinct values as long as no
177 : /// internal structural changes occur)
178 : class ProviderMetadataTree
179 : {
180 : public:
181 160 : virtual ~ProviderMetadataTree() = default;
182 :
183 : // This iteration will list all the endpoints in the data model
184 : virtual EndpointEntry FirstEndpoint() = 0;
185 : virtual EndpointEntry NextEndpoint(EndpointId before) = 0;
186 : virtual std::optional<EndpointInfo> GetEndpointInfo(EndpointId id) = 0;
187 : virtual bool EndpointExists(EndpointId id);
188 :
189 : // This iteration describes device types registered on an endpoint
190 : virtual std::optional<DeviceTypeEntry> FirstDeviceType(EndpointId endpoint) = 0;
191 : virtual std::optional<DeviceTypeEntry> NextDeviceType(EndpointId endpoint, const DeviceTypeEntry & previous) = 0;
192 :
193 : // This iteration describes semantic tags registered on an endpoint
194 : using SemanticTag = Clusters::Descriptor::Structs::SemanticTagStruct::Type;
195 : virtual std::optional<SemanticTag> GetFirstSemanticTag(EndpointId endpoint) = 0;
196 : virtual std::optional<SemanticTag> GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) = 0;
197 :
198 : // This iteration will list all server clusters on a given endpoint
199 : virtual ClusterEntry FirstServerCluster(EndpointId endpoint) = 0;
200 : virtual ClusterEntry NextServerCluster(const ConcreteClusterPath & before) = 0;
201 : virtual std::optional<ClusterInfo> GetServerClusterInfo(const ConcreteClusterPath & path) = 0;
202 :
203 : // This iteration will list all client clusters on a given endpoint
204 : // As the client cluster is only a client without any attributes/commands,
205 : // these functions only return the cluster path.
206 : virtual ConcreteClusterPath FirstClientCluster(EndpointId endpoint) = 0;
207 : virtual ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) = 0;
208 :
209 : // Attribute iteration and accessors provide cluster-level access over
210 : // attributes
211 : virtual AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) = 0;
212 : virtual AttributeEntry NextAttribute(const ConcreteAttributePath & before) = 0;
213 : virtual std::optional<AttributeInfo> GetAttributeInfo(const ConcreteAttributePath & path) = 0;
214 :
215 : // Command iteration and accessors provide cluster-level access over commands
216 : virtual CommandEntry FirstAcceptedCommand(const ConcreteClusterPath & cluster) = 0;
217 : virtual CommandEntry NextAcceptedCommand(const ConcreteCommandPath & before) = 0;
218 : virtual std::optional<CommandInfo> GetAcceptedCommandInfo(const ConcreteCommandPath & path) = 0;
219 :
220 : // "generated" commands are purely for reporting what types of command ids can be
221 : // returned as responses.
222 : virtual ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) = 0;
223 : virtual ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) = 0;
224 :
225 : /// Workaround function to report attribute change.
226 : ///
227 : /// When this is invoked, the caller is expected to increment the cluster data version, and the attribute path
228 : /// should be marked as `dirty` by the data model provider listener so that the reporter can notify the subscriber
229 : /// of attribute changes.
230 : /// This function should be invoked when attribute managed by attribute access interface is modified but not
231 : /// through an actual Write interaction.
232 : /// For example, if the LastNetworkingStatus attribute changes because the NetworkCommissioning driver detects a
233 : /// network connection status change and calls SetLastNetworkingStatusValue(). The data model provider can recognize
234 : /// this change by invoking this function at the point of change.
235 : ///
236 : /// This is a workaround function as we cannot notify the attribute change to the data model provider. The provider
237 : /// should own its data and versions.
238 : ///
239 : /// TODO: We should remove this function when the AttributeAccessInterface/CommandHandlerInterface is able to report
240 : /// the attribute changes.
241 : virtual void Temporary_ReportAttributeChanged(const AttributePathParams & path) = 0;
242 : };
243 :
244 : } // namespace DataModel
245 : } // namespace app
246 : } // namespace chip
|