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 <platform/CHIPDeviceConfig.h>
26 : #include <protocols/secure_channel/CheckInCounter.h>
27 : #include <system/SystemClock.h>
28 :
29 : namespace chip {
30 :
31 : namespace app {
32 : // Forward declaration of ICDManager to allow it to be friend with ICDConfigurationData.
33 : class ICDManager;
34 : } // namespace app
35 :
36 : namespace Test {
37 : // Forward declaration of ICDConfigurationDataTestAccess tests to allow it to be friend with the ICDConfigurationData.
38 : // Used in unit tests
39 : class ICDConfigurationDataTestAccess;
40 : } // namespace Test
41 :
42 : /**
43 : * @brief ICDConfigurationData manages and stores ICD related configurations for the ICDManager.
44 : * Goal of the class is to expose ICD information to all consummers without creating circular dependencies
45 : * since the ICDManager is appart of the App layer
46 : *
47 : * Anyone can read the ICD configurations but only the ICDManager can changes those configurations.
48 : */
49 : class ICDConfigurationData
50 : {
51 : public:
52 : static constexpr uint32_t kICDCounterPersistenceIncrement = 100;
53 :
54 : enum class ICDMode : uint8_t
55 : {
56 : SIT, // Short Interval Time ICD
57 : LIT, // Long Interval Time ICD
58 : };
59 :
60 202 : static ICDConfigurationData & GetInstance() { return instance; };
61 :
62 33 : System::Clock::Seconds32 GetIdleModeDuration() { return mIdleModeDuration; }
63 :
64 58 : System::Clock::Milliseconds32 GetActiveModeDuration() { return mActiveModeDuration; }
65 :
66 11 : System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; }
67 :
68 4 : System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; }
69 :
70 : Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; }
71 :
72 : uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; }
73 :
74 10 : System::Clock::Milliseconds32 GetSITPollingThreshold() { return kSITPollingThreshold; }
75 :
76 16 : System::Clock::Milliseconds32 GetFastPollingInterval() { return mFastPollingInterval; }
77 :
78 : System::Clock::Milliseconds16 GetMinLitActiveModeThreshold() { return kMinLitActiveModeThreshold; }
79 :
80 : System::Clock::Seconds32 GetMaximumCheckInBackoff() { return mMaximumCheckInBackOff; }
81 :
82 0 : BitFlags<app::Clusters::IcdManagement::Feature> GetFeatureMap() { return mFeatureMap; }
83 :
84 : /**
85 : * The returned value will depend on the devices operating mode.
86 : * If ICDMode == SIT && the configured slow poll interval is superior to the maximum threshold (15s), the function will return
87 : * the threshold kSITPollingThreshold (<= 15s). If ICDMode == SIT but the configured slow poll interval is equal or inferior to
88 : * the threshold, the function will the return the configured slow poll interval. If ICDMode == LIT, the function will return
89 : * the configured slow poll interval.
90 : *
91 : * @return System::Clock::Milliseconds32
92 : */
93 : System::Clock::Milliseconds32 GetSlowPollingInterval();
94 :
95 27 : ICDMode GetICDMode() { return mICDMode; }
96 :
97 : private:
98 : // Singleton Object
99 4 : ICDConfigurationData()
100 8 : {
101 : // Initialize feature map
102 : #if CHIP_CONFIG_ENABLE_ICD_CIP
103 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kCheckInProtocolSupport);
104 : #endif // CHIP_CONFIG_ENABLE_ICD_CIP
105 : #if CHIP_CONFIG_ENABLE_ICD_UAT
106 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kUserActiveModeTrigger);
107 : #endif // CHIP_CONFIG_ENABLE_ICD_UAT
108 : #if CHIP_CONFIG_ENABLE_ICD_LIT
109 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kLongIdleTimeSupport);
110 : #if CHIP_CONFIG_ENABLE_ICD_DSLS
111 : mFeatureMap.Set(app::Clusters::IcdManagement::Feature::kDynamicSitLitSupport);
112 : #endif // CHIP_CONFIG_ENABLE_ICD_DSLS
113 : #endif // CHIP_CONFIG_ENABLE_ICD_LIT
114 4 : }
115 : static ICDConfigurationData instance;
116 :
117 : // ICD related information is managed by the ICDManager but stored in the ICDConfigurationData to enable consummers to access it
118 : // without creating a circular dependency. To avoid allowing consummers changing the state of the ICD mode without going through
119 : // the ICDManager, the ICDManager is a friend that can access the private setters. If a consummer needs to be notified when a
120 : // value is changed, they can leverage the Observer events the ICDManager generates. See src/app/icd/server/ICDStateObserver.h
121 : friend class chip::app::ICDManager;
122 :
123 : friend class chip::Test::ICDConfigurationDataTestAccess;
124 :
125 16 : void SetICDMode(ICDMode mode) { mICDMode = mode; };
126 : void SetFastPollingInterval(System::Clock::Milliseconds32 fastPollInterval) { mFastPollingInterval = fastPollInterval; };
127 :
128 : /**
129 : * @brief Sets the slow polling interval for the ICD.
130 : *
131 : * If LIT support is not enabled, the interval cannot be set higher than the SIT polling threshold.
132 : * If LIT support is enabled, any value is accepted.
133 : *
134 : * @param[in] slowPollInterval The slow polling interval in milliseconds.
135 : * @return CHIP_ERROR CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if the value is invalid.
136 : */
137 : CHIP_ERROR SetSlowPollingInterval(System::Clock::Milliseconds32 slowPollInterval);
138 :
139 : /**
140 : * @brief Sets the SIT Idle polling interval.
141 : *
142 : * This function sets the slow/idle polling interval, which is used when the configured
143 : * slow polling interval exceeds the allowed threshold for SIT mode. The provided value must
144 : * be less than, or equal to the SIT polling threshold (kSITPollingThreshold).
145 : *
146 : * This SIT Slow Polling configuration allows ICD LIT device to configure a longer SlowPollingInterval
147 : * when operating as LIT, but use a faster SlowPollingInterval when the device must operate in SIT mode
148 : *
149 : * @param[in] pollingInterval The SIT slow polling interval in milliseconds.
150 : * @return CHIP_ERROR CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if the value is invalid.
151 : */
152 : CHIP_ERROR SetSITPollingInterval(System::Clock::Milliseconds32 pollingInterval);
153 :
154 : static constexpr System::Clock::Milliseconds16 kMinLitActiveModeThreshold = System::Clock::Milliseconds16(5000);
155 :
156 : /**
157 : * @brief Change the ActiveModeDuration or the IdleModeDuration value
158 : * If only one value is provided, check will be done agaisn't the other already set value.
159 : *
160 : * @param[in] activeModeDuration new ActiveModeDuration value
161 : * @param[in] idleModeDuration new IdleModeDuration value
162 : * The precision of the IdleModeDuration must be seconds.
163 : * @return CHIP_ERROR CHIP_ERROR_INVALID_ARGUMENT is returned if idleModeDuration_ms is smaller than activeModeDuration_ms
164 : * is returned if idleModeDuration_ms is greater than 64800000 ms
165 : * is returned if idleModeDuration_ms is smaller than 1000 ms
166 : * is returned if no valid values are provided
167 : * CHIP_NO_ERROR is returned if the new intervals were set
168 : */
169 : CHIP_ERROR SetModeDurations(Optional<System::Clock::Milliseconds32> activeModeDuration,
170 : Optional<System::Clock::Milliseconds32> idleModeDuration);
171 :
172 2 : void SetFeatureMap(BitFlags<app::Clusters::IcdManagement::Feature> featureMap) { mFeatureMap = featureMap; }
173 :
174 : static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour);
175 : static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1);
176 : // As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application
177 : // Clusters: 9.17.7.5.1. PromisedActiveDuration Field"
178 : static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000);
179 :
180 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(),
181 : "Spec requires the IdleModeDuration to be equal or inferior to 64800s.");
182 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= kMinIdleModeDuration.count(),
183 : "Spec requires the IdleModeDuration to be equal or greater to 1s.");
184 4 : System::Clock::Seconds32 mIdleModeDuration = System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC);
185 :
186 : static_assert(System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <=
187 : System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC),
188 : "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration.");
189 4 : System::Clock::Milliseconds32 mActiveModeDuration = System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS);
190 :
191 4 : System::Clock::Milliseconds16 mActiveThreshold = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS);
192 :
193 : Protocols::SecureChannel::CheckInCounter mICDCounter;
194 :
195 : static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1,
196 : "Spec requires the minimum of supported clients per fabric be equal or greater to 1.");
197 : uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC;
198 :
199 : static_assert((CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC) <= kMaxIdleModeDuration.count(),
200 : "Spec requires the MaximumCheckInBackOff to be equal or inferior to 64800s");
201 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= (CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC),
202 : "Spec requires the MaximumCheckInBackOff to be equal or superior to the IdleModeDuration");
203 4 : System::Clock::Seconds32 mMaximumCheckInBackOff = System::Clock::Seconds32(CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC);
204 :
205 : // SIT ICDs SHALL have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5)
206 : static constexpr System::Clock::Milliseconds32 kSitIcdSlowPollMaximum = System::Clock::Milliseconds32(15000);
207 : static_assert((CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT).count() <= kSitIcdSlowPollMaximum.count(),
208 : "Spec requires the maximum slow poll interval for the SIT device to be smaller or equal than 15 s.");
209 : static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT;
210 :
211 : #if CHIP_CONFIG_ENABLE_ICD_LIT == 0
212 : static_assert((CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL <= kSitIcdSlowPollMaximum),
213 : "LIT support is required for slow polling intervals superior to 15 seconds");
214 : #endif
215 : // The Polling interval used in Idle mode
216 4 : System::Clock::Milliseconds32 mLITPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL;
217 : // The Polling interval used in Active mode
218 4 : System::Clock::Milliseconds32 mFastPollingInterval = CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL;
219 :
220 : static_assert((CHIP_DEVICE_CONFIG_ICD_SIT_POLLING_INTERVAL <= kSitIcdSlowPollMaximum),
221 : "The SIT polling intervals must not exceed 15 seconds");
222 : // The Polling interval used in Idle mode when a LIT capable device operates in SIT mode and that is mLITPollingInterval is
223 : // greater than mSITPollingInterval
224 4 : System::Clock::Milliseconds32 mSITPollingInterval = CHIP_DEVICE_CONFIG_ICD_SIT_POLLING_INTERVAL;
225 :
226 : BitFlags<app::Clusters::IcdManagement::Feature> mFeatureMap;
227 :
228 : ICDMode mICDMode = ICDMode::SIT;
229 : };
230 :
231 : } // namespace chip
|