Make the timing inside on-off server cluster more accurate (#21755)
* Make the timing inside on-off server cluster more accurate by compensating the latency between scheduling and firing a timer callback
* debug output line removed
* even simpler: nextDesiredOnWithTimedOffTimestamp reflects the desired time stamp for the next state machine step. This variable gets adjusted by UPDATE_TIME_MS and the wait time gets calculated by UPDATE_TIME_MS - last latency
* Fixing style
Co-authored-by: Justin Wood <woody@apple.com>
diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp
index c0006c7..b24ee63 100644
--- a/src/app/clusters/on-off-server/on-off-server.cpp
+++ b/src/app/clusters/on-off-server/on-off-server.cpp
@@ -452,6 +452,26 @@
return true;
}
+uint32_t OnOffServer::calculateNextWaitTimeMS(void)
+{
+ const chip::System::Clock::Timestamp currentTime = chip::System::SystemClock().GetMonotonicTimestamp();
+ chip::System::Clock::Timestamp waitTime = UPDATE_TIME_MS;
+ chip::System::Clock::Timestamp latency;
+
+ if (currentTime > nextDesiredOnWithTimedOffTimestamp)
+ {
+ latency = currentTime - nextDesiredOnWithTimedOffTimestamp;
+ if (latency >= UPDATE_TIME_MS)
+ waitTime = chip::System::Clock::Milliseconds32(1);
+ else
+ waitTime -= latency;
+ }
+
+ nextDesiredOnWithTimedOffTimestamp += UPDATE_TIME_MS;
+
+ return (uint32_t) waitTime.count();
+}
+
bool OnOffServer::OnWithTimedOffCommand(const app::ConcreteCommandPath & commandPath,
const Commands::OnWithTimedOff::DecodableType & commandData)
{
@@ -503,7 +523,8 @@
if (currentOnTime < MAX_TIME_VALUE && currentOffWaitTime < MAX_TIME_VALUE)
{
- emberEventControlSetDelayMS(configureEventControl(endpoint), UPDATE_TIME_MS);
+ nextDesiredOnWithTimedOffTimestamp = chip::System::SystemClock().GetMonotonicTimestamp() + UPDATE_TIME_MS;
+ emberEventControlSetDelayMS(configureEventControl(endpoint), (uint32_t) UPDATE_TIME_MS.count());
}
exit:
@@ -526,7 +547,7 @@
if (isOn) // OnOff On case
{
// Restart Timer
- emberEventControlSetDelayMS(configureEventControl(endpoint), UPDATE_TIME_MS);
+ emberEventControlSetDelayMS(configureEventControl(endpoint), calculateNextWaitTimeMS());
// Update onTime values
uint16_t onTime = MIN_TIME_VALUE;
@@ -565,7 +586,7 @@
if (offWaitTime > 0)
{
// Restart Timer
- emberEventControlSetDelayMS(configureEventControl(endpoint), UPDATE_TIME_MS);
+ emberEventControlSetDelayMS(configureEventControl(endpoint), calculateNextWaitTimeMS());
}
else
{
diff --git a/src/app/clusters/on-off-server/on-off-server.h b/src/app/clusters/on-off-server/on-off-server.h
index a915880..61c9527 100644
--- a/src/app/clusters/on-off-server/on-off-server.h
+++ b/src/app/clusters/on-off-server/on-off-server.h
@@ -29,8 +29,8 @@
* Defines and Macros
*********************************************************/
-static constexpr uint8_t UPDATE_TIME_MS = 100;
-static constexpr uint16_t TRANSITION_TIME_1S = 10;
+static constexpr chip::System::Clock::Milliseconds32 UPDATE_TIME_MS = chip::System::Clock::Milliseconds32(100);
+static constexpr uint16_t TRANSITION_TIME_1S = 10;
static constexpr uint16_t MAX_TIME_VALUE = 0xFFFF;
static constexpr uint8_t MIN_TIME_VALUE = 1;
@@ -79,12 +79,14 @@
EmberEventControl * getEventControl(chip::EndpointId endpoint);
EmberEventControl * configureEventControl(chip::EndpointId endpoint);
+ uint32_t calculateNextWaitTimeMS(void);
/**********************************************************
* Attributes Declaration
*********************************************************/
static OnOffServer instance;
EmberEventControl eventControls[EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT];
+ chip::System::Clock::Timestamp nextDesiredOnWithTimedOffTimestamp;
};
struct OnOffEffect