Skip to content

Commit

Permalink
Created StateObserver as an interface class to fix dependencies issue…
Browse files Browse the repository at this point in the history
…s in app/BUILD.gn
  • Loading branch information
lpbeliveau-silabs committed Jul 27, 2023
1 parent d4b245d commit 36cf916
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static_library("app") {
public_deps = [
":app_config",
"${chip_root}/src/access",
"${chip_root}/src/app/icd:cluster-srcs",
"${chip_root}/src/app/icd:observer-srcs",
"${chip_root}/src/lib/address_resolve",
"${chip_root}/src/lib/support",
"${chip_root}/src/messaging",
Expand Down
4 changes: 2 additions & 2 deletions src/app/ReadHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,8 @@ class ReadHandler : public Messaging::ExchangeDelegate
friend class chip::app::reporting::Engine;
friend class chip::app::InteractionModelEngine;

// The report scheduler needs to be able to access StateFlag private functions IsReportable(), IsGeneratingReports() and
// IsDirty() to know when to schedule a run so it is declared as a friend class.
// The report scheduler needs to be able to access StateFlag private functions IsReportable(), IsGeneratingReports(),
// ForceDirtyState() and IsDirty() to know when to schedule a run so it is declared as a friend class.
friend class chip::app::reporting::ReportScheduler;

enum class HandlerState : uint8_t
Expand Down
11 changes: 8 additions & 3 deletions src/app/icd/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@ import("icd.gni")

# ICD Server sources and configurations

source_set("observer-srcs") {
sources = [ "ICDStateObserver.h" ]
}

# ICD Manager source-set is broken out of the main source-set to enable unit tests
# All sources and configurations used by the ICDManager need to go in this source-set
source_set("manager-srcs") {
sources = [
"ICDManager.cpp",
"ICDManager.h",
"${chip_root}/src/app/reporting/ReportScheduler.h",
]

deps = [ ":cluster-srcs" ]
deps = [
":cluster-srcs",
":observer-srcs",
]
public_deps = [ "${chip_root}/src/credentials:credentials" ]
}

Expand Down Expand Up @@ -55,7 +61,6 @@ source_set("server-srcs") {
sources = [
"ICDEventManager.cpp",
"ICDEventManager.h",

]

public_deps = [ ":manager-srcs" ]
Expand Down
22 changes: 14 additions & 8 deletions src/app/icd/ICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <app/icd/ICDManager.h>
#include <app/icd/IcdManagementServer.h>
#include <app/icd/IcdMonitoringTable.h>
#include <app/reporting/ReportScheduler.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConnectivityManager.h>
Expand All @@ -34,23 +33,28 @@
#define ICD_ENFORCE_SIT_SLOW_POLL_LIMIT 0
#endif

#ifndef ICD_REPORT_ON_ENTER_ACTIVE_MODE
// Enabling this makes the devive emmit subscription reports when transitionning from idle to active mode. It gives the device a
// chance to sleep for the extent of its idle mode interval before getting awakened to emit reports again.
#define ICD_REPORT_ON_ENTER_ACTIVE_MODE 0
#endif

namespace chip {
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, ReportScheduler * reportScheduler)
void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, ICDStateObserver * stateObserver)
{
VerifyOrDie(storage != nullptr);
VerifyOrDie(fabricTable != nullptr);
VerifyOrDie(reportScheduler != nullptr);
VerifyOrDie(stateObserver != nullptr);

mStorage = storage;
mFabricTable = fabricTable;
mReportScheduler = reportScheduler;
mStorage = storage;
mFabricTable = fabricTable;
mStateObserver = stateObserver;

uint32_t activeModeInterval = IcdManagementServer::GetInstance().GetActiveModeInterval();
VerifyOrDie(kFastPollingInterval.count() < activeModeInterval);
Expand Down Expand Up @@ -158,7 +162,9 @@ void ICDManager::UpdateOperationState(OperationalState state)
ChipLogError(AppServer, "Failed to set Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format());
}

mReportScheduler->TriggerReportEmission();
#if ICD_REPORT_ON_ENTER_ACTIVE_MODE
mStateObserver->OnEnterActiveMode();
#endif
}
else
{
Expand Down
14 changes: 7 additions & 7 deletions src/app/icd/ICDManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
#pragma once

#include <app/reporting/ReportScheduler.h>
#include <app/icd/ICDStateObserver.h>
#include <credentials/FabricTable.h>
#include <lib/support/BitFlags.h>
#include <platform/CHIPDeviceConfig.h>
Expand Down Expand Up @@ -52,7 +52,7 @@ class ICDManager
};

ICDManager() {}
void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, reporting::ReportScheduler * reportScheduler);
void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, ICDStateObserver * stateObserver);
void Shutdown();
void UpdateIcdMode();
void UpdateOperationState(OperationalState state);
Expand Down Expand Up @@ -83,11 +83,11 @@ class ICDManager
bool SupportsCheckInProtocol();

