Skip to content

Commit

Permalink
[ICD] Report before idle mode (#28714)
Browse files Browse the repository at this point in the history
* Added a check before going to idle mode to emit a report if it would avoid the device waking up earlier

* Added check to prevent looping when emiting a report before leaving active mode, Changed OnActiveModeAlmostDone to OnTransitionToIdle, added check to prevent wrap around when computing OnTransitionToIdle timeout

* Moved boolean set to true to proper place

* Set flag before calling observer method

* Added stub in observer test function
  • Loading branch information
lpbeliveau-silabs authored and pull[bot] committed Nov 8, 2023
1 parent 28bee90 commit 7eda702
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 1 deletion.
26 changes: 26 additions & 0 deletions src/app/icd/ICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void ICDManager::Shutdown()
// cancel any running timer of the icd
DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this);
DeviceLayer::SystemLayer().CancelTimer(OnActiveModeDone, this);
DeviceLayer::SystemLayer().CancelTimer(OnTransitionToIdle, this);
mICDMode = ICDMode::SIT;
mOperationalState = OperationalState::IdleMode;
mStorage = nullptr;
Expand Down Expand Up @@ -157,6 +158,9 @@ void ICDManager::UpdateOperationState(OperationalState state)
mOperationalState = OperationalState::ActiveMode;
uint32_t activeModeInterval = IcdManagementServer::GetInstance().GetActiveModeInterval();
DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeInterval), OnActiveModeDone, this);
uint32_t activeModeJitterInterval =
(activeModeInterval >= ICD_ACTIVE_TIME_JITTER_MS) ? activeModeInterval - ICD_ACTIVE_TIME_JITTER_MS : 0;
DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeJitterInterval), OnTransitionToIdle, this);

CHIP_ERROR err = DeviceLayer::ConnectivityMgr().SetPollingInterval(GetFastPollingInterval());
if (err != CHIP_NO_ERROR)
Expand All @@ -170,6 +174,13 @@ void ICDManager::UpdateOperationState(OperationalState state)
{
uint16_t activeModeThreshold = IcdManagementServer::GetInstance().GetActiveModeThreshold();
DeviceLayer::SystemLayer().ExtendTimerTo(System::Clock::Timeout(activeModeThreshold), OnActiveModeDone, this);
uint16_t activeModeJitterThreshold =
(activeModeThreshold >= ICD_ACTIVE_TIME_JITTER_MS) ? activeModeThreshold - ICD_ACTIVE_TIME_JITTER_MS : 0;
if (!mTransitionToIdleCalled)
{
DeviceLayer::SystemLayer().ExtendTimerTo(System::Clock::Timeout(activeModeJitterThreshold), OnTransitionToIdle,
this);
}
}
}
}
Expand All @@ -195,6 +206,10 @@ void ICDManager::OnIdleModeDone(System::Layer * aLayer, void * appState)
{
ICDManager * pIcdManager = reinterpret_cast<ICDManager *>(appState);
pIcdManager->UpdateOperationState(OperationalState::ActiveMode);

// We only reset this flag when idle mode is complete to avoid re-triggering the check when an event brings us back to active,
// which could cause a loop.
pIcdManager->mTransitionToIdleCalled = false;
}

void ICDManager::OnActiveModeDone(System::Layer * aLayer, void * appState)
Expand All @@ -207,5 +222,16 @@ void ICDManager::OnActiveModeDone(System::Layer * aLayer, void * appState)
pIcdManager->UpdateOperationState(OperationalState::IdleMode);
}
}

void ICDManager::OnTransitionToIdle(System::Layer * aLayer, void * appState)
{
ICDManager * pIcdManager = reinterpret_cast<ICDManager *>(appState);

// OnTransitionToIdle will trigger a report message if reporting is needed, which should extend the active mode until the
// ack for the report is received.
pIcdManager->mTransitionToIdleCalled = true;
pIcdManager->mStateObserver->OnTransitionToIdle();
}

} // namespace app
} // namespace chip
8 changes: 8 additions & 0 deletions src/app/icd/ICDManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ class ICDManager

static void OnIdleModeDone(System::Layer * aLayer, void * appState);
static void OnActiveModeDone(System::Layer * aLayer, void * appState);
/**
* @brief Callback function called shortly before the device enters idle mode to allow checks to be made. This is currently only
* called once to prevent entering in a loop if some events re-trigger this check (for instance if a check for subscription
* before entering idle mode leads to emiting a report, we will re-enter UpdateOperationState and check again for subscription,
* etc.)
*/
static void OnTransitionToIdle(System::Layer * aLayer, void * appState);

private:
// SIT ICDs should have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5)
Expand All @@ -95,6 +102,7 @@ class ICDManager
PersistentStorageDelegate * mStorage = nullptr;
FabricTable * mFabricTable = nullptr;
ICDStateObserver * mStateObserver = nullptr;
bool mTransitionToIdleCalled = false;
};

} // namespace app
Expand Down
11 changes: 10 additions & 1 deletion src/app/icd/ICDStateObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,23 @@
*/
#pragma once

#ifndef ICD_SLEEP_TIME_JITTER_MS
#define ICD_SLEEP_TIME_JITTER_MS (CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL * 0.75)
#endif

#ifndef ICD_ACTIVE_TIME_JITTER_MS
#define ICD_ACTIVE_TIME_JITTER_MS 300
#endif

namespace chip {
namespace app {

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

} // namespace app
Expand Down
2 changes: 2 additions & 0 deletions src/app/reporting/ReportSchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : Repor
VerifyOrDie(nullptr != mTimerDelegate);
}

void ReportSchedulerImpl::OnTransitionToIdle() {}

/// @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()
Expand Down
1 change: 1 addition & 0 deletions src/app/reporting/ReportSchedulerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ReportSchedulerImpl : public ReportScheduler

// ICDStateObserver
void OnEnterActiveMode() override;
void OnTransitionToIdle() override;

// ReadHandlerObserver
void OnSubscriptionEstablished(ReadHandler * aReadHandler) final;
Expand Down
13 changes: 13 additions & 0 deletions src/app/reporting/SynchronizedReportSchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ void SynchronizedReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aRead
}
}

void SynchronizedReportSchedulerImpl::OnTransitionToIdle()
{
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
uint32_t targetIdleInterval = static_cast<uint32_t>(ICD_SLEEP_TIME_JITTER_MS);
VerifyOrReturn(now >= mTestNextReportTimestamp);
if (((mTestNextReportTimestamp - now) < Seconds16(targetIdleInterval)) && (now > mNextMinTimestamp))
{
// If the next report is due in less than the idle mode interval and we are past the min interval, we can just send it now
CancelReport();
TimerFired();
}
}

CHIP_ERROR SynchronizedReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
{
// Cancel Report if it is currently scheduled
Expand Down
2 changes: 2 additions & 0 deletions src/app/reporting/SynchronizedReportSchedulerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class SynchronizedReportSchedulerImpl : public ReportSchedulerImpl, public Timer
SynchronizedReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportSchedulerImpl(aTimerDelegate) {}
~SynchronizedReportSchedulerImpl() override { UnregisterAllHandlers(); }

void OnTransitionToIdle() override;

bool IsReportScheduled();

void TimerFired() override;
Expand Down
1 change: 1 addition & 0 deletions src/app/tests/TestICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class TestICDStateObserver : public app::ICDStateObserver
{
public:
void OnEnterActiveMode() {}
void OnTransitionToIdle() {}
};

TestICDStateObserver mICDStateObserver;
Expand Down

0 comments on commit 7eda702

Please sign in to comment.