Adaptive Cover Pro ⛅ v2026.8.2
Highlights
2026.8.2 is an in-month patch: five bug fixes back-ported from develop, no new features, no configuration changes and nothing to migrate. Three of them cost users real cover movement. Manual overrides survive a Home Assistant restart again, after a regression that destroyed them on every reboot for every user (#1232). A blind with a blank start time and a configured end time no longer drives to its daytime default at local midnight (#1256). And the end-of-window reposition now actually fires instead of mistaking an ordinary in-window winner for an active override and skipping the move entirely (#1241). The remaining two fix a venetian drift-reset scope leak and a set_position_limits field that the Actions form never rendered.
Fixed
-
An unset manual-override toggle no longer wipes restored state (#1232):
_update_manager_and_coverstruthiness-testedmanual_toggle, which is a tri-statebool | None. That conflated theNonemeaning "no switch entity has restored yet" with theFalsemeaning "the user disabled manual-override detection". During platform setup theIntegration Enabledswitch fires a coordinator refresh three switch specs beforeManual Overriderestores the flag, so the reset loop ran while the toggle was stillNoneand destroyed every override the sensor had just rehydrated from the restore cache. Every user hit this on every reboot.Gating the reset on an explicit
is Falsefixes it. This is a follow-on to #1019 and PR #1021, whose fix (populatingmanager.coversearly) is correct and untouched. -
A blank start time anchors to sunrise, not midnight (#1256): With no start time configured and an end time set, the operational window re-opened at local midnight.
after_start_timemapped "no start configured" toTrue, putting the window's lower bound at midnight while_normalize_to_todaypinned the end onto the new date.is_activeflipped inactive to active at 00:00,check_transitionfiredon_window_open, and with every override handler declining in darkness the priority-0 default handler drove the cover to its daytime default.The night-hold branch added for #492 never reached these installs, because
compute_effective_defaultshort-circuits whensunset_pos is Noneand they had never configured a night position.TimeWindowManagernow takes an optionalsunrise_provider, and only the blank-start branch ofafter_start_timechanged: when an end bound is configured it consults sunrise and fails open toTruewhen none is available, so the window runs from sunrise to the configured end and never flips at midnight. The coordinator wires the provider as a closure over liveSunData, converting astral's UTC-aware sunrise to naive local. The config summary renders "from sunrise" for that shape, with DE and FR synced._resolve_start_datetime,_start_has_passed,window_explicitly_startedandcompute_effective_defaultare untouched. The mirror-image case, a start time set with the end left blank, is not fixed here; the shared_bound_is_configuredhelper prepares for it. -
The pipeline refreshes before the end-time override guard (#1241): The end-of-window reposition is a one-shot fired from the reconciliation tick, and its override guard read whatever
_pipeline_resultthe last coordinator cycle happened to write. This coordinator has no periodic update interval, so that result can predateend_timeby up to a full reconciliation interval, and any ordinary in-window winner such asSOLAR,CLOUDorGLARE_ZONEthen looked like an active override. The entire end-time move was skipped.managers/time_window.pylatches the close edge before invoking the callback, so nothing retried, and outside the clock window no other dispatch path will move the cover.I refresh the pipeline immediately before consulting the guard. Re-evaluating with the clock window already closed makes every window-gated handler decline, so the winner is
DEFAULTand the end-time position is sent. A genuinely activeCUSTOM_POSITION,MANUALorWEATHERslot still wins and is still deferred to, preserving the behaviour added in #895. -
Sun-tracking minimum position is visible in
set_position_limits(#1242):min_position_sun_trackingwas already wired intoFIELD_VALIDATORSand the_SECTION_POSITION_LIMITSfrozenset the service is registered with, and it carried translation entries in all three languages, butservices.yamlnever declared the field. Home Assistant builds the Actions form strictly fromservices.yaml, so the option was invisible in theset_position_limitsaction even though calling the service with it worked. It now has a field block with a slider selector matching the backend range (0-99, step 1, %).The same service had the mirror-image gap:
enable_position_matchingwas declared inservices.yamlbut had no translation entry in any language, so it rendered as raw English inside translated UIs. Both directions are now locked by a parity test modelled on theset_blind_spotguard from #247. The same class of drift in five other services is tracked separately in #1251 and is not fixed here. -
Drift-reset ineligibility is inherited on the tilt retry (#1234): The
sun_tracking_onlydrift-reset scope gate works correctly on the primary tilt send, but the #500 drift-retry re-send inside_verify_and_record_tiltcalled_send_tilt_commandwithout threadingdrift_reset_eligible. The flag fell back to itsTruedefault and re-armed drift accumulation on a send the scope had already ruled ineligible, so aDEFAULT-controlled venetian tilt ran a full reset cycle. The scope gate itself was never wrong: it readsControlMethodoffPositionContextrather than the command's trigger label, which is why the original diagnosis landed one frame short of the real seam._verify_and_record_tiltnow takesdrift_reset_eligiblekeyword-only and forwards it on the retry. Both verify call sites pass the raw parameter rather than the deriveddrift_reset_enabled, because the retry's own_send_tilt_commandre-derives the_reset_in_progressand threshold folds itself.apply_user_tiltleaked the same flag and now passes_drift_reset_eligible(None), so a card or service tilt is eligible only under theall_tilt_commandsscope. The retry still fires; only its accumulation is gated. This is a no-op under the defaultall_tilt_commandsscope and for every non-venetian cover type.
Testing
12,584 tests passing.
Compatibility
Home Assistant 2026.3.0+ and Python 3.11+. No migration runs for this release, and no new or changed configuration options. The companion Lovelace card (jrhubott/adaptive-cover-pro-card) is a separate repo with its own release cycle.