Repository navigation
v0.4.9
Fixed
Two regressions where belt_state derived as STOPPED after a successful pause instead of PAUSED. Both were found by running tests/stress_dynamic.py against a real KS-HD-Z1D and verified by the pause_resume scenario invariants (16/16 OK after the fixes; ~50% before).
-
_pauseddeceleration race in_on_treadmill_data. The previous version cleared_pausedon every Treadmill Data frame withspeed > 0. Pause sets the flag at speed ≈ 2.5; the ~5–10 s deceleration to zero emits dozens ofspeed > 0frames, each clearing the flag, so by the time speed reached 0 the_pausedbranch was dead and belt_state derived as STOPPED. The flag is now set/cleared exclusively by_on_machine_statusin response to FM Status events;_on_treadmill_dataonly reads it. -
"First 2ADA event after subscribe" filter dropped genuine ack state. The defensive filter that drops the first 2ADA event (added because the firmware replays its prior state on CCCD-subscribe, which would flap
last_fm_eventon every reconnect) over-filtered when the user's first command after a fresh connect produced an ack as the first event — e.g.pause()right after a reconnect → FM StatusSTOPPED_OR_PAUSED + PAUSEarrives as the first event. The ack waiter got woken (sopause()returned True), but_pausedwas never set, andbelt_statederived as STOPPED. Heuristic: if the first event matches_status_ack_expected_opcode, treat as the real ack and apply state. Otherwise skip as before.
Refs walkingpad-controller#2.