diff --git a/src/app/icd/BUILD.gn b/src/app/icd/BUILD.gn index f4d5b9a7375dac..fc8a2df96278ee 100644 --- a/src/app/icd/BUILD.gn +++ b/src/app/icd/BUILD.gn @@ -23,6 +23,7 @@ source_set("manager-srcs") { sources = [ "ICDManager.cpp", "ICDManager.h", + "${chip_root}/src/app/reporting/ReportScheduler.h", ] deps = [ ":cluster-srcs" ] @@ -54,6 +55,7 @@ source_set("server-srcs") { sources = [ "ICDEventManager.cpp", "ICDEventManager.h", + ] public_deps = [ ":manager-srcs" ] diff --git a/src/app/icd/ICDManager.cpp b/src/app/icd/ICDManager.cpp index 183a95ba498301..936f612d21f6b0 100644 --- a/src/app/icd/ICDManager.cpp +++ b/src/app/icd/ICDManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -39,13 +40,17 @@ namespace app { using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::IcdManagement; +using ReportScheduler = reporting::ReportScheduler; -void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable) +void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, ReportScheduler * reportScheduler) { VerifyOrDie(storage != nullptr); VerifyOrDie(fabricTable != nullptr); - mStorage = storage; - mFabricTable = fabricTable; + VerifyOrDie(reportScheduler != nullptr); + + mStorage = storage; + mFabricTable = fabricTable; + mReportScheduler = reportScheduler; uint32_t activeModeInterval = IcdManagementServer::GetInstance().GetActiveModeInterval(); VerifyOrDie(kFastPollingInterval.count() < activeModeInterval); @@ -153,7 +158,7 @@ void ICDManager::UpdateOperationState(OperationalState state) ChipLogError(AppServer, "Failed to set Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format()); } - InteractionModelEngine::GetInstance()->GetReportScheduler()->OnActiveModeEntered(); + mReportScheduler->TriggerReportEmission(); } else { diff --git a/src/app/icd/ICDManager.h b/src/app/icd/ICDManager.h index 94127d645e9c18..9bb0eb95b29c77 100644 --- a/src/app/icd/ICDManager.h +++ b/src/app/icd/ICDManager.h @@ -16,6 +16,7 @@ */ #pragma once +#include #include #include #include @@ -51,7 +52,7 @@ class ICDManager }; ICDManager() {} - void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable); + void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, reporting::ReportScheduler * reportScheduler); void Shutdown(); void UpdateIcdMode(); void UpdateOperationState(OperationalState state); @@ -82,10 +83,11 @@ class ICDManager bool SupportsCheckInProtocol(); BitFlags mKeepActiveFlags{ 0 }; - OperationalState mOperationalState = OperationalState::IdleMode; - ICDMode mICDMode = ICDMode::SIT; - PersistentStorageDelegate * mStorage = nullptr; - FabricTable * mFabricTable = nullptr; + OperationalState mOperationalState = OperationalState::IdleMode; + ICDMode mICDMode = ICDMode::SIT; + PersistentStorageDelegate * mStorage = nullptr; + FabricTable * mFabricTable = nullptr; + reporting::ReportScheduler * mReportScheduler = nullptr; }; } // namespace app diff --git a/src/app/reporting/ReportScheduler.h b/src/app/reporting/ReportScheduler.h index 87a9ef545b4c71..e42e0ac2830082 100644 --- a/src/app/reporting/ReportScheduler.h +++ b/src/app/reporting/ReportScheduler.h @@ -69,8 +69,14 @@ class ReportScheduler : public ReadHandler::Observer MinIntervalElapsed = (1 << 0), MaxIntervalElapsed = (1 << 1), }; - void SetTestFlags(TestFlags aFlag, bool aValue) { mFlags.Set(aFlag, aValue); } - bool GetTestFlags(TestFlags aFlag) const { return mFlags.Has(aFlag); } + void SetTestFlags(TestFlags aFlag, bool aValue) + { + mFlags.Set(aFlag, aValue); + } + bool GetTestFlags(TestFlags aFlag) const + { + return mFlags.Has(aFlag); + } #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST ReadHandlerNode(ReadHandler * aReadHandler, TimerDelegate * aTimerDelegate, ReportScheduler * aScheduler) : @@ -83,7 +89,10 @@ class ReportScheduler : public ReadHandler::Observer mReadHandler = aReadHandler; SetIntervalTimeStamps(aReadHandler); } - ReadHandler * GetReadHandler() const { return mReadHandler; } + ReadHandler * GetReadHandler() const + { + return mReadHandler; + } /// @brief Check if the Node is reportable now, meaning its readhandler was made reportable by attribute dirtying and /// handler state, and minimal time interval since last report has elapsed, or the maximal time interval since last @@ -102,7 +111,10 @@ class ReportScheduler : public ReadHandler::Observer #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST } - bool IsEngineRunScheduled() const { return mEngineRunScheduled; } + bool IsEngineRunScheduled() const + { + return mEngineRunScheduled; + } void SetEngineRunScheduled(bool aEngineRunScheduled) { mEngineRunScheduled = aEngineRunScheduled; @@ -140,9 +152,18 @@ class ReportScheduler : public ReadHandler::Observer mSyncTimestamp = aSyncTimestamp; } - System::Clock::Timestamp GetMinTimestamp() const { return mMinTimestamp; } - System::Clock::Timestamp GetMaxTimestamp() const { return mMaxTimestamp; } - System::Clock::Timestamp GetSyncTimestamp() const { return mSyncTimestamp; } + System::Clock::Timestamp GetMinTimestamp() const + { + return mMinTimestamp; + } + System::Clock::Timestamp GetMaxTimestamp() const + { + return mMaxTimestamp; + } + System::Clock::Timestamp GetSyncTimestamp() const + { + return mSyncTimestamp; + } private: #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST @@ -167,26 +188,39 @@ class ReportScheduler : public ReadHandler::Observer virtual void ReportTimerCallback() = 0; - void OnActiveModeEntered() + /// @brief Method that triggers a report emission on each ReadHandler that are above their min interval + /// It checks if all read handlers are above their min interval and if so forces them in a dirty state to trigger a + /// report emission + void TriggerReportEmission() { - for (auto & iter : mReadHandlerList) - { - if (iter.IsReportableNow()) + Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp(); + mNodesPool.ForEachActiveObject([now](ReadHandlerNode * node) { + if (now >= node->GetMinTimestamp()) { - OnBecameReportable(iter.GetReadHandler()); - break; + node->GetReadHandler()->ForceDirtyState(); } - } + + return Loop::Continue; + }); } /// @brief Check whether a ReadHandler is reportable right now, taking into account its minimum and maximum intervals. /// @param aReadHandler read handler to check - bool IsReportableNow(ReadHandler * aReadHandler) { return FindReadHandlerNode(aReadHandler)->IsReportableNow(); } + bool IsReportableNow(ReadHandler * aReadHandler) + { + return FindReadHandlerNode(aReadHandler)->IsReportableNow(); + } /// @brief Check if a ReadHandler is reportable without considering the timing - bool IsReadHandlerReportable(ReadHandler * aReadHandler) const { return aReadHandler->IsReportable(); } + bool IsReadHandlerReportable(ReadHandler * aReadHandler) const + { + return aReadHandler->IsReportable(); + } /// @brief Get the number of ReadHandlers registered in the scheduler's node pool - size_t GetNumReadHandlers() const { return mNodesPool.Allocated(); } + size_t GetNumReadHandlers() const + { + return mNodesPool.Allocated(); + } #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST void RunNodeCallbackForHandler(const ReadHandler * aReadHandler) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 96847ace574100..ce07c595d6db06 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -249,7 +249,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) #endif // CHIP_CONFIG_ENABLE_SERVER_IM_EVENT #if CHIP_CONFIG_ENABLE_ICD_SERVER - mICDManager.Init(mDeviceStorage, &GetFabricTable()); + mICDManager.Init(mDeviceStorage, &GetFabricTable(), &mReportScheduler); mICDEventManager.Init(&mICDManager); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER