From ef9f08a82b8df4c2cb410d511a210c02ae9a4b41 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Mon, 19 Feb 2024 16:26:12 -0500 Subject: [PATCH 1/6] Implementation of StayActive request with test --- .../icd-management-server.cpp | 21 +++-- .../icd-management-server.h | 2 - src/app/icd/server/ICDConfigurationData.h | 4 + src/app/icd/server/ICDManager.cpp | 46 +++++++---- src/app/icd/server/ICDManager.h | 19 ++++- src/app/icd/server/ICDNotifier.h | 3 +- src/app/tests/TestICDManager.cpp | 76 +++++++++++++++++++ .../chip/icd-management-cluster.xml | 1 + src/system/SystemLayer.h | 14 ++++ src/system/SystemLayerImplFreeRTOS.cpp | 5 ++ src/system/SystemLayerImplFreeRTOS.h | 1 + src/system/SystemLayerImplSelect.cpp | 5 ++ src/system/SystemLayerImplSelect.h | 26 +++++-- 13 files changed, 185 insertions(+), 38 deletions(-) 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..abe748611691c5 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,15 @@ 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); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + IcdManagement::Commands::StayActiveResponse::Type response; + response.promisedActiveDuration = Server::GetInstance().GetICDManager().StayActiveRequest(commandData.stayActiveDuration); + commandObj->AddResponse(commandPath, response); +#else + // Note: We only keep this line around for platforms examples that enable the ICD management server without building the sample + // as an ICD. + commandObj->AddStatus(commandPath, InteractionModel::Status::UnsupportedCommand); +#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..70f1152bc6ec00 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 GetMaxStayActiveDuration() { return kMaxStayActiveDuration; } + Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; } uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } @@ -123,6 +125,8 @@ 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 duration for the StayActiveDuration is 30s (spec 7.5.1) + static constexpr System::Clock::Milliseconds32 kMaxStayActiveDuration = 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..d896453306f4d8 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(static_cast(ICDConfigurationData::GetInstance().GetMaxStayActiveDuration().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..b6c8a1dc7d5c39 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 Extends the Active Mode duration for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking + * in account the remaining active time. + * @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(); @@ -119,7 +127,10 @@ class ICDManager : public ICDListener #endif // CHIP_CONFIG_ENABLE_ICD_CIP #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST - void SetTestFeatureMapValue(uint32_t featureMap) { mFeatureMap = featureMap; }; + void SetTestFeatureMapValue(uint32_t featureMap) + { + mFeatureMap = featureMap; + }; #endif // Implementation of ICDListener functions. @@ -131,6 +142,12 @@ class ICDManager : public ICDListener void OnSubscriptionReport() override; protected: + /** + * @brief Hepler function that extends the Active Mode duration by the extendDuration parameter + * 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..a6d5e11f00c178 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -540,6 +540,82 @@ 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(); + + // 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 duration of the stay active request - 1 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms); + // 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_ms); + // 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_ms); + 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_ms); + 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_ms); + 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_ms); + 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_ms); + 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 - 10000 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 10000_ms); + // 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 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/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..316925da05d071 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; @@ -87,18 +88,33 @@ class LayerImplSelect : public LayerSocketsLoop void EventLoopEnds() override {} #if CHIP_SYSTEM_CONFIG_USE_DISPATCH - void SetDispatchQueue(dispatch_queue_t dispatchQueue) override { mDispatchQueue = dispatchQueue; }; - dispatch_queue_t GetDispatchQueue() override { return mDispatchQueue; }; + void SetDispatchQueue(dispatch_queue_t dispatchQueue) override + { + mDispatchQueue = dispatchQueue; + }; + dispatch_queue_t GetDispatchQueue() override + { + return mDispatchQueue; + }; void HandleTimerComplete(TimerList::Node * timer); #elif CHIP_SYSTEM_CONFIG_USE_LIBEV - virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) override { mLibEvLoopP = aLibEvLoopP; }; - virtual struct ev_loop * GetLibEvLoop() override { return mLibEvLoopP; }; + virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) override + { + mLibEvLoopP = aLibEvLoopP; + }; + virtual struct ev_loop * GetLibEvLoop() override + { + return mLibEvLoopP; + }; static void HandleLibEvTimer(EV_P_ struct ev_timer * t, int revents); static void HandleLibEvIoWatcher(EV_P_ struct ev_io * i, int revents); #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV // Expose the result of WaitForEvents() for non-blocking socket implementations. - bool IsSelectResultValid() const { return mSelectResult >= 0; } + bool IsSelectResultValid() const + { + return mSelectResult >= 0; + } protected: static SocketEvents SocketEventsFromFDs(int socket, const fd_set & readfds, const fd_set & writefds, const fd_set & exceptfds); From c33827bb22c1e35f362692ac10f83e8560419aa9 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Tue, 20 Feb 2024 17:42:03 -0500 Subject: [PATCH 2/6] Regenerated zap files --- .../nxp/zap-sit/contact-sensor-app.matter | 6 ++- .../light-switch-app.matter | 6 ++- .../light-switch-app/qpg/zap/switch.matter | 6 ++- .../lit-icd-common/lit-icd-server-app.matter | 6 ++- examples/lock-app/lock-common/lock-app.matter | 12 ++++- examples/lock-app/lock-common/lock-app.zap | 50 +++++++++++++++++-- examples/lock-app/qpg/zap/lock.matter | 6 ++- .../smoke-co-alarm-app.matter | 6 ++- examples/window-app/common/window-app.matter | 6 ++- src/app/tests/TestICDManager.cpp | 10 ++-- .../data_model/controller-clusters.matter | 6 ++- .../chip/devicecontroller/ChipClusters.java | 10 ++-- .../devicecontroller/ClusterIDMapping.java | 17 +++++++ .../devicecontroller/ClusterInfoMapping.java | 6 +++ .../cluster/clusters/IcdManagementCluster.kt | 8 ++- .../python/chip/clusters/CHIPClusters.py | 1 + .../python/chip/clusters/Objects.py | 3 ++ .../CHIP/zap-generated/MTRBaseClusters.h | 4 +- .../CHIP/zap-generated/MTRBaseClusters.mm | 6 +-- .../CHIP/zap-generated/MTRClusters.h | 4 +- .../CHIP/zap-generated/MTRClusters.mm | 6 +-- .../zap-generated/MTRCommandPayloadsObjc.h | 2 + .../zap-generated/MTRCommandPayloadsObjc.mm | 8 ++- .../zap-generated/cluster-objects.cpp | 14 ++++++ .../zap-generated/cluster-objects.h | 4 ++ .../zap-generated/cluster/Commands.h | 1 + .../zap-generated/cluster/Commands.h | 7 +++ 27 files changed, 183 insertions(+), 38 deletions(-) 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..e7130720e5d63a 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 */ @@ -2888,6 +2892,12 @@ endpoint 0 { callback attribute activeModeThreshold; ram attribute featureMap default = 0x0000; ram attribute clusterRevision default = 2; + + handle command RegisterClient; + handle command RegisterClientResponse; + handle command UnregisterClient; + handle command StayActiveRequest; + handle command StayActiveResponse; } } endpoint 1 { diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index c5201e7a6fbb0c..b2eab1211e1639 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,48 @@ "define": "ICD_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "RegisterClient", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RegisterClientResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UnregisterClient", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StayActiveRequest", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StayActiveResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], "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/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index a6d5e11f00c178..cab36be10fe2dd 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -544,8 +544,9 @@ class TestICDManager /* 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(); + 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); @@ -606,8 +607,8 @@ class TestICDManager // 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 - 10000 ms - AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 10000_ms); + // Advance time by the duration of the stay active request - 20000 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 20000_ms); // 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); @@ -632,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/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 235366f4206e78..41de251419354e 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 fcc9154511d2b7..b9d14b1103b189 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 14b4a97284f173..24e3ce5257041a 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 b2c13559d07aec..ad9c0f6d71c5f4 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/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 99e6e3bb1d63f7..61a76f6752fc3f 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 3a7a4e981629b6..2277cf360395e8 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 9a1389e416deb4..05b0cf53ef9d13 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 From 21329bd789079f9c206bd1a3b1a1454617632f71 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Wed, 21 Feb 2024 15:04:02 -0500 Subject: [PATCH 3/6] Added StayActiveRequest scenarios to the yaml test --- examples/lock-app/lock-common/lock-app.matter | 6 -- examples/lock-app/lock-common/lock-app.zap | 43 +--------- src/app/icd/server/ICDManager.h | 5 +- .../suites/TestIcdManagementCluster.yaml | 79 +++++++++++++++++++ src/system/SystemLayerImplSelect.h | 25 ++---- 5 files changed, 86 insertions(+), 72 deletions(-) diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index e7130720e5d63a..1b34782e4ea180 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -2892,12 +2892,6 @@ endpoint 0 { callback attribute activeModeThreshold; ram attribute featureMap default = 0x0000; ram attribute clusterRevision default = 2; - - handle command RegisterClient; - handle command RegisterClientResponse; - handle command UnregisterClient; - handle command StayActiveRequest; - handle command StayActiveResponse; } } endpoint 1 { diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index b2eab1211e1639..8ec233c5250e71 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -4939,48 +4939,7 @@ "define": "ICD_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, - "commands": [ - { - "name": "RegisterClient", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "RegisterClientResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "UnregisterClient", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "StayActiveRequest", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "StayActiveResponse", - "code": 4, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], + "commands": [], "attributes": [ { "name": "IdleModeDuration", diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index b6c8a1dc7d5c39..9ac7f9aa3d8be5 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -127,10 +127,7 @@ class ICDManager : public ICDListener #endif // CHIP_CONFIG_ENABLE_ICD_CIP #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST - void SetTestFeatureMapValue(uint32_t featureMap) - { - mFeatureMap = featureMap; - }; + void SetTestFeatureMapValue(uint32_t featureMap) { mFeatureMap = featureMap; }; #endif // Implementation of ICDListener functions. 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/system/SystemLayerImplSelect.h b/src/system/SystemLayerImplSelect.h index 316925da05d071..1bab3db9b5f39c 100644 --- a/src/system/SystemLayerImplSelect.h +++ b/src/system/SystemLayerImplSelect.h @@ -88,33 +88,18 @@ class LayerImplSelect : public LayerSocketsLoop void EventLoopEnds() override {} #if CHIP_SYSTEM_CONFIG_USE_DISPATCH - void SetDispatchQueue(dispatch_queue_t dispatchQueue) override - { - mDispatchQueue = dispatchQueue; - }; - dispatch_queue_t GetDispatchQueue() override - { - return mDispatchQueue; - }; + void SetDispatchQueue(dispatch_queue_t dispatchQueue) override { mDispatchQueue = dispatchQueue; }; + dispatch_queue_t GetDispatchQueue() override { return mDispatchQueue; }; void HandleTimerComplete(TimerList::Node * timer); #elif CHIP_SYSTEM_CONFIG_USE_LIBEV - virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) override - { - mLibEvLoopP = aLibEvLoopP; - }; - virtual struct ev_loop * GetLibEvLoop() override - { - return mLibEvLoopP; - }; + virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) override { mLibEvLoopP = aLibEvLoopP; }; + virtual struct ev_loop * GetLibEvLoop() override { return mLibEvLoopP; }; static void HandleLibEvTimer(EV_P_ struct ev_timer * t, int revents); static void HandleLibEvIoWatcher(EV_P_ struct ev_io * i, int revents); #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV // Expose the result of WaitForEvents() for non-blocking socket implementations. - bool IsSelectResultValid() const - { - return mSelectResult >= 0; - } + bool IsSelectResultValid() const { return mSelectResult >= 0; } protected: static SocketEvents SocketEventsFromFDs(int socket, const fd_set & readfds, const fd_set & writefds, const fd_set & exceptfds); From 55f75e2dfc1fe5db8640d6d0342f215b9dfb3d65 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:33:40 -0500 Subject: [PATCH 4/6] Co-authored-by: Boris Zbarsky Applied comments about #if and clarifying maximum guaranteed stay active --- .../icd-management-server/icd-management-server.cpp | 6 ------ src/app/icd/server/ICDConfigurationData.h | 7 ++++--- src/app/icd/server/ICDManager.h | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) 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 abe748611691c5..0739b9ee6af798 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -425,15 +425,9 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * comman bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { -#if CHIP_CONFIG_ENABLE_ICD_SERVER IcdManagement::Commands::StayActiveResponse::Type response; response.promisedActiveDuration = Server::GetInstance().GetICDManager().StayActiveRequest(commandData.stayActiveDuration); commandObj->AddResponse(commandPath, response); -#else - // Note: We only keep this line around for platforms examples that enable the ICD management server without building the sample - // as an ICD. - commandObj->AddStatus(commandPath, InteractionModel::Status::UnsupportedCommand); -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER return true; } diff --git a/src/app/icd/server/ICDConfigurationData.h b/src/app/icd/server/ICDConfigurationData.h index 70f1152bc6ec00..350244127831c0 100644 --- a/src/app/icd/server/ICDConfigurationData.h +++ b/src/app/icd/server/ICDConfigurationData.h @@ -61,7 +61,7 @@ class ICDConfigurationData System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; } - System::Clock::Milliseconds32 GetMaxStayActiveDuration() { return kMaxStayActiveDuration; } + System::Clock::Milliseconds32 GetMaxStayActiveDuration() { return kMaxGuaranteedStayActiveDuration; } Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; } @@ -125,8 +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 duration for the StayActiveDuration is 30s (spec 7.5.1) - static constexpr System::Clock::Milliseconds32 kMaxStayActiveDuration = System::Clock::Milliseconds32(30000); + // 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 kMaxGuaranteedStayActiveDuration = 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.h b/src/app/icd/server/ICDManager.h index 9ac7f9aa3d8be5..0f5eefdb8d703e 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -110,8 +110,8 @@ class ICDManager : public ICDListener OperationalState GetOperationalState() { return mOperationalState; } /** - * @brief Extends the Active Mode duration for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking - * in account the remaining active time. + * @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 */ From e7936da8a54571dd46ca41df622bc524e3db3e20 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Thu, 22 Feb 2024 11:36:55 -0500 Subject: [PATCH 5/6] Added the #if back for platforms that build the icd-management-server cluster without being ICD devices --- .../nxp/zap-lit/contact-sensor-app.matter | 6 +++++- .../icd-management-server/icd-management-server.cpp | 5 +++++ src/app/tests/TestICDManager.cpp | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) 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/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 0739b9ee6af798..0f71345a38d0f1 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -425,9 +425,14 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * comman bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { +// 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/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index cab36be10fe2dd..5a1664a3bf03fc 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -551,11 +551,11 @@ class TestICDManager // 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 + // 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 + // Advance time by the ActiveModeDuration - 1 AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms); // Confirm ICD manager is in active mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); From 62ccf9c3c796480f6d323e091b08b701ea68b6e0 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Thu, 22 Feb 2024 16:41:45 -0500 Subject: [PATCH 6/6] Applied suggestions --- src/app/icd/server/ICDConfigurationData.h | 4 ++-- src/app/icd/server/ICDManager.cpp | 2 +- src/app/icd/server/ICDManager.h | 4 ++-- src/app/tests/TestICDManager.cpp | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/app/icd/server/ICDConfigurationData.h b/src/app/icd/server/ICDConfigurationData.h index 350244127831c0..8b87d090f769e1 100644 --- a/src/app/icd/server/ICDConfigurationData.h +++ b/src/app/icd/server/ICDConfigurationData.h @@ -61,7 +61,7 @@ class ICDConfigurationData System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; } - System::Clock::Milliseconds32 GetMaxStayActiveDuration() { return kMaxGuaranteedStayActiveDuration; } + System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; } Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; } @@ -127,7 +127,7 @@ class ICDConfigurationData 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 kMaxGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000); + 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 d896453306f4d8..931737783dde9f 100644 --- a/src/app/icd/server/ICDManager.cpp +++ b/src/app/icd/server/ICDManager.cpp @@ -126,7 +126,7 @@ uint32_t ICDManager::StayActiveRequest(uint32_t stayActiveDuration) VerifyOrReturnValue(mOperationalState == OperationalState::ActiveMode, 0); uint32_t promisedActiveDuration = - std::min(static_cast(ICDConfigurationData::GetInstance().GetMaxStayActiveDuration().count()), stayActiveDuration); + 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. diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index 0f5eefdb8d703e..5e391c1469143c 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -140,8 +140,8 @@ class ICDManager : public ICDListener protected: /** - * @brief Hepler function that extends the Active Mode duration by the extendDuration parameter - * as well as the Active Mode Jitter timer for the transition to iddle mode. + * @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); diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index 5a1664a3bf03fc..ba311f889989f8 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -556,7 +556,7 @@ class TestICDManager NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // Advance time by the ActiveModeDuration - 1 - AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms); + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); // Confirm ICD manager is in active mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -567,12 +567,12 @@ class TestICDManager NL_TEST_ASSERT(aSuite, stayActivePromisedMs == stayActiveRequestedMs); // Advance time by the duration of the stay stayActiveRequestedMs - 1 ms - AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(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_ms); + 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 @@ -580,7 +580,7 @@ class TestICDManager 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_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); @@ -588,11 +588,11 @@ class TestICDManager 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_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_ms); + 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 @@ -600,7 +600,7 @@ class TestICDManager 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_ms); + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); stayActiveRequestedMs = 30000; // Send a stay active request for 30 seconds stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); @@ -608,7 +608,7 @@ class TestICDManager 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_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);