fix: shield switch commands from stale poll state - #36
Conversation
|
Warning Review limit reached
Next review available in: 30 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Turning a diffuser off from HA flipped back to On one poll (~60s) later while the device stayed off (issue #34). The device takes 15-20s to acknowledge a switch server-side and the list endpoints keep serving the pre-command snapshot long after (statisticsUpdateTime can lag by hours while onlineStatus stays 1), but the optimistic-state shield only lasted 8-15s, so the first scheduled poll reinstated the stale state. A contradicting poll is now only trusted when its statisticsUpdateTime postdates the command (5s skew margin), with a 30-minute cap so HA can never diverge from the server indefinitely; polls without a snapshot timestamp fall back to a 180s shield. Agreeing polls always pass through untouched, and a second delayed refresh fires 25s after each command so HA converges as soon as the device ack lands. Fixes #34 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1dfe2a2 to
c4b3be4
Compare
Covers the configurable SSL bypass (#32), the Power/Fan control split and API reference (#33), schedule disarming after momentary runs (#35), the stale-poll shield (#36), the restored count sensors with long-term statistics (#37), and the MIT license adoption. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Fixes #34 — turning a diffuser off from HA showed On again ~60 seconds later while the physical device stayed off (reported with 2× A7 + 1× A5).
Plan / root-cause write-up: https://plan.dalem.dev/p/iwuvjac2
Root cause
Per
docs/API.md: the device takes 15–20s to acknowledge a switch command server-side, and the list endpoints (the integration's poll source) can serve stale cached snapshots long after that —statisticsUpdateTimeis sometimes hours old whileonlineStatus=1, and an idle device rarely pushes fresh state. The rows carry no realonOff; it's derived fromworkStatus.Meanwhile the optimistic shield in
_apply_recent_switch_stateonly protected a command for 8–15s. Timeline: off at T+0 → T+3s delayed refresh (stale, shielded, still Off) → T+60s scheduled poll: shield expired, server still serving the pre-commandworkStatus=1/2snapshot → HA flips back to On. The ~60s in the report is exactly the default poll interval.(The other half of this failure mode — a leftover armed 24/7 schedule genuinely re-activating the device — is issue #31, fixed separately in #35. This PR reproduces and fixes the pure-staleness half.)
Change
A poll that contradicts the last HA switch command is now only trusted when the server's own snapshot proves it postdates that command:
statisticsUpdateTimenewer than the command (+5s clock-skew margin) → accepted immediately (genuine change, e.g. app use).workStatusis kept coherent with the commanded state in both directions (previously an ON command shielded against a stale OFF could show switch On + Work Status "Off").Verification
Stubbed-coordinator scenario tests, all passing:
statisticsUpdateTimeand keeps commanded Off.All files compile; hassfest + HACS on this PR.
Hardware test for @dalyem: turn a diffuser off from HA → wait 3+ min (2–3 polls) → should stay Off; then turn it on from the Aroma-Link app → HA should show On within a couple of polls once the server publishes a fresh snapshot.
Rollback
Single revertable commit, coordinator-only, no entity/config migrations.
🤖 Generated with Claude Code