/src/connectedhomeip/src/app/data-model-provider/Provider.h
Line | Count | Source (jump to first uncovered line) |
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 <lib/core/CHIPError.h> |
20 | | #include <lib/core/TLVReader.h> |
21 | | #include <lib/core/TLVWriter.h> |
22 | | |
23 | | #include <app/AttributeValueDecoder.h> |
24 | | #include <app/AttributeValueEncoder.h> |
25 | | #include <app/CommandHandler.h> |
26 | | |
27 | | #include <app/data-model-provider/ActionReturnStatus.h> |
28 | | #include <app/data-model-provider/Context.h> |
29 | | #include <app/data-model-provider/OperationTypes.h> |
30 | | #include <app/data-model-provider/ProviderMetadataTree.h> |
31 | | |
32 | | namespace chip { |
33 | | namespace app { |
34 | | namespace DataModel { |
35 | | |
36 | | /// Represents operations against a matter-defined data model. |
37 | | /// |
38 | | /// Class is SINGLE-THREADED: |
39 | | /// - operations are assumed to only be ever run in a single event-loop |
40 | | /// thread or equivalent |
41 | | /// - class is allowed to attempt to cache indexes/locations for faster |
42 | | /// lookups of things (e.g during iterations) |
43 | | class Provider : public ProviderMetadataTree |
44 | | { |
45 | | public: |
46 | | ~Provider() override = default; |
47 | | |
48 | | // `context` references will be guaranteed valid until Shutdown is called() |
49 | 1 | virtual CHIP_ERROR Startup(InteractionModelContext context) { return CHIP_NO_ERROR; } |
50 | 0 | virtual CHIP_ERROR Shutdown() { return CHIP_NO_ERROR; } |
51 | | |
52 | | /// NOTE: this code is NOT required to handle `List` global attributes: |
53 | | /// AcceptedCommandsList, GeneratedCommandsList OR AttributeList |
54 | | /// |
55 | | /// Users of DataModel::Provider are expected to get these lists |
56 | | /// from ProviderMetadataTree (in particular IM Reads of these |
57 | | /// attributes will be automatically filled from metadata). |
58 | | /// |
59 | | /// When this is invoked, caller is expected to have already done some validations: |
60 | | /// - `request.path` is a valid path inside the ProviderMetadataTree (an AttributeEntry exists) |
61 | | /// - Attribute is readable according to the ProviderMetadataTree/AttributeEntry data |
62 | | /// - Appropriate ACL checks done according to the attribute's AttributeEntry |
63 | | /// |
64 | | /// Return value notes: |
65 | | /// ActionReturnStatus::IsOutOfSpaceEncodingResponse |
66 | | /// - Indicates that list encoding had insufficient buffer space to encode elements. |
67 | | /// - encoder::GetState().AllowPartialData() determines if these errors are permanent (no partial |
68 | | /// data allowed) or further encoding can be retried (AllowPartialData true for list encoding) |
69 | | virtual ActionReturnStatus ReadAttribute(const ReadAttributeRequest & request, AttributeValueEncoder & encoder) = 0; |
70 | | |
71 | | /// Requests a write of an attribute. |
72 | | /// |
73 | | /// When this is invoked, caller is expected to have already done some validations: |
74 | | /// - cluster `data version` has been checked for the incoming request if applicable |
75 | | /// - validation of ACL/timed interaction flags/writability, if those checks are desired. |
76 | | /// - `request.path` is a valid path inside the ProviderMetadataTree (an AttributeEntry exists) |
77 | | /// - Attribute is writable according to the ProviderMetadataTree/AttributeEntry data |
78 | | /// - Appropriate ACL checks done according to the attribute's AttributeEntry |
79 | | virtual ActionReturnStatus WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder) = 0; |
80 | | |
81 | | /// Indicates the start/end of a series of list operations. This function will be called either before the first |
82 | | /// Write operation or after the last one of a series of consecutive attribute data of the same attribute. |
83 | | /// |
84 | | /// 1) This function will be called if the client tries to set a nullable list attribute to null. |
85 | | /// 2) This function will only be called at the beginning and end of a series of consecutive attribute data |
86 | | /// blocks for the same attribute, no matter what list operations those data blocks represent. |
87 | | /// 3) The opType argument indicates the type of notification (Start, Failure, Success). |
88 | | virtual void ListAttributeWriteNotification(const ConcreteAttributePath & aPath, ListWriteOperation opType) = 0; |
89 | | |
90 | | /// `handler` is used to send back the reply. |
91 | | /// - returning `std::nullopt` means that return value was placed in handler directly. |
92 | | /// This includes cases where command handling and value return will be done asynchronously. |
93 | | /// - returning a value other than Success implies an error reply (error and data are mutually exclusive) |
94 | | /// |
95 | | /// Preconditions: |
96 | | /// - `request.path` MUST refer to a command that actually exists. This is because in practice |
97 | | /// callers must do ACL and flag checks (e.g. for timed invoke) before calling this function. |
98 | | /// |
99 | | /// Callers that do not care about those checks should use `ProviderMetadataTree::AcceptedCommands` |
100 | | /// to check for command existence. |
101 | | /// |
102 | | /// - TODO: as interfaces are updated, we may want to make the above requirement more |
103 | | /// relaxed, as it seems desirable for users of this interface to have guaranteed |
104 | | /// behavior (like error on invalid paths) whereas today this seems unclear as some |
105 | | /// command intercepts do not validate that the command is in fact accepted on the |
106 | | /// endpoint provided. |
107 | | /// |
108 | | /// Return value expectations: |
109 | | /// - if a response has been placed into `handler` then std::nullopt MUST be returned. In particular |
110 | | /// note that CHIP_NO_ERROR is NOT the same as std::nullopt: |
111 | | /// > CHIP_NO_ERROR means handler had no status set and we expect the caller to AddStatus(success) |
112 | | /// > std::nullopt means that handler has added an appropriate data/status response |
113 | | /// - if a value is returned (not nullopt) then the handler response MUST NOT be filled. The caller |
114 | | /// will then issue `handler->AddStatus(request.path, <return_value>->GetStatusCode())`. This is a |
115 | | /// convenience to make writing Invoke calls easier. |
116 | | virtual std::optional<ActionReturnStatus> InvokeCommand(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, |
117 | | CommandHandler * handler) = 0; |
118 | | }; |
119 | | |
120 | | } // namespace DataModel |
121 | | } // namespace app |
122 | | } // namespace chip |