From 7220f38fcd126d2453a4a8249e91c78de0c09548 Mon Sep 17 00:00:00 2001 From: cjkas Date: Fri, 16 Oct 2026 22:41:48 +0200 Subject: [PATCH] fix: wait out a remote's long press across the millis() wrap The 500 ms wait that tells a short press from a long one compared now > await, so a press just before the wrap acted at once. It now compares the wrap-safe difference. Reconcile Q21 in SHADE_BEHAVIOUR_PLAN.md. Co-Authored-By: Claude Opus 5.5 --- docs/SHADE_BEHAVIOUR_PLAN.md | 2 +- src/ShadeBehaviour.cpp | 3 ++- test/test_shadebehaviour/test_shadebehaviour.cpp | 12 ++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/SHADE_BEHAVIOUR_PLAN.md b/docs/SHADE_BEHAVIOUR_PLAN.md index e669c75..371c6d6 100644 --- a/docs/SHADE_BEHAVIOUR_PLAN.md +++ b/docs/SHADE_BEHAVIOUR_PLAN.md @@ -92,7 +92,7 @@ The decisions are the user's. Each question comes with a recommended answer, and - ~~A group's SunFlag or Flag doesn't make other groups work their flags out again.~~ Fixed (Q20). - The self-echo (Q5) and merging group commands into the frame rule (Q8). - `lastFrame` doing two jobs (the Q6 revisit). - - The 500 ms long-press deadline is compared as `now > await`, which isn't wrap-safe (not tested). + - ~~The 500 ms long-press deadline isn't wrap-safe.~~ Fixed (Q21). ## Constraints diff --git a/src/ShadeBehaviour.cpp b/src/ShadeBehaviour.cpp index 42745b7..c89c940 100644 --- a/src/ShadeBehaviour.cpp +++ b/src/ShadeBehaviour.cpp @@ -360,7 +360,8 @@ void ShadeBehaviour::onWaitingFrame(uint32_t now) { return; } if(this->lastFrame.processed) return; - if(this->lastFrame.await > 0 && (now > this->lastFrame.await)) { + // Wrap-safe: await is now + 500 when the press began. + if(this->lastFrame.await > 0 && static_cast(now - this->lastFrame.await) > 0) { somfy_commands cmd = this->transformCommand(this->lastFrame.cmd); switch(cmd) { case somfy_commands::StepUp: diff --git a/test/test_shadebehaviour/test_shadebehaviour.cpp b/test/test_shadebehaviour/test_shadebehaviour.cpp index f8f1fef..2b96a26 100644 --- a/test/test_shadebehaviour/test_shadebehaviour.cpp +++ b/test/test_shadebehaviour/test_shadebehaviour.cpp @@ -324,6 +324,17 @@ static void test_remote_my_when_idle_goes_to_the_favorite_after_half_a_second() r.wait(200); ASSERT_POS(60, r.st().target); } +static void test_remote_my_waits_half_a_second_across_the_millis_wrap() { + Rig r; + r.b.restore(0, 0, 60, -1); + r.now = 0xFFFFFFFF - 200; + r.press(somfy_commands::My); + // The deadline is past the wrap; it still waits for it. + r.wait(300); + ASSERT_POS(0, r.st().target); + r.wait(300); + ASSERT_POS(60, r.st().target); +} static void test_remote_my_held_sets_the_favorite() { Rig r; r.b.restore(30, 0, 60, -1); @@ -629,6 +640,7 @@ int main(int argc, char **argv) { RUN_TEST(test_flipped_shade_sends_the_other_way); RUN_TEST(test_remote_down_and_my_stop); RUN_TEST(test_remote_my_when_idle_goes_to_the_favorite_after_half_a_second); + RUN_TEST(test_remote_my_waits_half_a_second_across_the_millis_wrap); RUN_TEST(test_remote_my_held_sets_the_favorite); RUN_TEST(test_remote_held_up_on_a_tilt_motor_tilts); RUN_TEST(test_remote_step_uses_the_frames_step_size);