Cover Control Automation (CCA) - Intelligent Automation for Blinds, Awnings & Shutters | Calendar, Sun Shading, Force Functions

Are you sure? There's actually always some migration going on. But two years really is a long time.

If necessary, just clear the helpers. They'll refill on their own.

I had seen many β€ž 'homeassistant.helpers.template.wrapper object' has no attribute 'vpart'β€œ in the traces. However, itβ€˜s a no brainer starting with a clean setup after teo years :laughing:.

BTW: Is the homematic service still needed as a custom action or can i use your builtin cover tilt control?

My scenario would be:

  • Opening the cover tilt to 50% in the morning, Cover 1%
  • Using your default tilt positions for sun shading
  • When the cover was opened manually to 100%, will sun shading and closing still work?

:rocket: CCA 2026.05.24 β€” New State Machine, Priority Cascade, Force Pause & 30+ Bug Fixes

This is the biggest CCA update since the initial release β€” a complete architecture overhaul of the automation engine, combined with powerful new features and months of stability fixes.

What's new at a glance:

  • :brain: New State Machine v6 with a clearly defined 7-layer Priority Cascade
  • :package: Mandatory JSON Helper v6 with automatic migration from v5
  • :pause_button: Force Pause β€” suspend all movements while keeping state in sync
  • :gear: AND/OR operators for brightness & sun elevation conditions
  • :notebook: Optional Logbook entries for debugging without trace limits
  • :wrench: 30+ bug fixes across shading, force functions, ventilation, manual override & more
  • :warning: Behavior change: BASE=OPN now beats VENT in the priority cascade

:warning: Breaking Changes & Migration

Priority Cascade: BASE=OPN now beats VENT

When the time schedule is in the open window (bas=opn) and a window is tilted, the cover now opens fully instead of stopping at the ventilation position.

Situation Before After
Daytime (bas=opn), window tilted, no shading/privacy Cover at ventilation position (e.g. 50%) Cover fully open (100%)
Closing time (bas=cls), window tilted Cover at ventilation position Cover at ventilation position (unchanged)
Shading active, window tilted Cover at ventilation position Cover at ventilation position (unchanged)

Rationale: A tilted window expresses ventilation intent β€” and a fully open cover provides the maximum possible airflow. VENT now acts as a floor: it only kicks in when the cover would otherwise close, shade, or be restricted from opening.

To restore previous behavior: Close the window or remove the time schedule (so bas never reaches opn).

Automation Options Consolidated

All enable/disable decisions are now centrally located in the Automation Options section (auto_options):

Before After Breaking?
time_control: time_control_disabled Uncheck time_control_enabled in auto_options :warning: Legacy (still works, but deprecated)
Brightness & Sun Elevation operator in Sun Elevation section Moved to Automation Options section :white_check_mark: No

Backward compatible: Existing automations without time_control_enabled in auto_options continue to work as before.

Removed Parameters

The following parameters have been removed β€” please update your configuration:

  • shading_start_behavior β†’ replaced by shading_start_max_duration (in seconds, e.g. 3600)
  • shading_end_behavior β†’ covers now always return to open_position when shading ends
  • is_shading_end_immediate_by_sun_position β†’ removed

Helper Schema Cleanup

The shading-pending state is now type-safe: a single pnd enum (non / beg / end) plus ts.due (fire time) and ts.arm (retry anchor). Helper version remains v6 β€” auto-migration handles everything.

For custom card templates / external tooling: Use the new keys (pnd, ts.due, ts.arm). See the updated card examples in examples/.


:brain: New Architecture: State Machine v6 & Priority Cascade

The automation now resolves the cover's target state through a clearly defined priority cascade, evaluated on every run. Higher-priority states always win:

Priority State When active
1 – highest FORCE Any force function is active (Force Open/Close/Shade/Ventilate)
2 LOCKOUT Window is fully open β€” cover must not close
3 BASE=OPN Time schedule = open, no privacy/shading/restriction β†’ fully open
4 VENT Window tilted and cover would otherwise be below ventilation height
5 PRIVACY Resident present + closing trigger configured β†’ close
6 SHADING Sun shading is active
7 – lowest BASE=CLS Time schedule = close

This replaces the previous implicit state resolution and makes the cover's behavior predictable in every situation, including when multiple states are active simultaneously.

Mandatory JSON Helper v6