BitFlags<KeepActiveFlags> mKeepActiveFlags{ 0 };
OperationalState mOperationalState = OperationalState::IdleMode;
ICDMode mICDMode = ICDMode::SIT;
PersistentStorageDelegate * mStorage = nullptr;
FabricTable * mFabricTable = nullptr;
reporting::ReportScheduler * mReportScheduler = nullptr;
OperationalState mOperationalState = OperationalState::IdleMode;
ICDMode mICDMode = ICDMode::SIT;
PersistentStorageDelegate * mStorage = nullptr;
FabricTable * mFabricTable = nullptr;
ICDStateObserver * mStateObserver = nullptr;
};

} // namespace app
Expand Down
30 changes: 30 additions & 0 deletions src/app/icd/ICDStateObserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once

namespace chip {
namespace app {

class ICDStateObserver
{
public:
virtual ~ICDStateObserver() {}
virtual void OnEnterActiveMode() = 0;
};

} // namespace app
} // namespace chip
70 changes: 15 additions & 55 deletions src/app/reporting/ReportScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include <app/ReadHandler.h>
#include <app/icd/ICDStateObserver.h>
#include <lib/core/CHIPError.h>
#include <system/SystemClock.h>

Expand All @@ -38,7 +39,7 @@ class TimerContext
virtual void TimerFired() = 0;
};

class ReportScheduler : public ReadHandler::Observer
class ReportScheduler : public ReadHandler::Observer, public ICDStateObserver
{
public:
/// @brief This class acts as an interface between the report scheduler and the system timer to reduce dependencies on the
Expand Down Expand Up @@ -69,14 +70,8 @@ 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) :
Expand All @@ -89,10 +84,7 @@ 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
Expand All @@ -111,10 +103,7 @@ 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;
Expand Down Expand Up @@ -152,18 +141,9 @@ 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
Expand All @@ -188,38 +168,18 @@ class ReportScheduler : public ReadHandler::Observer

virtual void ReportTimerCallback() = 0;

/// @brief Method that triggers a report emission on each ReadHandler that is not blocked on its min interval.
/// Each read handler that is not blocked is immediately marked dirty so that it will report as soon as possible.
void TriggerReportEmission()
{
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
mNodesPool.ForEachActiveObject([now](ReadHandlerNode * node) {
if (now >= node->GetMinTimestamp())
{
node->GetReadHandler()->ForceDirtyState();
}

return Loop::Continue;
});
}
void TriggerReportEmission() {}

/// @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 Sets the ForceDirty flag of a ReadHandler
void HandlerForceDirtyState(ReadHandler * aReadHandler) { aReadHandler->ForceDirtyState(); }

/// @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)
Expand Down
15 changes: 15 additions & 0 deletions src/app/reporting/ReportSchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : Repor
VerifyOrDie(nullptr != mTimerDelegate);
}

/// @brief Method that triggers a report emission on each ReadHandler that is not blocked on its min interval.
/// Each read handler that is not blocked is immediately marked dirty so that it will report as soon as possible.
void ReportSchedulerImpl::OnEnterActiveMode()
{
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
mNodesPool.ForEachActiveObject([now, this](ReadHandlerNode * node) {
if (now >= node->GetMinTimestamp())
{
this->HandlerForceDirtyState(node->GetReadHandler());
}

return Loop::Continue;
});
}

/// @brief When a ReadHandler is added, register it, which will schedule an engine run
void ReportSchedulerImpl::OnReadHandlerCreated(ReadHandler * aReadHandler)
{
Expand Down
3 changes: 3 additions & 0 deletions src/app/reporting/ReportSchedulerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class ReportSchedulerImpl : public ReportScheduler
ReportSchedulerImpl(TimerDelegate * aTimerDelegate);
~ReportSchedulerImpl() override { UnregisterAllHandlers(); }

// ICDStateObserver
void OnEnterActiveMode() override;

// ReadHandlerObserver
void OnReadHandlerCreated(ReadHandler * aReadHandler) final;
void OnBecameReportable(ReadHandler * aReadHandler) final;
Expand Down

0 comments on commit 36cf916

Please sign in to comment.