Skip to content

Adaptive Cover Pro ⛅ v2.22.0-beta.2

Pre-release
Pre-release

Choose a tag to compare

@jrhubott jrhubott released this 19 May 17:30
· 236 commits to main since this release

ℹ Using release notes from: release_notes/v2.22.0-beta.2.md

v2.22.0-beta.2

🎯 v2.22.0-beta.2 — Refactor + Post-Settle Cap Grace (Developer + Issue-33 Beta)

This beta carries everything from v2.22.0-beta.1 (the nine-phase internal refactor) plus a targeted fix for a venetian false-override bug discovered after beta.1: on KNX, Shelly 2PM, and other real-motor actuators, cover.state can settle to open/closed before the tilt-walk burst finishes publishing, causing DualAxisSequencer.is_in_suppression_with_cap to reject legitimate motor drift as a user move. If you are running real venetian hardware that was tripping false manual-override after a position command, please install this beta and report back on issue #33.

⚠️ Should I install this?

  • If you ran v2.22.0-beta.1 and it worked, install this — it adds the post-settle cap grace fix on top.
  • If you are on v2.21.5 and seeing false manual-override on venetian blinds after a position command (issue #33), please install this beta and report back.
  • If you are on v2.21.5 and not hitting any issue, you may want to stay there.

🔑 Highlights

  • NEW in beta.2: A 5-second post-settle cap grace in DualAxisSequencer.is_in_suppression_with_cap eliminates false venetian manual-override on KNX, Shelly 2PM, FGR223, and similar actuators that publish their tilt-walk burst after cover.state has already reported open/closed (issue #33).
  • Coordinator shrunk by ~640 lines of code; responsibility distributed into managers/, state/, pipeline/, and cover_types/ where it belongs.
  • Manual-override detection extracted from coordinator.process_entity_state_change into managers/cover_command/state_classifier.py; all five prior issue-specific fixes (#147, #172, #186, #271, #285) preserved verbatim.
  • Cover-type-specific behaviour consolidated onto CoverTypePolicy subclasses; the coordinator and pipeline handlers no longer branch on cover-type strings or hardcoded capability keys.
  • StubSingleAxisPolicy and StubDualAxisPolicy added as canary types; ~60 regression tests now run across all real and stub policies to catch future regressions early.
  • Net diff (beta.1 refactor): 62 files changed, +3,682 / −1,251 lines.

🐛 Bug Fixes (new in beta.2)

  • Post-settle cap grace prevents false venetian override (#33, commit 8c911d3): DualAxisSequencer.is_in_suppression_with_cap guards against false manual-override by bypassing the geometry-bounded backrotate cap while cover.state is in a moving set. On real KNX, Shelly 2PM, and FGR223 actuators, however, the carriage reports open or closed before the full tilt-walk burst has drained from the HA state machine, so the cap would reassert mid-burst and flag the trailing delta as a user grab — latching manual override immediately after a programmatic position command. The fix adds a VENETIAN_POST_SETTLE_CAP_GRACE_SECONDS = 5.0 constant and checks the elapsed time since stamp_position_command was called inside is_in_suppression_with_cap: for 5 seconds after the stamp, the cap bypass stays active even when cover.state has already settled. Once the grace tail expires, the geometry-bounded cap reasserts normally and will still detect a genuine user move. Also tightened the manual-override reason string in managers/manual_override.py — the redundant "(no recent position cmd)" suffix was removed.

🧹 Chores

  • Phase A — latent-defect cleanup at the policy boundary: Six surgical fixes around CoverTypePolicy: GlareZoneHandler downcast guarded; VenetianPolicy.is_in_tilt_suppression signature harmonised; return-to-default switch gate moved to a policy ClassVar; manual-override threshold deduped; custom-position priority default unified; CoverTypePolicy safe-defaults added.

  • Phase B — TimeoutController for the manager timeout pattern: Consolidates the timeout-spawn/await/expiry/nullify pattern shared by MotionManager, WeatherManager, and GracePeriodManager into managers/common/timeout_controller.py. Removes ~80 lines of duplication.

  • Phase C — DualAxisSequencer relocated to cover_types/venetian/: Moves managers/dual_axis_sequencer.py and the flat cover_types/venetian.py into a new cover_types/venetian/ package (policy.py + sequencer.py). Zero behavior change; the sequencer now lives alongside the policy that owns it.

  • Phase D — PipelineSnapshotBuilder extracted from coordinator: Five coordinator methods (~213 LOC) move into pipeline/snapshot_builder.py. Climate, force-sensor, and custom-position reads, plus snapshot assembly, are no longer inline in the coordinator.

  • Phase E — WindowTransitionTracker extracted from coordinator: ~130 lines of transition tracking move into state/window_transition_tracker.py. Removes _last_sun_validity_state and _prev_sunset_active as coordinator instance attributes.

  • Phase F — StateClassifier extracted from coordinator: Moves a 256-line manual-override detection block into managers/cover_command/state_classifier.py. Issue-specific logic for #147, #172, #186, #271, and #285 is preserved exactly.

  • Phase G — eliminate last cover-type literals, harden guard: Replaces remaining SensorType.VENETIAN == checks with ClassVar flags (exposes_dual_axis_sensor, custom_position_includes_tilt). Adds a regression guard that scans for banned literal patterns to prevent the pattern from re-entering.

  • Phase H — stub policies + parametrised cross-type invariants: Introduces StubSingleAxisPolicy and StubDualAxisPolicy; production code must tolerate an unknown policy. Parametrises ~60 regression tests across all real and stub policies.

  • Phase I — wiki anchor + display label onto the policy: Consolidates per-type label and wiki-URL mappings onto CoverTypePolicy.wiki_anchor() and display_label() hooks. Removes hardcoded mappings from config_flow.py.

🧪 Testing

  • 3380 tests passing (up from 3375 in v2.22.0-beta.1).
  • New tests in tests/test_manual_override_venetian.py cover the inside-grace and post-grace cases for the post-settle cap-grace tail, including a stamp_age_seconds backdating helper that lands stamps outside the 5s window while staying inside the overall suppression window.
  • New tests in tests/test_cover_types/test_venetian_sequencer.py cover the cap grace: large delta inside grace returns true with settled state, large delta past grace returns false, small delta past grace still suppresses, and in-motion bypass still passes any delta.

Compatibility

  • Home Assistant 2026.3.0+
  • Python 3.11+