The Cover Status Helper (input_text, minimum 254 characters) is now required. It stores all relevant state: base state, shading status, window sensor state, force function, resident presence, manual override flag, and timestamps for every state transition.

  • Existing helper users: Automatic migration from v5 to v6 on first run β€” no manual action needed
  • New users: Create an input_text helper with at least 254 characters (Settings β†’ Devices & Services β†’ Helpers)

:sparkles: New Features

:pause_button: Force Pause β€” Suspend All Movements

A new optional force_pause input (input_boolean or switch) allows suspending all automatic cover movements while keeping the background state fully up to date.

  • While active: all triggers fire, helper is updated β€” only movement is blocked
  • When turned off: cover immediately drives to the correct target position
  • Superior to the global condition: the global condition freezes state tracking, so when you re-enable, the helper is stale and the cover only catches up at the next scheduled trigger (possibly hours away). Force Pause solves this.

Use case: A manual/automatic toggle switch. Flip it off to pause, flip it back on β†’ instant correct position.

:gear: AND/OR Operator for Brightness & Sun Elevation

The combination of Brightness and Sun Elevation conditions is now configurable via brightness_sun_operator:

  • OR (default): Cover opens/closes when either condition crosses the threshold (matches previous behavior)
  • AND: Cover opens/closes only when both conditions cross their thresholds β€” useful to avoid premature triggers

When only one sensor is enabled, the operator is irrelevant.

:notebook: Optional Logbook Entries

A new opt-in Logging section (enable_logbook) writes a structured logbook entry on every automation run:

  • Trigger ID, effective state, current cover position
  • Window / resident / force sensor states
  • Full update_values JSON written to the helper
  • Selected branches attach extra context (shading retry, pending timing)

Default: off. Toggle on while debugging β€” the 5-trace limit in Home Assistant no longer caps your ability to reconstruct what the cover did over the course of a day.

:house: Keep Cover Open on Full-to-Tilt Transition

New option ventilation_keep_open_on_full_to_tilt: when a window changes from fully opened to tilted, the cover stays at the open position instead of lowering to the ventilation position. Useful for terrace doors where you come back inside, tilt the door, and don't want the cover moving down.

:family: Resident Handling Redesign

Resident control was completely redesigned. A single smart trigger now handles both arrival and departure, including all environment checks and resident flags. When a force function is deactivated, the cover automatically returns to the correct state (open, closed, shading, or ventilation) without manual intervention.

:new: Forecast Temperature Triggers

Dedicated state-change triggers for forecast temperature sensors (t_shading_start_pending_6 / t_shading_end_pending_6) ensure immediate reaction when forecast temperature values change β€” previously forecast temperature was only evaluated on time-based triggers.


:wrench: Bug Fixes

