Skip to content

Adaptive Cover Pro ⛅ v2.21.0

Choose a tag to compare

@jrhubott jrhubott released this 17 May 01:31
· 184 commits to main since this release

ℹ Using release notes from: release_notes/v2.21.0.md

v2.21.0

🔑 Highlights

  • Venetian sequencer fully hardened. Five bug fixes close every edge case
    reported after v2.20.0 shipped the dual-axis sequencer: stale tilt anchors,
    overnight tilt commands, wrong hemisphere on MODE2 summer-presence, and
    tilt_skip_above gaps on the tilt-only path. Users on FGR223, KNX, and
    Shelly 2PM hardware should experience a silent sequencer — no more spurious
    tilt commands, no midnight motor activity.

  • Post-settle hold is now configurable. The 2.0-second delay between
    carriage settle and tilt dispatch — previously a hard-coded constant — is
    exposed as venetian_post_settle_hold (0.0–10.0 s) and accessible at
    runtime via the new set_venetian options service. KNX FGR223 users with
    slow tilt-reassert can extend this without a code change.

  • New adaptive_cover_pro.set_position service. Automations that need
    to move a cover to a specific position while respecting ACP's custom-position
    minimum-mode floors should use this service instead of the stock
    cover.set_cover_position. It reads every active min-mode floor, clamps the
    requested position to the highest one, and bypasses the time-delta gate.

  • MODE2 venetian summer-with-presence now blocks on the correct side.
    The 45° summer-presence setpoint mapped to 25% on the MODE2 scale —
    the open hemisphere — causing slats to admit direct sun rather than block
    it. The fix returns 75% for MODE2, leaving MODE1 unchanged.

✨ Features

  • Configurable post-settle hold for venetian sequencer (#370):
    venetian_post_settle_hold is a new per-instance option (0.0–10.0 s,
    default 2.0) that controls how long the sequencer waits after carriage settle
    before sending set_cover_tilt_position. The previously hard-coded
    VENETIAN_POST_SETTLE_HOLD_SECONDS constant becomes the default only.
    All three venetian options (venetian_mode, venetian_tilt_skip_above,
    venetian_post_settle_hold) now flow through a VenetianSlice dataclass on
    RuntimeConfig, and the new set_venetian options service exposes them at
    runtime without a config-entry reload.

  • adaptive_cover_pro.set_position service (#372):
    A new integration service moves a cover to a requested position while
    enforcing any active custom-position minimum-mode floors. The service reads
    all custom-position slots whose sensor is on and whose min_mode flag is set,
    clamps the requested position to the highest active floor, and calls
    apply_position with force=True to bypass the time-delta gate. Tilt is
    not affected. Use this from automations that need to respect ACP's floor
    constraints — plain cover.set_cover_position bypasses them.

  • Post-settle state gate for venetian sequencer (#33):
    _wait_for_position_settle now requires the cover to have left opening or
    closing state before declaring settle, when a get_state callback is
    provided. Position within tolerance alone is no longer sufficient. The
    no-callback path is preserved for backwards compatibility.

🐛 Bug Fixes

  • MODE2 venetian slats open toward sun on summer-with-presence (#373):
    The climate handler's summer-with-presence branch converts a 45° setpoint to
    a tilt percentage. On the MODE1 scale (0% = closed, 100% = open) the formula
    angle / max_degrees * 100 yields 25% — correctly toward the blocking
    hemisphere. On the symmetric MODE2 scale (50% = horizontal, 0%/100% = closed
    poles) the same result puts the slats past horizontal, admitting direct sun.
    The fix detects MODE2 and applies (max_degrees − angle) / max_degrees * 100
    instead, returning 75% on MODE2 and leaving MODE1 unchanged.

  • Venetian tilt commands fire overnight on low-light branch (#33):
    When the climate handler evaluated an intermediate-temperature, low-light
    scenario (sun below the horizon or lux below threshold), it fell through to
    the ControlMethod.SOLAR branch. The venetian policy's tilt synthesis step
    treats SOLAR as a green light to compute a tilt from the current sun
    azimuth — even at midnight. The result was a tilt command roughly every four
    minutes overnight. Two guards close both ends: the climate handler now emits
    ControlMethod.DEFAULT on the low-light branch, and the venetian policy adds
    a direct_sun_valid check that suppresses tilt synthesis and sets the tilt
    field to None whenever direct sun is not actually striking the window.

  • Venetian tilt delta gate used stale stored target (#33):
    DualAxisSequencer was comparing a new tilt target against the value the
    integration last commanded, not the actuator's current reported tilt. After a
    close, the motor mechanically auto-tilts to 100 regardless of the last-sent
    value, leaving the stored anchor out of sync. The gate then suppressed correct
    tilt commands because the stale anchor looked like the cover was already at
    target. The same stale anchor persisted across Auto Control off→on
    transitions. The fix introduces _resolve_tilt_anchor, which reads the live
    current_tilt_position via the existing callback and falls back to the stored
    target only when the actuator value is unavailable. clear_tilt_targets is
    now called when Auto Control is turned on (not during startup restore), so the
    first cycle after re-enable resolves from actuator state. The
    tilt_command_skipped diagnostic event gains anchor_value and
    anchor_source fields (actual or target_fallback).

  • tilt_skip_above guard missing from tilt-only update path (#33):
    maybe_update_tilt_only was passing the computed tilt to
    DualAxisSequencer.update_tilt_only without checking whether the carriage was
    above the tilt_skip_above threshold. after_position_command already
    enforced this guard; the tilt-only path bypassed it entirely, firing a
    redundant set_cover_tilt_position on every solar recompute while the
    carriage sat retracted. A shared _resolve_skip_above_tilt helper now covers
    both call sites, returning POSITION_OPEN when above the threshold and the
    original tilt otherwise.

📖 Documentation

  • const.py reorganized into 26 named sections with inline docs:
    Every constant now lives under a banner-style section header with a trailing
    inline comment giving its unit, range, default, or role. A module docstring
    with a table of contents lists all sections. No symbol names or values
    changed; the reorganization is purely navigational.

🧹 Chores

  • CI issue-confirmation respects pinned label:
    The issue-confirmation workflow now skips auto-close for issues marked with
    the pinned label, preventing false-positive closures on tracked issues that
    are deliberately held open.

🧪 Testing

  • 3056 tests passing

Compatibility

  • Home Assistant 2026.3.0+