Adaptive Cover Pro ⛅ v2.28.0-beta.4
Pre-releaseℹ Using release notes from: release_notes/v2.28.0-beta.4.md
This beta builds on beta.3 (FOV-mode persistence fix, same-position gate exact equality, set-position covers reaching true 0%, string entity_id normalization) by completing the Configuration Summary translation work from issue #258: the narrative summary shown in the config/options flow now renders in the user's Home Assistant language, with German and French shipping alongside English as the source.
🎯 Highlights
Beta — please test and report back.
- German/French users: switch your HA language and open the config or options flow for any cover. Confirm the Configuration Summary renders in your language — priority rules, position limits, warnings, headers, the cover-type label, and dimension lines should all appear translated.
- Confirm the English fallback works: if a translation key is missing (e.g. a custom HA locale), the summary should fall back to English rather than showing a blank or an error.
- Configure a window using
MEASUREMENTSmode and confirm the mode sticks — previous betas had a save loop where the mode selection didn't persist on re-render. This is now fixed. - Verify small solar tracking adjustments (1–3%) are sent to the cover. beta.2 silently swallowed these moves; they should now go through.
- If you have a set-position cover with a geometry path that previously stopped short of fully closed, confirm it reaches 0% during solar tracking.
- Try the FOV-mode selector end-to-end: switch between
ANGLESandMEASUREMENTSmode, save, reload, and confirm the saved mode is the one that loads. - Verify service calls that pass a string
entity_idtarget resolve correctly, especially for sunset/sunrise time entity services.
✨ Features
Configuration Summary translated to user's language (#258, #575, #576)
The narrative Configuration Summary shown in the config/options flow is now fully translated. This landed in two steps:
Translate configuration summary to user's language (#258, #575): Adds a config_summary top-level translation namespace in en.json with templated leaves (banner, headers, cover, words, fragments, rules, etc.) — each leaf is a Python str.format template with {field} placeholders. _load_summary_labels(hass, language) loads the translated label set via HA's translation system (category config_summary); _config_summary_flat(data) flattens the nested namespace into dotted keys. A no-hass / missing-key English fallback keeps the summary rendering without translations. German and French ship alongside English.
Translate cover-type label and dimension block (#258, #576): The cover-type label (e.g. "Vertical Blind", "Horizontal Awning", "Venetian / Tilt Blind") and the window/geometry dimension lines in the summary are also translated. Adds cover_types and geometry namespaces under config_summary in en.json. A display_label(labels) method on the CoverTypePolicy subclasses returns the translated cover-type name with an English fallback; summary_geometry_lines(config) returns the translated dimension lines per cover type.
Both features ship English/German/French. Verified identifiers: _load_summary_labels, _config_summary_flat, _load_json, _placeholder_fields, _walk, display_label, summary_geometry_lines, _cover_type_label, window_dimensions_lines, computed_fov_line, _flatten, _en_config_summary.
Set-position covers can reach true 0% in solar tracking (#569, #572)
Adds a solar_floor() helper and a position_axis_supported() method on CoverTypePolicy to distinguish covers with the SET_POSITION capability from those limited to open/close/stop/tilt. Covers that support arbitrary position commands can now close fully (true 0%) during solar tracking. Previously, a geometry oversight in some paths prevented these covers from reaching 0%, leaving them stopped short of fully closed.
🐛 Bug Fixes
FOV mode not persisted on re-render causes save loop (#565)
When a FOV-mode switch triggered a re-render in ConfigFlowHandler or OptionsFlowHandler, the selected mode was passed to _show_sun_tracking_form but not written back into self.config or self.options. The form re-rendered with the old stored mode, which differed from the displayed mode, causing an infinite re-render cycle. The fix writes CONF_FOV_MODE into the config/options dict before calling _show_sun_tracking_form, so the persisted value and the displayed value stay in sync. Covered by test_create_flow_switch_to_measurements_then_save, test_imperial_switch_to_measurements_then_save, and test_switching_to_measurements_then_submitting_saves.
Same-position gate used tolerance band, swallowing 1–3% tracking moves (#567, #574)
A position tolerance band introduced in #567 widened the same-position gate so that positions within the tolerance range were treated as identical and not sent. This silently dropped small solar tracking adjustments. The fix reverts the same-position gate to exact equality; movement hysteresis is preserved in the reconcile path, which is the right place for it. Covered by test_apply_position_one_percent_tracking_move_is_sent, test_same_position_band_uses_exact_equality_not_tolerance, test_unreachable_target_suppressed_by_reconcile_not_command_gate, and test_reconcile_gives_up_on_unreachable_target.
String entity_id in service targets not normalizing correctly (#570, #571)
Services that accept a string entity_id target now normalize the value before resolution, so case or spacing variations no longer cause silent failures. Adds regression test coverage via TestStringEntityIdRegression, and adds coverage for the sunset/sunrise time entity service paths via TestSunsetSunriseTimeEntity, including test_set_option_sunset_time_entity_accepted and test_set_option_sunrise_time_entity_accepted.
Previously in this beta line
Measurements mode config-flow save and imperial shaded-area compounding (beta.2, #565): The FOV sliders were emitted as vol.Required markers, blocking the frontend from switching to Measurements mode. A _as_optional() helper re-emits them as vol.Optional to unblock the mode switch. Imperial shaded-area values also compounded on each re-render because user_input was fed back into _show_sun_tracking_form without first converting it back to canonical metres; the fix calls user_input_to_canonical() once up front.
Low-sun edge case returns closed position (beta.1, #559, #562): At very low sun elevations, a geometry edge case returned h_win (fully open) instead of 0 (fully closed). The cover now closes when the sun is near the horizon.
🔧 Internal
Write-gating, geometry caching, and sun availability guard (#543)
Shipped in beta.1, carried here for completeness:
- Write-gating:
_acp_render_signature()detects when a calculated position matches the last written value and skips the HA state write, reducing redundant entity updates. - Geometry cache: Pure geometry helpers decorated with
@lru_cache(maxsize=512)eliminate repeated identical calculations across update cycles. - Sun availability guard: A guard on
sun.sunsuppresses solar tracking when the sun entity is unavailable, preventing stale or error-state data from driving cover commands.
🧪 Testing
4,327 tests passing (up from 4,316 at beta.3).
Compatibility
Requires Home Assistant 2026.3.0+. No new coupled-component requirements.