Force Functions

  • Force features blocking themselves (#339): Force Open/Close/Ventilation/Shading failed to move the cover because is_cover_movement_blocked.any was already true when the force was active. Force triggers now bypass this check.
  • Covers closing during ventilation despite active force (#337): Ventilation recovery now properly respects active force features. Force checks are centralized via YAML anchors.
  • Force recovery ignoring resident sensor (#332): Force recovery now validates resident conditions before returning to background state.
  • Force operations incorrectly updating helper (#318): Force operations now preserve the background helper state instead of overwriting it.
  • Force priority: "Last Wins" (#342, #377): When multiple forces are active, the last activated one wins. Disabling one force correctly falls back to the remaining active force.
  • Cover incorrectly closes when window closes during Force-Ventilation (#445): The contact handler now respects the active force.
  • Background state always kept up to date during force functions: The automation continues to track the scheduled state (e.g. "close at 18:00") while force is running, ensuring correct return after force ends.

Shading

  • Shading never starts with weather_attributes forecast mode (#399): The weather condition was read from an attribute instead of the entity state, returning None permanently. Fixed.
  • Shading-start retry aborts on a fresh day (#408, #416): Duration check used yesterday's timestamp as anchor. A dedicated retry anchor (ts.arm) now ensures the configured retry window is honored correctly.
  • Cover stuck in shading when conditions change rapidly (#395): Stale pending state blocked all subsequent shading-end attempts. Pending is now cleared correctly.
  • Shading-start pending stuck outside shading window (#430): Pending armed inside the shading window was never cleared when the window moved past. Fixed.
  • Shading not triggering after cover opens (#325): Shading conditions are now re-evaluated when covers open.
  • Manual override ignored when shading state is stale (#447): The "Manual: unknown position" branch now clears stale shading state and pending.

Ventilation & Window Sensors

  • Window-opened sensor now always takes priority over tilted: Every branch explicitly checks that opened is not active before processing tilted. Lockout always beats ventilation.
  • Lockout works independently of resident_allow_ventilation: Lockout protection is now a standalone safety feature. Only the tilted sub-branch requires resident_allow_ventilation.
  • Incorrect open status when window tilted during closing time: The tilted-closing branch now correctly sets the base state to closed.
  • Base state not updated when closing trigger fires with tilted window: The CLOSE handler now always records the base-state change, fixing prevent_multiple_times for the next day.

Manual Override

  • man flag cleared in non-movement blocks: Manual override was prematurely cleared after triggers that didn't even drive the cover. man: 0 is now only written when the cover actually moves.
  • Manual position detection trigger (#326): Replaced non-functional template trigger with separate state triggers for each position source. Manual changes are now reliably detected within 60 seconds.
  • Manual override flag not cleared after auto-driven tilt (#425): man flag is now correctly cleared when the automation drives the cover.

Environment Sensors

  • Cover opens at early time without waiting for sensor threshold (#436): With only one sensor enabled + OR operator, the disabled sensor short-circuited the check to true. Both opening and closing now branch explicitly on which sensors are enabled.
  • Sun elevation triggers respect fixed/dynamic/hybrid modes: Triggers t_open_5 and t_close_5 now correctly implement all three modes.
  • Brightness, temp1, temp2 trust their pending trigger: A transient invalid_states no longer overrides a sensor that just fired the pending trigger.

Resident Handling

  • Resident leaving correctly restores shading/ventilation position: Previously the cover sometimes closed instead.
  • Resident leaving with window open no longer falls through to shading (lockout takes priority).
  • Resident handler reads live sensor state, not the helper's stale res value β€” eliminating race conditions during transitions.
  • Force recovery respecting environmental conditions (#310, #312): Covers now check sun elevation and brightness before reopening after force ends.

Other Fixes

  • Ventilation-after-shading blocked by stale lockout gate (#426): Removed incorrect guard.
  • Dead helper write in Force-Shade activation (#427): Removed unused ts.shd write.
  • Redundant cover movements prevented (#344): Cover no longer moves when already at target position.
  • Shading state persistence: The shading state is now correctly saved to the helper across reboots.
  • Defensive fallback for missing weather forecast configuration: Missing data is treated as "no forecast available" instead of producing Jinja2 errors.
  • Silent failures after v5 β†’ v6 upgrade: Fixed manual override timeout, shading start pending, and shading end conditions.

:hammer_and_wrench: Tool Updates

CCA Configuration Validator

  • Recognizes all new parameters (sun_elevation_mode, force_pause, auto_options, brightness_sun_operator, enable_logbook, ventilation_keep_open_on_full_to_tilt, etc.)
  • Sun elevation validation rewritten with full mode-aware support (Fixed / Dynamic / Hybrid)
  • New check: warns when required elevation sensors are missing for Dynamic/Hybrid mode

Trace Analyzer v2.0

Fully updated for the new Branch 0–11 structure and v6 helper format. Supports v6 internal, v6 compact, and v5 legacy display. Includes new runtime variables and an aligned shading deep-dive view.

Trace Compare v2.0

Updated to Branch 0–11 structure, extended trigger explanations, and same v6/v5 multi-format support.


:books: Documentation Updates

New FAQ sections:

  • State Hierarchy β€” detailed explanation of how effective_state is resolved through the priority cascade
  • Force State Architecture β€” when persisted helper state vs. real-time entity state is used
  • State Transition Matrix β€” maps every trigger to its branch and resulting helper changes
  • Shading Pending Mechanism β€” documents the two-phase trigger flow for delayed shading start
  • Window Sensor Priority β€” why opened always beats tilted

New dashboard card examples (in examples/):

  • CCA Status Tile Card β€” compact tile-style visualization
  • Flex-Table-Card β€” full-row visualization of all helper fields

New guide:

  • Window-sun-angle aware shading via Force Shading β€” step-by-step guide for window-orientation-aware shading

:link: Resources


Enjoying CCA? :pray: Buy me a Coffee or tip via PayPal. Thank you! :raised_hands:

6 Likes

Looking at your trace and the behavior you’re describing (stuck at t_shading_start_pending_1 with nothing happening afterwards), I’d like to point out that you appear to be running an older version of the blueprint.
I’d strongly recommend updating to the latest version of CCA. Recent l have significantly improved the shading logic.

But your trace above refers to the January version. And that one was buggy.

Looking at your trace, the automation stops at condition/3 with failed_conditions. Here's what's happening:

The Problem

After a fresh setup (deleting and recreating the automation), your status helper (input_text.coverstatushelper_wzrechts) hasn't been written to yet β€” its raw state is empty or unknown. This is the root cause: the empty/uninitialized JSON helper blocks the entire shading logic from proceeding.

The global condition that gates shading-start triggers checks the raw helper text with a regex:

{{ states(cover_status_helper) | regex_search('"shd"\s*:\s*0') }}

Since the helper is empty/uninitialized, the regex can't find "shd": 0 in an empty string β†’ returns false β†’ automation stops before it ever reaches the shading logic. Every subsequent sun position update hits the same wall.

Workaround (for current version)

Go to Developer Tools β†’ Services and call input_text.set_value:

  • Entity: input_text.coverstatushelper_wzrechts
  • Value:

{"bas":"opn","shd":0,"pnd":"non","win":"cls","frc":"non","res":0,"man":0,"ts":{"opn":0,"cls":0,"shd":0,"due":0,"arm":0,"man":0},"v":6,"t":0}

This initializes the helper with valid JSON so the regex can match. After that, shading should proceed past the pending phase normally.

Fix (available in 2026.05.25)

This is a bug in the blueprint β€” the condition doesn't handle uninitialized helpers. The fix inverts the logic: instead of requiring "shd": 0 to be present, it checks that "shd": 1 is not present. That way, an empty/invalid helper correctly means "shading not active" and the trigger is allowed through.

1 Like

Hi everybody,
thanks for the great work in cca.
I switched over from fhem (asc) to ha an cca.
I'm struggling a lot with shading.

The last two days seem to bring me closer since i managed to shade my roller blinds for some time.

In the afternoon though i encountered a weird problem. Some of my rollers (east side of house) stared to go into shading at around 3 and again around half past 6.

The azimuth is save out of the configured range and the trace analyzer even says the conditions for start are false and for end are true.
I have the config: alias: EG_ESS_rollo_o_ccadescription: ""use_blueprint: path: hvorragend/c - Pastebin.com
I also have a trace, but i'm not sure where to put it. To big for pastebin.

Any idea what i'm doing wrong?
Thanks
max

I can't help without a trace.

Please update your blueprint, or else create an issue on GitHub.

Thanks.

Ok, here is the config and the trace

config: alias: OG_SZ_rollo_ccadescription: ""use_blueprint: path: hvorragend/cove - Pastebin.com
trace: Filebin | mi535b8adf7uh19j

Question removed

I'm still experimenting with a couple of Blueprint options, including yours. What I am looking for is for shading to occur when the sun is in a defined azimuth range AND a defined elevation range AND use solar intensity (from my Ecowitt weather station) AND have the shading reduce as the sun sets.

I have a west-facing roller blind which needs to shade the searing (in summer anyway) afternoon sun but not shade when it's cloudy.

Hi Max,

I looked at your trace β€” the root cause is clear now.

You have "Independent Shading via Temperature Comparison" enabled in your shading configuration (shading_config: ['shading_temp_comparison_independent']). This feature is designed to start shading based solely on forecast temperature, bypassing all other conditions β€” including your configured azimuth range (70–170Β°).

At the time of your trace, the sun was at 277Β° (well past your east-facing window), but the forecast temperature was still above your threshold (forecast_temp_valid=True). So the independent mode said "temperature is high enough β†’ start shading" β€” completely ignoring the azimuth.

This is actually working as designed: the feature description says "independently of other conditions like brightness, sun position, or time". But it's understandably confusing when you've carefully configured an azimuth range and the Trace Analyzer shows start_conditions_met=False.

The fix: Disable "Independent Shading via Temperature Comparison" in your Sun Shading Configuration section. Your standard AND conditions (cond_azimuth + cond_elevation + cond_brightness) will then control shading start β€” and azimuth will be properly enforced.

What I improved: The CCA Trace Analyzer now shows an INDEPENDENT section in the Shading Conditions Deep-Dive when this mode is active. It displays forecast_temp_valid, the effective start decision (independent=true OR conditions_met=false β†’ true), and makes it immediately visible that independent mode is overriding the standard conditions.

1 Like

Hi Hr Vorragend,
thanks for the investigation and the fast and comprehensive reply.
Again thanks for the prompt improvements.
I think that solved my issue. I was the remains of my first naive configuration which i simplified for testing after it did not work.

I have a follow up question for a specific use case.
I have big windows on the east side that have to be shaded directly after opening in the morning.
For WAF reasons the morning opening has to happen on the press of a button, but also occur on brightness, elevation and time fallback, when nobody is home.

If i leave the blind closed via workday sensor and open them via cover.open method the shading conditions seem to be true before the opening. Since i opened them manually the shading is not retriggered an there is no shading.

If i keep them closed via resident sensor the shading conditions do not become true before opening. Shading is not triggered again.

Is there an easy way e.g. toggle the additional shading condition to retrigger shading?

thanks again
max

Good morning!

I’ve been using CCA seasonally since 2024. In previous summers, everything worked as intended, but this year I’m having an issue I can’t seem to resolve.

I’m running the latest version, and I’m only using the sun’s altitude and direction to troubleshoot the problem, but it still isn’t working.

I don’t understand what’s happening or why it’s happening in the last step.

Please help :slight_smile:

config: config
trace: trace

Hi kasownik,

im facing similar problems (but without the positive experience from last year :wink:
I hat a similar config yesterday. In the configuration vaildator it complained that there is no sun entity set, and in deed it was missing in the yamel, even though in the automation it was visible.

Setting it again in the visual automation editor it showed up in yaml and solved some of my problems:

default_sun_sensor: sun.sun

Also validator complains: shading_sun_brightness_start (0lx) should be higher than shading_sun_brightness_end (0lx)

good luck
max :slight_smile:

Hi! I analyzed your trace and found the issue.
It's not a blueprint bug but a configuration problem with your input_text helper.

The Problem

Your input_text.roleta_07_sypialnia helper has a maximum length of 100 characters (the Home Assistant default). However, CCA's v6 state JSON requires approximately 160–170 characters to store all fields. This means every time the automation tries to save its state, the data is truncated or rejected.

You can confirm this in your trace:

  • action/7 shows: HELPER VALIDATION WARNING - Cover Status Helper contains invalid or empty data. Current state: unknown
  • The helper is re-initialized with defaults on every single trigger β€” so state is never persisted.

This is why shading doesn't work: the automation correctly detects the shading conditions (azimuth 213Β° is within your 212°–295Β° range, elevation 54Β° is within 4°–90Β°), arms the "Shading Start Pending" phase, writes the pending state to the helper… and then the helper data is lost. On the next trigger, it starts from scratch again β€” endlessly.

The Fix

Change the maximum length of your input_text.roleta_07_sypialnia helper to 254:

Settings β†’ Devices & Services β†’ Helpers β†’ roleta_07_sypialnia β†’ Maximum length: 254

This is documented in the blueprint description:

Attention: You will need to manually create an input_text entity with a length of 254 chars for this.

After changing this, the automation should work correctly on the next trigger cycle.

Actually, once I corrected the helper, the automation started working.

It says the field needs to be longer, but when I created the new helper, I assumed everything was set up correctlyβ€”only to find out that I had to manually fix it after creating it.

Thank you so much for your help!!!

@Herr.Vorragend is the fixed drive delay now also active on ventilation because it seems so?!

The Fixed Drive Delay applies to all cover movements. Including ventilation start (window opens/tilts). This is the same behavior as for open, close, and shading movements.

For the return movement when the window closes again (ventilation end), the delay is optional. It's only active if you enabled "Enables a calculated delay after the window is closed" in the Ventilation Configuration section.

Could you clarify. Is the delay you're seeing when the window opens/tilts, or when it closes again?

@Herr.Vorragend thanks for the quick answer!
Its exactly as you said, the fixed delay is applied when ventilation is about to start but not when it ends (because the option is disabled).

As you know I have the same problem with the somfy queue overload and have to separate 15 covers with fixed delay so that morning/evening open/close works well but I would like to not have the delay when tilting/opening a window because here only one or two covers have to drive at the same time and that is expected to be instant instead of after 30, 60 whatever seconds the fixed delay is set to.

Or do you have any workaround or idea on how to set this up correctly?