diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index 9a6eeb77ef10f2..fa6101b2586a63 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 479f8baa86284c..f82f6a9ea079d4 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index 90e60581be27da..b96bf908f766ab 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -2007,6 +2007,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -2016,7 +2020,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Attributes and commands for scene configuration and manipulation. */ diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index b7f217d7221b27..0475721b798fe9 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -1804,6 +1804,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1813,7 +1817,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Attributes and commands for scene configuration and manipulation. */ diff --git a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter index db80008fef240c..d4b7f3faa245db 100644 --- a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter +++ b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter @@ -1465,6 +1465,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1474,7 +1478,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index f07b85cfe6de45..1b34782e4ea180 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -1825,6 +1825,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1834,7 +1838,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** An interface to a generic way to secure a door */ diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index c5201e7a6fbb0c..8ec233c5250e71 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -2412,10 +2412,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2428,10 +2428,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x0002", + "defaultValue": null, "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4939,6 +4939,7 @@ "define": "ICD_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, + "commands": [], "attributes": [ { "name": "IdleModeDuration", diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 91ff76970813f1..9815defa7f8cef 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -1481,6 +1481,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1490,7 +1494,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** An interface to a generic way to secure a door */ diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter index 6c1938c578ea27..f3188350035291 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter @@ -1801,6 +1801,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1810,7 +1814,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** This cluster provides an interface for observing and managing the state of smoke and CO alarms. */ diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 7e0053fd83ee39..7f1b3d34943911 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -1899,6 +1899,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1908,7 +1912,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Provides an interface for controlling and adjusting automatic window coverings. */ diff --git a/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 27ecfe778a33bb..0f71345a38d0f1 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -364,14 +364,6 @@ void ICDManagementServer::TriggerICDMTableUpdatedEvent() #endif // CHIP_CONFIG_ENABLE_ICD_CIP -Status ICDManagementServer::StayActiveRequest(FabricIndex fabricIndex) -{ - // TODO: Implementent stay awake logic for end device - // https://github.com/project-chip/connectedhomeip/issues/24259 - ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDListener::ICDManagementEvents::kStayActiveRequestReceived); - return InteractionModel::Status::UnsupportedCommand; -} - void ICDManagementServer::Init(PersistentStorageDelegate & storage, Crypto::SymmetricKeystore * symmetricKeystore, ICDConfigurationData & icdConfigurationData) { @@ -433,10 +425,14 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * comman bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { - ICDManagementServer server; - InteractionModel::Status status = server.StayActiveRequest(commandObj->GetAccessingFabricIndex()); - - commandObj->AddStatus(commandPath, status); +// Note: We only need this #if statement for platform examples that enable the ICD management server without building the sample +// as an ICD. Since this is not spec compliant, we should remove this #if statement once we stop compiling the ICD management +// server in those examples. +#if CHIP_CONFIG_ENABLE_ICD_SERVER + IcdManagement::Commands::StayActiveResponse::Type response; + response.promisedActiveDuration = Server::GetInstance().GetICDManager().StayActiveRequest(commandData.stayActiveDuration); + commandObj->AddResponse(commandPath, response); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER return true; } diff --git a/src/app/clusters/icd-management-server/icd-management-server.h b/src/app/clusters/icd-management-server/icd-management-server.h index 4462cb96d9c9f2..5c6b838fa9b527 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.h +++ b/src/app/clusters/icd-management-server/icd-management-server.h @@ -68,8 +68,6 @@ class ICDManagementServer const chip::app::Clusters::IcdManagement::Commands::UnregisterClient::DecodableType & commandData); #endif // CHIP_CONFIG_ENABLE_ICD_CIP - chip::Protocols::InteractionModel::Status StayActiveRequest(chip::FabricIndex fabricIndex); - private: #if CHIP_CONFIG_ENABLE_ICD_CIP /** diff --git a/src/app/icd/server/ICDConfigurationData.h b/src/app/icd/server/ICDConfigurationData.h index 3fb3e9a92d2304..8b87d090f769e1 100644 --- a/src/app/icd/server/ICDConfigurationData.h +++ b/src/app/icd/server/ICDConfigurationData.h @@ -61,6 +61,8 @@ class ICDConfigurationData System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; } + System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; } + Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; } uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } @@ -123,6 +125,9 @@ class ICDConfigurationData static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour); static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1); + // As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application + // Clusters: 9.17.7.5.1. PromisedActiveDuration Field" + static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000); static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(), "Spec requires the IdleModeDuration to be equal or inferior to 64800s."); diff --git a/src/app/icd/server/ICDManager.cpp b/src/app/icd/server/ICDManager.cpp index 057cc089e9624f..931737783dde9f 100644 --- a/src/app/icd/server/ICDManager.cpp +++ b/src/app/icd/server/ICDManager.cpp @@ -120,6 +120,22 @@ bool ICDManager::SupportsFeature(Feature feature) #endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST } +uint32_t ICDManager::StayActiveRequest(uint32_t stayActiveDuration) +{ + // This should only be called when the device is in ActiveMode + VerifyOrReturnValue(mOperationalState == OperationalState::ActiveMode, 0); + + uint32_t promisedActiveDuration = + std::min(ICDConfigurationData::GetInstance().GetGuaranteedStayActiveDuration().count(), stayActiveDuration); + + // If the device is already in ActiveMode, we need to extend the active mode duration + // for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking in account the remaining active time. + ExtendActiveMode(System::Clock::Milliseconds16(promisedActiveDuration)); + promisedActiveDuration = DeviceLayer::SystemLayer().GetRemainingTime(OnActiveModeDone, this).count(); + + return promisedActiveDuration; +} + #if CHIP_CONFIG_ENABLE_ICD_CIP void ICDManager::SendCheckInMsgs() { @@ -366,17 +382,7 @@ void ICDManager::UpdateOperationState(OperationalState state) } else { - Milliseconds16 activeModeThreshold = ICDConfigurationData::GetInstance().GetActiveModeThreshold(); - DeviceLayer::SystemLayer().ExtendTimerTo(activeModeThreshold, OnActiveModeDone, this); - - Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS); - activeModeJitterThreshold = - (activeModeThreshold >= activeModeJitterThreshold) ? activeModeThreshold - activeModeJitterThreshold : kZero; - - if (!mTransitionToIdleCalled) - { - DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this); - } + ExtendActiveMode(ICDConfigurationData::GetInstance().GetActiveModeThreshold()); } } } @@ -521,11 +527,6 @@ void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event) case ICDManagementEvents::kTableUpdated: this->UpdateICDMode(); break; - - case ICDManagementEvents::kStayActiveRequestReceived: - // TODO : Implement the StayActiveRequest - // https://github.com/project-chip/connectedhomeip/issues/24259 - break; default: break; } @@ -540,6 +541,19 @@ void ICDManager::OnSubscriptionReport() this->UpdateOperationState(OperationalState::ActiveMode); } +void ICDManager::ExtendActiveMode(Milliseconds16 extendDuration) +{ + DeviceLayer::SystemLayer().ExtendTimerTo(extendDuration, OnActiveModeDone, this); + + Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS); + activeModeJitterThreshold = (extendDuration >= activeModeJitterThreshold) ? extendDuration - activeModeJitterThreshold : kZero; + + if (!mTransitionToIdleCalled) + { + DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this); + } +} + ICDManager::ObserverPointer * ICDManager::RegisterObserver(ICDStateObserver * observer) { return mStateObserverPool.CreateObject(observer); diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index 396e6be20d0606..5e391c1469143c 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -109,6 +109,14 @@ class ICDManager : public ICDListener void postObserverEvent(ObserverEventType event); OperationalState GetOperationalState() { return mOperationalState; } + /** + * @brief Ensures that the remaining Active Mode duration is at least the smaller of 30000 milliseconds and stayActiveDuration. + * + * @param stayActiveDuration The duration (in milliseconds) requested by the client to stay in Active Mode + * @return The duration (in milliseconds) the device will stay in Active Mode + */ + uint32_t StayActiveRequest(uint32_t stayActiveDuration); + #if CHIP_CONFIG_ENABLE_ICD_CIP void SendCheckInMsgs(); @@ -131,6 +139,12 @@ class ICDManager : public ICDListener void OnSubscriptionReport() override; protected: + /** + * @brief Hepler function that extends the Active Mode duration as well as the Active Mode Jitter timer for the transition to + * iddle mode. + */ + void ExtendActiveMode(System::Clock::Milliseconds16 extendDuration); + friend class TestICDManager; static void OnIdleModeDone(System::Layer * aLayer, void * appState); diff --git a/src/app/icd/server/ICDNotifier.h b/src/app/icd/server/ICDNotifier.h index 1223732e3fc05f..5db14503a296d7 100644 --- a/src/app/icd/server/ICDNotifier.h +++ b/src/app/icd/server/ICDNotifier.h @@ -48,8 +48,7 @@ class ICDListener enum class ICDManagementEvents : uint8_t { - kTableUpdated = 0x01, - kStayActiveRequestReceived = 0x02, + kTableUpdated = 0x01, }; using KeepActiveFlags = BitFlags; diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index da549ff5062f34..ba311f889989f8 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -540,6 +540,83 @@ class TestICDManager // After the init we should be in Idle mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); } + + /* Test that verifies the logic of the ICDManager when it receives a StayActiveRequest*/ + static void TestICDMStayActive(nlTestSuite * aSuite, void * aContext) + { + TestContext * ctx = static_cast(aContext); + ICDNotifier notifier = ICDNotifier::GetInstance(); + ICDConfigurationData & icdConfigData = ICDConfigurationData::GetInstance(); + + // Verify That ICDManager starts in Idle + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report. Put the ICD manager into active mode. + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the ActiveModeDuration - 1 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + // Confirm ICD manager is in active mode + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + uint32_t stayActiveRequestedMs = 20000; + // Send a stay active request for 20 seconds + uint32_t stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the same as the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == stayActiveRequestedMs); + + // Advance time by the duration of the stay stayActiveRequestedMs - 1 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 1_ms32); + // Confirm ICD manager is in active mode + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by 1ms and Confirm ICD manager is in idle mode + AdvanceClockAndRunEventLoop(ctx, 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report Put the ICD manager into active mode + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the duration of the stay active request - 1 ms + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + stayActiveRequestedMs = 35000; + // Send a stay active request for 35 seconds, which is higher than the maximum stay active duration (30 seconds) + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the maximum stay active duration (30 seconds) + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 30000); + + // Advance time by the duration of the max stay active duration - 1 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(30000) - 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by 1ms and Confirm ICD manager is in idle mode + AdvanceClockAndRunEventLoop(ctx, 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report Put the ICD manager into active mode + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the duration of the stay active request - 1 ms + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + stayActiveRequestedMs = 30000; + // Send a stay active request for 30 seconds + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the same as the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 30000); + + // Advance time by the duration of the stay active request - 20000 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 20000_ms32); + // Confirm ICD manager is in active mode, we should have 20000 seconds left at that point + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + stayActiveRequestedMs = 10000; + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is 20000 since the device is already planing to stay active longer than the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 20000); + } }; } // namespace app @@ -556,6 +633,7 @@ static const nlTest sTests[] = { NL_TEST_DEF("TestKeepActivemodeRequests", TestICDManager::TestKeepActivemodeRequests), NL_TEST_DEF("TestICDMRegisterUnregisterEvents", TestICDManager::TestICDMRegisterUnregisterEvents), NL_TEST_DEF("TestICDCounter", TestICDManager::TestICDCounter), + NL_TEST_DEF("TestICDStayActive", TestICDManager::TestICDMStayActive), NL_TEST_SENTINEL(), }; diff --git a/src/app/tests/suites/TestIcdManagementCluster.yaml b/src/app/tests/suites/TestIcdManagementCluster.yaml index d9d275b90faf3c..3d0081504c19bf 100644 --- a/src/app/tests/suites/TestIcdManagementCluster.yaml +++ b/src/app/tests/suites/TestIcdManagementCluster.yaml @@ -372,3 +372,82 @@ tests: value: 102 response: error: NOT_FOUND + + - label: + "Wait for a little bit less than the active mode duration (10000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 9000 + + - label: + "StayActive Scenario 1: Confirm the promised active duration is + increased to a specific if a value less than 30000ms is requested and + the device does not intend to stay active longer" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 20000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 19500 + maxValue: 20500 + + - label: + "Wait for a little bit less than the new promied active mode duration + (20000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 19000 + + - label: + "StayActive Scenario 2: Confirm the promised active duration is + reduced to 30000ms if a value greater than 30000ms is requested" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 35000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 29500 + maxValue: 30500 + + - label: + "Wait for a 20000 less than the new promied active mode duration + (30000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 10000 + + - label: + "StayActive Scenario 3: confirm that the device ignores the request if + the device intends to stay active longer than the requested duration + we should have about 20000ms left here" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 10000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 19500 + maxValue: 20500 diff --git a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml index a2665916e23204..d68cc30ea95f9c 100644 --- a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml @@ -111,6 +111,7 @@ limitations under the License. Request the end device to stay in Active Mode for an additional ActiveModeThreshold + diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 8611f4bdcf62d8..5dece392f3cd97 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -2740,6 +2740,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -2749,7 +2753,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** This cluster supports creating a simple timer functionality. */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 7025f3cde37858..c55a45b77aaca8 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -18170,14 +18170,18 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void stayActiveRequest(StayActiveResponseCallback callback) { - stayActiveRequest(callback, 0); + public void stayActiveRequest(StayActiveResponseCallback callback, Long stayActiveDuration) { + stayActiveRequest(callback, stayActiveDuration, 0); } - public void stayActiveRequest(StayActiveResponseCallback callback, int timedInvokeTimeoutMs) { + public void stayActiveRequest(StayActiveResponseCallback callback, Long stayActiveDuration, int timedInvokeTimeoutMs) { final long commandId = 3L; ArrayList elements = new ArrayList<>(); + final long stayActiveDurationFieldID = 0L; + BaseTLVType stayActiveDurationtlvValue = new UIntType(stayActiveDuration); + elements.add(new StructElement(stayActiveDurationFieldID, stayActiveDurationtlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index a1d43e3a7933a5..3437b8a981e476 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -5881,6 +5881,23 @@ public static UnregisterClientCommandField value(int id) throws NoSuchFieldError } throw new NoSuchFieldError(); } + }public enum StayActiveRequestCommandField {StayActiveDuration(0),; + private final int id; + StayActiveRequestCommandField(int id) { + this.id = id; + } + + public int getID() { + return id; + } + public static StayActiveRequestCommandField value(int id) throws NoSuchFieldError { + for (StayActiveRequestCommandField field : StayActiveRequestCommandField.values()) { + if (field.getID() == id) { + return field; + } + } + throw new NoSuchFieldError(); + } }@Override public String getAttributeName(long id) throws NoSuchFieldError { return Attribute.value(id).toString(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 5162f9766a74da..4ded328fad6ed5 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -23352,10 +23352,16 @@ public Map> getCommandMap() { icdManagementClusterInteractionInfoMap.put("unregisterClient", icdManagementunregisterClientInteractionInfo); Map icdManagementstayActiveRequestCommandParams = new LinkedHashMap(); + + CommandParameterInfo icdManagementstayActiveRequeststayActiveDurationCommandParameterInfo = new CommandParameterInfo("stayActiveDuration", Long.class, Long.class); + icdManagementstayActiveRequestCommandParams.put("stayActiveDuration",icdManagementstayActiveRequeststayActiveDurationCommandParameterInfo); InteractionInfo icdManagementstayActiveRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.IcdManagementCluster) cluster) .stayActiveRequest((ChipClusters.IcdManagementCluster.StayActiveResponseCallback) callback + , (Long) + commandArguments.get("stayActiveDuration") + ); }, () -> new DelegatedIcdManagementClusterStayActiveResponseCallback(), diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt index 9421d92a1742f7..008aa6349da2ce 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt @@ -193,11 +193,17 @@ class IcdManagementCluster( logger.log(Level.FINE, "Invoke command succeeded: ${response}") } - suspend fun stayActiveRequest(timedInvokeTimeout: Duration? = null): StayActiveResponse { + suspend fun stayActiveRequest( + stayActiveDuration: UInt, + timedInvokeTimeout: Duration? = null + ): StayActiveResponse { val commandId: UInt = 3u val tlvWriter = TlvWriter() tlvWriter.startStructure(AnonymousTag) + + val TAG_STAY_ACTIVE_DURATION_REQ: Int = 0 + tlvWriter.put(ContextSpecificTag(TAG_STAY_ACTIVE_DURATION_REQ), stayActiveDuration) tlvWriter.endStructure() val request: InvokeRequest = diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 853fd1f98c38cd..3bc715829f27db 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -4078,6 +4078,7 @@ class ChipClusters: "commandId": 0x00000003, "commandName": "StayActiveRequest", "args": { + "stayActiveDuration": "int", }, }, }, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 3f5c116cc5515b..cd411b93d43301 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -14304,8 +14304,11 @@ class StayActiveRequest(ClusterCommand): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ + ClusterObjectFieldDescriptor(Label="stayActiveDuration", Tag=0, Type=uint), ]) + stayActiveDuration: 'uint' = 0 + @dataclass class StayActiveResponse(ClusterCommand): cluster_id: typing.ClassVar[int] = 0x00000046 diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 9f7d6f8ffd5c64..6232b6424b8eb1 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -4491,9 +4491,7 @@ MTR_PROVISIONALLY_AVAILABLE * * Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithCompletion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion - MTR_PROVISIONALLY_AVAILABLE; +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)readAttributeIdleModeDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeIdleModeDurationWithParams:(MTRSubscribeParams *)params diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 8cca4c8ed5a7d5..b375488f292fc8 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -37049,11 +37049,7 @@ - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParam queue:self.callbackQueue completion:responseHandler]; } -- (void)stayActiveRequestWithCompletion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion -{ - [self stayActiveRequestWithParams:nil completion:completion]; -} -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion { if (params == nil) { params = [[MTRICDManagementClusterStayActiveRequestParams diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index d8bc6458a2680d..7ce97cfe09442f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -2090,9 +2090,7 @@ MTR_PROVISIONALLY_AVAILABLE - (void)registerClientWithParams:(MTRICDManagementClusterRegisterClientParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterRegisterClientResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion - MTR_PROVISIONALLY_AVAILABLE; +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeIdleModeDurationWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 2374d7f3cf9531..db279250cac8bf 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -6080,11 +6080,7 @@ - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParam completion:responseHandler]; } -- (void)stayActiveRequestWithExpectedValues:(NSArray *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion -{ - [self stayActiveRequestWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion { if (params == nil) { params = [[MTRICDManagementClusterStayActiveRequestParams diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 8f2b0705fe3283..ccd23b30f0aceb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -3697,6 +3697,8 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE @interface MTRICDManagementClusterStayActiveRequestParams : NSObject + +@property (nonatomic, copy) NSNumber * _Nonnull stayActiveDuration MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 60757c92d0dfdb..3105c9a9d21f80 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -9783,6 +9783,8 @@ @implementation MTRICDManagementClusterStayActiveRequestParams - (instancetype)init { if (self = [super init]) { + + _stayActiveDuration = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -9793,6 +9795,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; { auto other = [[MTRICDManagementClusterStayActiveRequestParams alloc] init]; + other.stayActiveDuration = self.stayActiveDuration; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -9801,7 +9804,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: stayActiveDuration:%@; >", NSStringFromClass([self class]), _stayActiveDuration]; return descriptionString; } @@ -9813,6 +9816,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type encodableStruct; ListFreer listFreer; + { + encodableStruct.stayActiveDuration = self.stayActiveDuration.unsignedIntValue; + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 88ef78d1005314..9d1f7804da63b4 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -713,8 +713,19 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE * Time in seconds that a factory new device will advertise commissionable node discovery. */ #ifndef CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +/** + * By default, the extended announcement, when enabled, starts its extended advertising 15 mins + * after the standard slow advertisement. Time at which the default discovery time would close the + * commissioning window and stop the BLE. + * Therefore, when CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING is enabled bump the default Discovery timeout + * to the maximum allowed by the spec. 48h. + */ +#define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (60 * 60 * 48) +#else #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (15 * 60) -#endif +#endif // CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#endif // CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS /** * CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES diff --git a/src/platform/silabs/CHIPDevicePlatformConfig.h b/src/platform/silabs/CHIPDevicePlatformConfig.h index fa3a50974f6a50..e8601e5feedaf9 100644 --- a/src/platform/silabs/CHIPDevicePlatformConfig.h +++ b/src/platform/silabs/CHIPDevicePlatformConfig.h @@ -140,6 +140,8 @@ #define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 25 +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING SL_MATTER_BLE_EXTENDED_ADV + /* ICD Configuration Defines */ diff --git a/src/platform/silabs/rs911x/rsi_ble_config.h b/src/platform/silabs/rs911x/rsi_ble_config.h index bf40cad514dada..72f830b423ef9d 100644 --- a/src/platform/silabs/rs911x/rsi_ble_config.h +++ b/src/platform/silabs/rs911x/rsi_ble_config.h @@ -14,9 +14,7 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ - -#ifndef RSI_BLE_CONFIG_H -#define RSI_BLE_CONFIG_H +#pragma once #include "rsi_ble_apis.h" #if (SIWX_917 | EXP_BOARD) @@ -315,6 +313,4 @@ typedef struct rsi_ble_s uint16_t DATA_ix; uint16_t att_rec_list_count; rsi_ble_att_list_t att_rec_list[NO_OF_VAL_ATT]; -} rsi_ble_t; - -#endif \ No newline at end of file +} rsi_ble_t; \ No newline at end of file diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 427bf00c99c3eb..d91a80d9be8f57 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -142,6 +142,9 @@ class DLL_EXPORT Layer * This method searches for the timer matching the provided parameters. * and returns whether it is still "running" and waiting to trigger or not. * + * @note This is used to verify by how long the ExtendTimer method extends the timer, as it may ignore an extension request + * if it is shorter than the current timer's remaining time. + * * @param[in] onComplete A pointer to the function called when timer expires. * @param[in] appState A pointer to the application state object used when timer expires. * @@ -150,6 +153,17 @@ class DLL_EXPORT Layer */ virtual bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) = 0; + /** + * @brief + * This method searches for the timer matching the provided parameters + * and returns the remaining time left before it expires. + * @param[in] onComplete A pointer to the function called when timer expires. + * @param[in] appState A pointer to the application state object used when timer expires. + * + * @return The remaining time left before the timer expires. + */ + virtual Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) = 0; + /** * @brief This method cancels a one-shot timer, started earlier through @p StartTimer(). This method must * be called while in the Matter context (from the Matter event loop, or while holding the Matter diff --git a/src/system/SystemLayerImplFreeRTOS.cpp b/src/system/SystemLayerImplFreeRTOS.cpp index cfc8e091208f86..59265f61d03693 100644 --- a/src/system/SystemLayerImplFreeRTOS.cpp +++ b/src/system/SystemLayerImplFreeRTOS.cpp @@ -96,6 +96,11 @@ bool LayerImplFreeRTOS::IsTimerActive(TimerCompleteCallback onComplete, void * a return (mTimerList.GetRemainingTime(onComplete, appState) > Clock::kZero); } +Clock::Timeout LayerImplFreeRTOS::GetRemainingTime(TimerCompleteCallback onComplete, void * appState) +{ + return mTimerList.GetRemainingTime(onComplete, appState); +} + void LayerImplFreeRTOS::CancelTimer(TimerCompleteCallback onComplete, void * appState) { assertChipStackLockedByCurrentThread(); diff --git a/src/system/SystemLayerImplFreeRTOS.h b/src/system/SystemLayerImplFreeRTOS.h index 2e7401dfce03ce..fe0e9be4bc7e33 100644 --- a/src/system/SystemLayerImplFreeRTOS.h +++ b/src/system/SystemLayerImplFreeRTOS.h @@ -42,6 +42,7 @@ class LayerImplFreeRTOS : public LayerFreeRTOS CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override; + Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) override; void CancelTimer(TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override; diff --git a/src/system/SystemLayerImplSelect.cpp b/src/system/SystemLayerImplSelect.cpp index 7ae25a0a59d134..86ff1cb62da42f 100644 --- a/src/system/SystemLayerImplSelect.cpp +++ b/src/system/SystemLayerImplSelect.cpp @@ -255,6 +255,11 @@ bool LayerImplSelect::IsTimerActive(TimerCompleteCallback onComplete, void * app return timerIsActive; } +Clock::Timeout LayerImplSelect::GetRemainingTime(TimerCompleteCallback onComplete, void * appState) +{ + return mTimerList.GetRemainingTime(onComplete, appState); +} + void LayerImplSelect::CancelTimer(TimerCompleteCallback onComplete, void * appState) { assertChipStackLockedByCurrentThread(); diff --git a/src/system/SystemLayerImplSelect.h b/src/system/SystemLayerImplSelect.h index 060657e77a72ef..1bab3db9b5f39c 100644 --- a/src/system/SystemLayerImplSelect.h +++ b/src/system/SystemLayerImplSelect.h @@ -65,6 +65,7 @@ class LayerImplSelect : public LayerSocketsLoop CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override; + Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) override; void CancelTimer(TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override; diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 8510295bf7c2e0..55934ae5128b0f 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -46,6 +46,9 @@ declare_args() { # Enable Segger System View use_system_view = false + # Enable the BLE extended advertisement + sl_matter_ble_extended_adv = false + # ICD Openthread Configuration flags sl_ot_idle_interval_ms = 15000 # 15s Idle Intervals sl_ot_active_interval_ms = 200 # 200ms Active Intervals @@ -297,6 +300,7 @@ template("efr32_sdk") { "SL_RAIL_LIB_MULTIPROTOCOL_SUPPORT=1", "SL_RAIL_UTIL_PA_CONFIG_HEADER=", "RADIO_CONFIG_DMP_SUPPORT=1", + "SL_MATTER_BLE_EXTENDED_ADV=${sl_matter_ble_extended_adv}", #"__STACK_SIZE=0", ] diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index fc5a2bd789227b..32b62631ed30fd 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -9794,6 +9794,7 @@ namespace StayActiveRequest { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kStayActiveDuration), stayActiveDuration); return encoder.Finalize(); } @@ -9807,6 +9808,19 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { return std::get(__element); } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kStayActiveDuration)) + { + err = DataModel::Decode(reader, stayActiveDuration); + } + else + { + } + + ReturnErrorOnFailure(err); } } } // namespace StayActiveRequest. diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index dfdf2e691686f2..89c36f3c6f147d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -13302,6 +13302,7 @@ struct DecodableType namespace StayActiveRequest { enum class Fields : uint8_t { + kStayActiveDuration = 0, }; struct Type @@ -13311,6 +13312,8 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::StayActiveRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::IcdManagement::Id; } + uint32_t stayActiveDuration = static_cast(0); + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; using ResponseType = Clusters::IcdManagement::Commands::StayActiveResponse::DecodableType; @@ -13324,6 +13327,7 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::StayActiveRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::IcdManagement::Id; } + uint32_t stayActiveDuration = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace StayActiveRequest diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 6191eb2aa3ec2d..8a3081edc0dc1b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -4314,6 +4314,7 @@ class IcdManagementStayActiveRequest : public ClusterCommand IcdManagementStayActiveRequest(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("stay-active-request", credsIssuerConfig) { + AddArgument("StayActiveDuration", 0, UINT32_MAX, &mRequest.stayActiveDuration); ClusterCommand::AddArguments(); } diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 60843e78e103e7..be046cb6155993 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -47653,6 +47653,9 @@ class IcdManagementStayActiveRequest : public ClusterCommand { IcdManagementStayActiveRequest() : ClusterCommand("stay-active-request") { +#if MTR_ENABLE_PROVISIONAL + AddArgument("StayActiveDuration", 0, UINT32_MAX, &mRequest.stayActiveDuration); +#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -47667,6 +47670,9 @@ class IcdManagementStayActiveRequest : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterICDManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRICDManagementClusterStayActiveRequestParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; +#if MTR_ENABLE_PROVISIONAL + params.stayActiveDuration = [NSNumber numberWithUnsignedInt:mRequest.stayActiveDuration]; +#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -47693,6 +47699,7 @@ class IcdManagementStayActiveRequest : public ClusterCommand { } private: + chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type mRequest; }; #endif // MTR_ENABLE_PROVISIONAL