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 192 : static ICDConfigurationData & GetInstance() { return instance; };
61 :
62 31 : System::Clock::Seconds32 GetIdleModeDuration() { return mIdleModeDuration; }
63 :
64 56 : 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 20 : ICDMode GetICDMode() { return mICDMode; }
96 :
97 : private:
98 : // Singleton Object
99 3 : ICDConfigurationData()
100 6 : {
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 3 : }
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 10 : void SetICDMode(ICDMode mode) { mICDMode = mode; };
126 : void SetSlowPollingInterval(System::Clock::Milliseconds32 slowPollInterval) { mSlowPollingInterval = slowPollInterval; };
127 : void SetFastPollingInterval(System::Clock::Milliseconds32 fastPollInterval) { mFastPollingInterval = fastPollInterval; };
128 :
129 : static constexpr System::Clock::Milliseconds16 kMinLitActiveModeThreshold = System::Clock::Milliseconds16(5000);
130 :
131 : /**
132 : * @brief Change the ActiveModeDuration or the IdleModeDuration value
133 : * If only one value is provided, check will be done agaisn't the other already set value.
134 : *
135 : * @param[in] activeModeDuration new ActiveModeDuration value
136 : * @param[in] idleModeDuration new IdleModeDuration value
137 : * The precision of the IdleModeDuration must be seconds.
138 : * @return CHIP_ERROR CHIP_ERROR_INVALID_ARGUMENT is returned if idleModeDuration_ms is smaller than activeModeDuration_ms
139 : * is returned if idleModeDuration_ms is greater than 64800000 ms
140 : * is returned if idleModeDuration_ms is smaller than 1000 ms
141 : * is returned if no valid values are provided
142 : * CHIP_NO_ERROR is returned if the new intervals were set
143 : */
144 : CHIP_ERROR SetModeDurations(Optional<System::Clock::Milliseconds32> activeModeDuration,
145 : Optional<System::Clock::Milliseconds32> idleModeDuration);
146 :
147 : void SetFeatureMap(BitFlags<app::Clusters::IcdManagement::Feature> featureMap) { mFeatureMap = featureMap; }
148 :
149 : static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour);
150 : static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1);
151 : // As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application
152 : // Clusters: 9.17.7.5.1. PromisedActiveDuration Field"
153 : static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000);
154 :
155 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(),
156 : "Spec requires the IdleModeDuration to be equal or inferior to 64800s.");
157 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= kMinIdleModeDuration.count(),
158 : "Spec requires the IdleModeDuration to be equal or greater to 1s.");
159 3 : System::Clock::Seconds32 mIdleModeDuration = System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC);
160 :
161 : static_assert(System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <=
162 : System::Clock::Seconds32(CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC),
163 : "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration.");
164 3 : System::Clock::Milliseconds32 mActiveModeDuration = System::Clock::Milliseconds32(CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS);
165 :
166 3 : System::Clock::Milliseconds16 mActiveThreshold = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS);
167 :
168 : Protocols::SecureChannel::CheckInCounter mICDCounter;
169 :
170 : static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1,
171 : "Spec requires the minimum of supported clients per fabric be equal or greater to 1.");
172 : uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC;
173 :
174 : static_assert((CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC) <= kMaxIdleModeDuration.count(),
175 : "Spec requires the MaximumCheckInBackOff to be equal or inferior to 64800s");
176 : static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= (CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC),
177 : "Spec requires the MaximumCheckInBackOff to be equal or superior to the IdleModeDuration");
178 3 : System::Clock::Seconds32 mMaximumCheckInBackOff = System::Clock::Seconds32(CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC);
179 :
180 : // SIT ICDs SHALL have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5)
181 : static constexpr System::Clock::Milliseconds32 kSitIcdSlowPollMaximum = System::Clock::Milliseconds32(15000);
182 : static_assert((CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT).count() <= kSitIcdSlowPollMaximum.count(),
183 : "Spec requires the maximum slow poll interval for the SIT device to be smaller or equal than 15 s.");
184 : static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = CHIP_DEVICE_CONFIG_ICD_SIT_SLOW_POLL_LIMIT;
185 :
186 : #if CHIP_CONFIG_ENABLE_ICD_LIT == 0
187 : static_assert((CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL <= kSitIcdSlowPollMaximum),
188 : "LIT support is required for slow polling intervals superior to 15 seconds");
189 : #endif
190 3 : System::Clock::Milliseconds32 mSlowPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL;
191 3 : System::Clock::Milliseconds32 mFastPollingInterval = CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL;
192 :
193 : BitFlags<app::Clusters::IcdManagement::Feature> mFeatureMap;
194 :
195 : ICDMode mICDMode = ICDMode::SIT;
196 : };
197 :
198 : } // namespace chip
|