Line data Source code
1 : /**
2 : *
3 : * Copyright (c) 2023 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-enums.h>
21 : #include <app/icd/server/ICDServerConfig.h>
22 : #include <lib/core/Optional.h>
23 : #include <lib/support/BitFlags.h>
24 : #include <lib/support/TimeUtils.h>
25 : #include <optional>
26 : #include <platform/CHIPDeviceConfig.h>
27 : #include <protocols/secure_channel/CheckInCounter.h>
28 : #include <system/SystemClock.h>
29 :
30 : namespace chip {
31 :
32 : namespace app {
33 : // Forward declaration of ICDManager to allow it to be friend with ICDConfigurationData.
34 : class ICDManager;
35 : } // namespace app
36 :
37 : namespace Testing {
38 : // Forward declaration of ICDConfigurationDataTestAccess tests to allow it to be friend with the ICDConfigurationData.
39 : // Used in unit tests
40 : class ICDConfigurationDataTestAccess;
41 : } // namespace Testing
42 :
43 : /**
44 : * @brief ICDConfigurationData manages and stores ICD related configurations for the ICDManager.
45 : * Goal of the class is to expose ICD information to all consummers without creating circular dependencies
46 : * since the ICDManager is appart of the App layer
47 : *
48 : * Anyone can read the ICD configurations but only the ICDManager can changes those configurations.
49 : */
50 : class ICDConfigurationData
51 : {
52 : public:
53 : static constexpr uint32_t kICDCounterPersistenceIncrement = 100;
54 :
55 : enum class ICDMode : uint8_t
56 : {
57 : SIT, // Short Interval Time ICD
58 : LIT, // Long Interval Time ICD
59 : };
60 :
61 141 : static ICDConfigurationData & GetInstance() { return instance; };
62 :
63 : // This represents the ICDManagement Cluster's fixed value mIdleModeDuration Attribute
64 2 : System::Clock::Seconds32 GetIdleModeDuration() { return mIdleModeDuration; }
65 :
66 58 : System::Clock::Milliseconds32 GetActiveModeDuration() { return mActiveModeDuration; }
67 :
68 11 : System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; }
69 :
70 4 : System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; }
71 :
72 : Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; }
73 :
74 : uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; }
75 :
76 10 : System::Clock::Milliseconds32 GetSITPollingThreshold() { return kSITPollingThreshold; }
77 :
78 16 : System::Clock::Milliseconds32 GetFastPollingInterval() { return mFastPollingInterval; }
79 :
80 : System::Clock::Milliseconds16 GetMinLitActiveModeThreshold() { return kMinLitActiveModeThreshold; }
81 :
82 : System::Clock::Seconds32 GetMaximumCheckInBackoff() { return mMaximumCheckInBackOff; }
83 :
84 4 : BitFlags<app::Clusters::IcdManagement::Feature> GetFeatureMap() { return mFeatureMap; }
85 :
86 : /**
87 : * The returned value will depend on the devices operating mode.
88 : * If ICDMode == SIT && the configured slow poll interval is superior to the maximum threshold (15s), the function will return
89 : * the threshold kSITPollingThreshold (<= 15s). If ICDMode == SIT but the configured slow poll interval is equal or inferior to
90 : * the threshold, the function will the return the configured slow poll interval. If ICDMode == LIT, the function will return
91 : * the configured slow poll interval.
92 : *
93 : * @return System::Clock::Milliseconds32
94 : */
95 : System::Clock::Milliseconds32 GetSlowPollingInterval();
96 :
97 : /**
98 : * @brief Indicates if the device should apply the ShortIdleModeDuration instead of the normal IdleModeDuration.
99 : *
100 : * Uses ShortIdle only when:
101 : * - ShortIdleModeDuration < IdleModeDuration
102 : * - Long Idle Time feature is supported
103 : * - Device currently operates in SIT mode
104 : *
105 : * NOTE: To make full use of the ShortIdleModeDuration, users SHOULD also set ICD_REPORT_ON_ENTER_ACTIVE_MODE
106 : *
107 : * @return true if ShortIdleModeDuration shall be used, false otherwise.
108 : */
109 : bool ShouldUseShortIdle();
110 :
111 : /**
112 : * @brief Returns the appropriate Idle duration based on current operating conditions.
113 : *
114 : * If ShouldUseShortIdle() is true, returns ShortIdleModeDuration; otherwise returns IdleModeDuration.
115 : *
116 : * @return Effective IdleMode duration in seconds.
117 : */
118 : System::Clock::Seconds32 GetModeBasedIdleModeDuration();
119 :
120 27 : ICDMode GetICDMode() { return mICDMode; }
121 :
122 : private:
123 : // Singleton Object
124 63 : ICDConfigurationData()
125 126 : {
126 : // Initialize feature map
127 : #if CHIP_CONFIG_ENABLE_ICD_CIP
128 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kCheckInProtocolSupport);
129 : #endif // CHIP_CONFIG_ENABLE_ICD_CIP
130 : #if CHIP_CONFIG_ENABLE_ICD_UAT
131 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kUserActiveModeTrigger);
132 : #endif // CHIP_CONFIG_ENABLE_ICD_UAT
133 : #if CHIP_CONFIG_ENABLE_ICD_LIT
134 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kLongIdleTimeSupport);
135 : #if CHIP_CONFIG_ENABLE_ICD_DSLS
136 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kDynamicSitLitSupport);
137 : #endif // CHIP_CONFIG_ENABLE_ICD_DSLS
138 : #endif // CHIP_CONFIG_ENABLE_ICD_LIT
139 63 : }
140 : static ICDConfigurationData instance;
141 :
142 : // ICD related information is managed by the ICDManager but stored in the ICDConfigurationData to enable consummers to access it
143 : // without creating a circular dependency. To avoid allowing consummers changing the state of the ICD mode without going through
144 : // the ICDManager, the ICDManager is a friend that can access the private setters. If a consummer needs to be notified when a
145 : // value is changed, they can leverage the Observer events the ICDManager generates. See src/app/icd/server/ICDStateObserver.h
146 : friend class chip::app::ICDManager;
147 :
148 : friend class chip::Testing::ICDConfigurationDataTestAccess;
149 :
150 16 : void SetICDMode(ICDMode mode) { mICDMode = mode; };
151 : void SetFastPollingInterval(System::Clock::Milliseconds32 fastPollInterval) { mFastPollingInterval = fastPollInterval; };
152 :
153 : /**
154 : * @brief Sets the slow polling interval for the ICD.
155 : *
156 : * If LIT support is not enabled, the interval cannot be set higher than the SIT polling threshold.
157 : * If LIT support is enabled, any value is accepted.
158 : *
159 : * @param[in] slowPollInterval The slow polling interval in milliseconds.
160 : * @return CHIP_ERROR CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if the value is invalid.
161 : */
162 : CHIP_ERROR SetSlowPollingInterval(System::Clock::Milliseconds32 slowPollInterval);
163 :
164 : /**
165 : * @brief Sets the SIT Idle polling interval.
166 : *
167 : * This function sets the slow/idle polling interval, which is used when the configured
168 : * slow polling interval exceeds the allowed threshold for SIT mode. The provided value must
169 : * be less than, or equal to the SIT polling threshold (kSITPollingThreshold).
170 : *
171 : * This SIT Slow Polling configuration allows ICD LIT device to configure a longer SlowPollingInterval
172 : * when operating as LIT, but use a faster SlowPollingInterval when the device must operate in SIT mode
173 : *
174 : * @param[in] pollingInterval The SIT slow polling interval in milliseconds.
175 : * @return CHIP_ERROR CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if the value is invalid.
176 : */
177 : CHIP_ERROR SetSITPollingInterval(System::Clock::Milliseconds32 pollingInterval);
178 :
179 : static constexpr System::Clock::Milliseconds16 kMinLitActiveModeThreshold = System::Clock::Milliseconds16(5000);
180 :
181 : /**
182 : * @brief Change the ActiveModeDuration or the IdleModeDuration value
183 : * If only one value is provided, check will be done agaisn't the other already set value.
184 : *
185 : * @param[in] activeModeDuration new ActiveModeDuration value
186 : * @param[in] idleModeDuration new IdleModeDuration value
187 : * The precision of the IdleModeDuration must be seconds.
188 : * Note: mIdleModeDuration is expressed in seconds. The idleModeDuration parameter is in milliseconds for backward compatibility
189 : * reasons. The conversion to seconds is done inside the function.
190 : *
191 : * @return CHIP_ERROR CHIP_ERROR_INVALID_ARGUMENT is returned if idleModeDuration_ms is smaller than activeModeDuration_ms
192 : * is returned if idleModeDuration_ms is greater than 64800000 ms
193 : * is returned if idleModeDuration_ms is smaller than 1000 ms
194 : * is returned if no valid values are provided
195 : * CHIP_NO_ERROR is returned if the new intervals were set
196 : */
197 : CHIP_ERROR SetModeDurations(Optional<System::Clock::Milliseconds32> activeModeDuration,
198 : Optional<System::Clock::Milliseconds32> idleModeDuration);
199 :
200 : /**
201 : * @brief Change the ActiveModeDuration, IdleModeDuration and/or ShortIdleModeDuration values.
202 : *
203 : * At least one of the three parameters must be provided. Omitted parameters keep their current stored values.
204 : *
205 : * Constraints:
206 : * - activeModeDuration (ms) must be <= resulting idleModeDuration (s)
207 : * - idleModeDuration (s) must be within [kMinIdleModeDuration, kMaxIdleModeDuration]
208 : * - shortIdleModeDuration (s) must be <= resulting idleModeDuration (s)
209 : *
210 : * NOTE: to keep previous behavior, If shortIdleModeDuration is not provided, mShortIdleModeDuration can be clamped to resulting
211 : * idleModeDuration if the later becomes lesser than the previous mShortIdleModeDuration.
212 : *
213 : * @param[in] activeModeDuration New ActiveModeDuration in milliseconds (optional).
214 : * @param[in] idleModeDuration New IdleModeDuration in seconds (optional).
215 : * @param[in] shortIdleModeDuration New ShortIdleModeDuration in seconds (optional, must not exceed IdleModeDuration).
216 : *
217 : * @return CHIP_NO_ERROR on success.
218 : * @return CHIP_ERROR_INVALID_ARGUMENT when:
219 : * - no parameter is provided
220 : * - activeModeDuration > resulting idleModeDuration
221 : * - idleModeDuration is greater than 64800 s or is smaller than 1 s
222 : * - shortIdleModeDuration > resulting idleModeDuration
223 : */
224 : CHIP_ERROR SetModeDurations(std::optional<System::Clock::Milliseconds32> activeModeDuration,
225 : std::optional<System::Clock::Seconds32> idleModeDuration,
226 : std::optional<System::Clock::Seconds32> shortIdleModeDuration);
227 :
228 2 : void SetFeatureMap(BitFlags<app::Clusters::IcdManagement::Feature> featureMap) { mFeatureMap = featureMap; }
229 :
230 : static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour);
231 : static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1);
232 : // As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application
233 : // Clusters: 9.17.7.5.1. PromisedActiveDuration Field"
234 : static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000);
235 :
236 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(),
237 : "Spec requires the IdleModeDuration to be equal or inferior to 64800s.");
238 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= kMinIdleModeDuration.count(),
239 : "Spec requires the IdleModeDuration to be equal or greater to 1s.");
240 63 : System::Clock::Seconds32 mIdleModeDuration = System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC);
241 :
242 : // Shorter idleModeDuration when a LIT capable device operates in SIT mode.
243 63 : System::Clock::Seconds32 mShortIdleModeDuration = System::Clock::Seconds32(CHIP_CONFIG_ICD_SHORT_IDLE_MODE_DURATION_SEC);
244 : static_assert((CHIP_CONFIG_ICD_SHORT_IDLE_MODE_DURATION_SEC <= CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC),
245 : "mShortIdleModeDuration must be lesser or equal than mIdleModeDuration.");
246 :
247 : static_assert(System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <=
248 : System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC),
249 : "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration.");
250 63 : System::Clock::Milliseconds32 mActiveModeDuration = System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS);
251 :
252 63 : System::Clock::Milliseconds16 mActiveThreshold = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS);
253 :
254 : Protocols::SecureChannel::CheckInCounter mICDCounter;
255 :
256 : static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1,
257 : "Spec requires the minimum of supported clients per fabric be equal or greater to 1.");
258 : uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC;
259 :
260 : static_assert((CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC) <= kMaxIdleModeDuration.count(),
261 : "Spec requires the MaximumCheckInBackOff to be equal or inferior to 64800s");
262 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= (CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC),
263 : "Spec requires the MaximumCheckInBackOff to be equal or superior to the IdleModeDuration");
264 63 : System::Clock::Seconds32 mMaximumCheckInBackOff = System::Clock::Seconds32(CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC);
265 :
266 : // SIT ICDs SHALL have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5)
267 : static constexpr System::Clock::Milliseconds32 kSitIcdSlowPollMaximum = System::Clock::Milliseconds32(15000);
268 : static_assert((CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT).count() <= kSitIcdSlowPollMaximum.count(),
269 : "Spec requires the maximum slow poll interval for the SIT device to be smaller or equal than 15 s.");
270 : static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT;
271 :
272 : #if CHIP_CONFIG_ENABLE_ICD_LIT == 0
273 : static_assert((CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL <= kSitIcdSlowPollMaximum),
274 : "LIT support is required for slow polling intervals superior to 15 seconds");
275 : #endif
276 : // The Polling interval used in Idle mode
277 63 : System::Clock::Milliseconds32 mLITPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL;
278 : // The Polling interval used in Active mode
279 63 : System::Clock::Milliseconds32 mFastPollingInterval = CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL;
280 :
281 : static_assert((CHIP_DEVICE_CONFIG_ICD_SIT_POLLING_INTERVAL <= kSitIcdSlowPollMaximum),
282 : "The SIT polling intervals must not exceed 15 seconds");
283 : // The Polling interval used in Idle mode when a LIT capable device operates in SIT mode and that is mLITPollingInterval is
284 : // greater than mSITPollingInterval
285 63 : System::Clock::Milliseconds32 mSITPollingInterval = CHIP_DEVICE_CONFIG_ICD_SIT_POLLING_INTERVAL;
286 :
287 : BitFlags<app::Clusters::IcdManagement::Feature> mFeatureMap;
288 :
289 : ICDMode mICDMode = ICDMode::SIT;
290 : };
291 :
292 : } // namespace chip
|