Skip to content

Commit 596e892

Browse files
lpbeliveau-silabshuangxuyong
authored andcommitted
[ICD] StayActiveRequest (project-chip#32247)
* Implementation of StayActive request with test * Regenerated zap files * Added StayActiveRequest scenarios to the yaml test * Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> Applied comments about #if and clarifying maximum guaranteed stay active * Added the #if back for platforms that build the icd-management-server cluster without being ICD devices * Applied suggestions
1 parent 102f890 commit 596e892

File tree

41 files changed

+377
-67
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+377
-67
lines changed

examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 {
13371337
optional octet_string<16> verificationKey = 1;
13381338
}
13391339

1340+
request struct StayActiveRequestRequest {
1341+
int32u stayActiveDuration = 0;
1342+
}
1343+
13401344
response struct StayActiveResponse = 4 {
13411345
int32u promisedActiveDuration = 0;
13421346
}
@@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 {
13461350
/** Unregister a client from an end device */
13471351
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
13481352
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1349-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1353+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
13501354
}
13511355

13521356
endpoint 0 {

examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 {
13371337
optional octet_string<16> verificationKey = 1;
13381338
}
13391339

1340+
request struct StayActiveRequestRequest {
1341+
int32u stayActiveDuration = 0;
1342+
}
1343+
13401344
response struct StayActiveResponse = 4 {
13411345
int32u promisedActiveDuration = 0;
13421346
}
@@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 {
13461350
/** Unregister a client from an end device */
13471351
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
13481352
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1349-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1353+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
13501354
}
13511355

13521356
endpoint 0 {

examples/light-switch-app/light-switch-common/light-switch-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,10 @@ cluster IcdManagement = 70 {
20072007
optional octet_string<16> verificationKey = 1;
20082008
}
20092009

2010+
request struct StayActiveRequestRequest {
2011+
int32u stayActiveDuration = 0;
2012+
}
2013+
20102014
response struct StayActiveResponse = 4 {
20112015
int32u promisedActiveDuration = 0;
20122016
}
@@ -2016,7 +2020,7 @@ cluster IcdManagement = 70 {
20162020
/** Unregister a client from an end device */
20172021
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
20182022
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
2019-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
2023+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
20202024
}
20212025

20222026
/** Attributes and commands for scene configuration and manipulation. */

examples/light-switch-app/qpg/zap/switch.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,10 @@ cluster IcdManagement = 70 {
18041804
optional octet_string<16> verificationKey = 1;
18051805
}
18061806

1807+
request struct StayActiveRequestRequest {
1808+
int32u stayActiveDuration = 0;
1809+
}
1810+
18071811
response struct StayActiveResponse = 4 {
18081812
int32u promisedActiveDuration = 0;
18091813
}
@@ -1813,7 +1817,7 @@ cluster IcdManagement = 70 {
18131817
/** Unregister a client from an end device */
18141818
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
18151819
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1816-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1820+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
18171821
}
18181822

18191823
/** Attributes and commands for scene configuration and manipulation. */

examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1465,6 +1465,10 @@ cluster IcdManagement = 70 {
14651465
optional octet_string<16> verificationKey = 1;
14661466
}
14671467

1468+
request struct StayActiveRequestRequest {
1469+
int32u stayActiveDuration = 0;
1470+
}
1471+
14681472
response struct StayActiveResponse = 4 {
14691473
int32u promisedActiveDuration = 0;
14701474
}
@@ -1474,7 +1478,7 @@ cluster IcdManagement = 70 {
14741478
/** Unregister a client from an end device */
14751479
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
14761480
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1477-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1481+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
14781482
}
14791483

14801484
endpoint 0 {

examples/lock-app/lock-common/lock-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,10 @@ cluster IcdManagement = 70 {
18251825
optional octet_string<16> verificationKey = 1;
18261826
}
18271827

1828+
request struct StayActiveRequestRequest {
1829+
int32u stayActiveDuration = 0;
1830+
}
1831+
18281832
response struct StayActiveResponse = 4 {
18291833
int32u promisedActiveDuration = 0;
18301834
}
@@ -1834,7 +1838,7 @@ cluster IcdManagement = 70 {
18341838
/** Unregister a client from an end device */
18351839
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
18361840
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1837-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1841+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
18381842
}
18391843

18401844
/** An interface to a generic way to secure a door */

examples/lock-app/lock-common/lock-app.zap

+5-4
Original file line numberDiff line numberDiff line change
@@ -2412,10 +2412,10 @@
24122412
"side": "server",
24132413
"type": "bitmap32",
24142414
"included": 1,
2415-
"storageOption": "RAM",
2415+
"storageOption": "External",
24162416
"singleton": 0,
24172417
"bounded": 0,
2418-
"defaultValue": "0",
2418+
"defaultValue": null,
24192419
"reportable": 1,
24202420
"minInterval": 1,
24212421
"maxInterval": 65534,
@@ -2428,10 +2428,10 @@
24282428
"side": "server",
24292429
"type": "int16u",
24302430
"included": 1,
2431-
"storageOption": "RAM",
2431+
"storageOption": "External",
24322432
"singleton": 0,
24332433
"bounded": 0,
2434-
"defaultValue": "0x0002",
2434+
"defaultValue": null,
24352435
"reportable": 1,
24362436
"minInterval": 0,
24372437
"maxInterval": 65344,
@@ -4939,6 +4939,7 @@
49394939
"define": "ICD_MANAGEMENT_CLUSTER",
49404940
"side": "server",
49414941
"enabled": 1,
4942+
"commands": [],
49424943
"attributes": [
49434944
{
49444945
"name": "IdleModeDuration",

examples/lock-app/qpg/zap/lock.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,10 @@ cluster IcdManagement = 70 {
14811481
optional octet_string<16> verificationKey = 1;
14821482
}
14831483

1484+
request struct StayActiveRequestRequest {
1485+
int32u stayActiveDuration = 0;
1486+
}
1487+
14841488
response struct StayActiveResponse = 4 {
14851489
int32u promisedActiveDuration = 0;
14861490
}
@@ -1490,7 +1494,7 @@ cluster IcdManagement = 70 {
14901494
/** Unregister a client from an end device */
14911495
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
14921496
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1493-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1497+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
14941498
}
14951499

14961500
/** An interface to a generic way to secure a door */

examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,10 @@ cluster IcdManagement = 70 {
18011801
optional octet_string<16> verificationKey = 1;
18021802
}
18031803

1804+
request struct StayActiveRequestRequest {
1805+
int32u stayActiveDuration = 0;
1806+
}
1807+
18041808
response struct StayActiveResponse = 4 {
18051809
int32u promisedActiveDuration = 0;
18061810
}
@@ -1810,7 +1814,7 @@ cluster IcdManagement = 70 {
18101814
/** Unregister a client from an end device */
18111815
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
18121816
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1813-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1817+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
18141818
}
18151819

18161820
/** This cluster provides an interface for observing and managing the state of smoke and CO alarms. */

examples/window-app/common/window-app.matter

+5-1
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,10 @@ cluster IcdManagement = 70 {
18991899
optional octet_string<16> verificationKey = 1;
19001900
}
19011901

1902+
request struct StayActiveRequestRequest {
1903+
int32u stayActiveDuration = 0;
1904+
}
1905+
19021906
response struct StayActiveResponse = 4 {
19031907
int32u promisedActiveDuration = 0;
19041908
}
@@ -1908,7 +1912,7 @@ cluster IcdManagement = 70 {
19081912
/** Unregister a client from an end device */
19091913
fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2;
19101914
/** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */
1911-
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
1915+
command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3;
19121916
}
19131917

19141918
/** Provides an interface for controlling and adjusting automatic window coverings. */

src/app/clusters/icd-management-server/icd-management-server.cpp

+8-12
Original file line numberDiff line numberDiff line change
@@ -364,14 +364,6 @@ void ICDManagementServer::TriggerICDMTableUpdatedEvent()
364364

365365
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
366366

367-
Status ICDManagementServer::StayActiveRequest(FabricIndex fabricIndex)
368-
{
369-
// TODO: Implementent stay awake logic for end device
370-
// https://github.com/project-chip/connectedhomeip/issues/24259
371-
ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDListener::ICDManagementEvents::kStayActiveRequestReceived);
372-
return InteractionModel::Status::UnsupportedCommand;
373-
}
374-
375367
void ICDManagementServer::Init(PersistentStorageDelegate & storage, Crypto::SymmetricKeystore * symmetricKeystore,
376368
ICDConfigurationData & icdConfigurationData)
377369
{
@@ -433,10 +425,14 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * comman
433425
bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath,
434426
const Commands::StayActiveRequest::DecodableType & commandData)
435427
{
436-
ICDManagementServer server;
437-
InteractionModel::Status status = server.StayActiveRequest(commandObj->GetAccessingFabricIndex());
438-
439-
commandObj->AddStatus(commandPath, status);
428+
// Note: We only need this #if statement for platform examples that enable the ICD management server without building the sample
429+
// as an ICD. Since this is not spec compliant, we should remove this #if statement once we stop compiling the ICD management
430+
// server in those examples.
431+
#if CHIP_CONFIG_ENABLE_ICD_SERVER
432+
IcdManagement::Commands::StayActiveResponse::Type response;
433+
response.promisedActiveDuration = Server::GetInstance().GetICDManager().StayActiveRequest(commandData.stayActiveDuration);
434+
commandObj->AddResponse(commandPath, response);
435+
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
440436
return true;
441437
}
442438

src/app/clusters/icd-management-server/icd-management-server.h

-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ class ICDManagementServer
6868
const chip::app::Clusters::IcdManagement::Commands::UnregisterClient::DecodableType & commandData);
6969
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
7070

71-
chip::Protocols::InteractionModel::Status StayActiveRequest(chip::FabricIndex fabricIndex);
72-
7371
private:
7472
#if CHIP_CONFIG_ENABLE_ICD_CIP
7573
/**

src/app/icd/server/ICDConfigurationData.h

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class ICDConfigurationData
6161

6262
System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; }
6363

64+
System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; }
65+
6466
Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; }
6567

6668
uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; }
@@ -123,6 +125,9 @@ class ICDConfigurationData
123125

124126
static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour);
125127
static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1);
128+
// As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application
129+
// Clusters: 9.17.7.5.1. PromisedActiveDuration Field"
130+
static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000);
126131

127132
static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(),
128133
"Spec requires the IdleModeDuration to be equal or inferior to 64800s.");

src/app/icd/server/ICDManager.cpp

+30-16
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,22 @@ bool ICDManager::SupportsFeature(Feature feature)
120120
#endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST
121121
}
122122

123+
uint32_t ICDManager::StayActiveRequest(uint32_t stayActiveDuration)
124+
{
125+
// This should only be called when the device is in ActiveMode
126+
VerifyOrReturnValue(mOperationalState == OperationalState::ActiveMode, 0);
127+
128+
uint32_t promisedActiveDuration =
129+
std::min(ICDConfigurationData::GetInstance().GetGuaranteedStayActiveDuration().count(), stayActiveDuration);
130+
131+
// If the device is already in ActiveMode, we need to extend the active mode duration
132+
// for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking in account the remaining active time.
133+
ExtendActiveMode(System::Clock::Milliseconds16(promisedActiveDuration));
134+
promisedActiveDuration = DeviceLayer::SystemLayer().GetRemainingTime(OnActiveModeDone, this).count();
135+
136+
return promisedActiveDuration;
137+
}
138+
123139
#if CHIP_CONFIG_ENABLE_ICD_CIP
124140
void ICDManager::SendCheckInMsgs()
125141
{
@@ -366,17 +382,7 @@ void ICDManager::UpdateOperationState(OperationalState state)
366382
}
367383
else
368384
{
369-
Milliseconds16 activeModeThreshold = ICDConfigurationData::GetInstance().GetActiveModeThreshold();
370-
DeviceLayer::SystemLayer().ExtendTimerTo(activeModeThreshold, OnActiveModeDone, this);
371-
372-
Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS);
373-
activeModeJitterThreshold =
374-
(activeModeThreshold >= activeModeJitterThreshold) ? activeModeThreshold - activeModeJitterThreshold : kZero;
375-
376-
if (!mTransitionToIdleCalled)
377-
{
378-
DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this);
379-
}
385+
ExtendActiveMode(ICDConfigurationData::GetInstance().GetActiveModeThreshold());
380386
}
381387
}
382388
}
@@ -521,11 +527,6 @@ void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event)
521527
case ICDManagementEvents::kTableUpdated:
522528
this->UpdateICDMode();
523529
break;
524-
525-
case ICDManagementEvents::kStayActiveRequestReceived:
526-
// TODO : Implement the StayActiveRequest
527-
// https://github.com/project-chip/connectedhomeip/issues/24259
528-
break;
529530
default:
530531
break;
531532
}
@@ -540,6 +541,19 @@ void ICDManager::OnSubscriptionReport()
540541
this->UpdateOperationState(OperationalState::ActiveMode);
541542
}
542543

544+
void ICDManager::ExtendActiveMode(Milliseconds16 extendDuration)
545+
{
546+
DeviceLayer::SystemLayer().ExtendTimerTo(extendDuration, OnActiveModeDone, this);
547+
548+
Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS);
549+
activeModeJitterThreshold = (extendDuration >= activeModeJitterThreshold) ? extendDuration - activeModeJitterThreshold : kZero;
550+
551+
if (!mTransitionToIdleCalled)
552+
{
553+
DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this);
554+
}
555+
}
556+
543557
ICDManager::ObserverPointer * ICDManager::RegisterObserver(ICDStateObserver * observer)
544558
{
545559
return mStateObserverPool.CreateObject(observer);

src/app/icd/server/ICDManager.h

+14
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ class ICDManager : public ICDListener
109109
void postObserverEvent(ObserverEventType event);
110110
OperationalState GetOperationalState() { return mOperationalState; }
111111

112+
/**
113+
* @brief Ensures that the remaining Active Mode duration is at least the smaller of 30000 milliseconds and stayActiveDuration.
114+
*
115+
* @param stayActiveDuration The duration (in milliseconds) requested by the client to stay in Active Mode
116+
* @return The duration (in milliseconds) the device will stay in Active Mode
117+
*/
118+
uint32_t StayActiveRequest(uint32_t stayActiveDuration);
119+
112120
#if CHIP_CONFIG_ENABLE_ICD_CIP
113121
void SendCheckInMsgs();
114122

@@ -131,6 +139,12 @@ class ICDManager : public ICDListener
131139
void OnSubscriptionReport() override;
132140

133141
protected:
142+
/**
143+
* @brief Hepler function that extends the Active Mode duration as well as the Active Mode Jitter timer for the transition to
144+
* iddle mode.
145+
*/
146+
void ExtendActiveMode(System::Clock::Milliseconds16 extendDuration);
147+
134148
friend class TestICDManager;
135149

136150
static void OnIdleModeDone(System::Layer * aLayer, void * appState);

src/app/icd/server/ICDNotifier.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ class ICDListener
4848

4949
enum class ICDManagementEvents : uint8_t
5050
{
51-
kTableUpdated = 0x01,
52-
kStayActiveRequestReceived = 0x02,
51+
kTableUpdated = 0x01,
5352
};
5453

5554
using KeepActiveFlags = BitFlags<KeepActiveFlagsValues>;

0 commit comments

Comments
 (0)