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

Thanks for the explanation โ€” that makes total sense! With 15 Somfy covers you need the fixed delay to stagger the morning/evening drives and avoid queue overload, but when you tilt a single window you'd expect the cover to react instantly.

Currently there's no way to disable the drive delay specifically for ventilation start โ€” the delay applies globally to all movements. The ventilation_delay_enabled option only controls the delay on ventilation end (window closes), not on ventilation start (window opens/tilts).

I'll look into adding a similar option to skip the drive delay on ventilation start. Since typically only one or two covers are involved when a window opens or tilts, the Somfy queue shouldn't be an issue there.

I'll keep you posted!

1 Like

Don't worry. I haven't forgotten you. Some things are just more complicated and take a little longer. And at least it's still on the same day.

The shading pending armed correctly at 06:55, but the execution aborted because ts.due (= now + waitingtime) resolved to a time before your opening window (07:00). The execution trigger fired too early, failed the time window check, and the retry mechanism also couldn't proceed. So it permanently aborted.

This is a confirmed bug, fixed in #475 . After the fix, ts.due is deferred to the window start when arming before it, so the execution only fires once the window is open.

New Updates

CCA 2026.05.27

  • :sparkles: Feature: New ventilation option to disable the drive delay when ventilation starts (window opens/tilts) โ€” useful for setups with many covers where a large fixed delay is needed for staggering, but single-cover ventilation reactions should be instant
  • :bug: Fix: Shading start pending armed before time window opens no longer aborts immediately โ€” ts.due is now set to max(now + waitingtime, window_start), ensuring execution fires after the window opens instead of aborting with only seconds elapsed of a multi-hour max_duration budget (#475)

CCA 2026.05.26

  • :bug: Fix: Contact handler incorrectly lowered cover to ventilation position when base state was open (bas=opn) and window transitioned from fully open to tilted (#460)
  • :wrench: Improvement: effective_state now reads the window state from live contact sensors instead of the stale helper field โ€” eliminates an entire class of stale-state bugs where effective_state returned lock instead of the correct cascade result during contact handler execution
  • :bug: Fix: Shading condition regex "shd"\s*:\s*1 falsely matched the ts.shd timestamp (e.g. "shd":1779701945) inside the nested ts object, blocking all t_shading_start_pending_* triggers even when shading was inactive (#467)
  • :bug: Fix: Shading End never executed when using Calendar time control โ€” t_shading_end triggers were missing from the calendar.get_events performance filter, causing is_shading_allowed_window to always evaluate to false (#477)

CCA 2026.05.25

  • :bug: Fix: Shading start pending blocked when status helper is uninitialized (e.g. after fresh setup)
  • :wrench: Trace Analyzer: Shading Conditions Deep-Dive now shows independent temperature mode status โ€” displays whether the temperature bypass is active and the effective start decision. This makes it visible when independent mode overrides the standard AND/OR conditions. (#459)
1 Like

@Herr.Vorragend thanks for implementing this feature so fast, absolutely awesome work!

Something else I just saw (only cosmetics), when manual override is active the status shows "Hold until HH:MM" but the time is not the actual reset time (after 1 Hour in my case) but the time the manual override happened.


Thanks for spotting that! The field ts.man stores when the manual override was activated , not when it expires. So the card was showing the wrong label. Fixed in the next release: it'll say "Active since HH:MM" instead of "Hold until HH:MM", which correctly reflects what's actually stored.

3 Likes

Hi there, I have a question to make sure I understand:
If all the AND conditions for shading are met, then the corresponding branch should be activated, right?
The CCA Trace Analyzer shows different (from my point of view)

Hi yokads,

Good question! The Trace Analyzer's "Shading Conditions Deep-Dive" only shows the user-configured conditions (azimuth, temperature, etc.) โ€” but those are just one piece of the puzzle. The shading branch has several additional internal conditions that must also be true for it to match.

The most common reasons for "No Branch Matched" despite valid shading conditions:

  1. Wrong trigger โ€” The shading branch only responds to specific trigger IDs (t_shading_start_*, t_open_1). If a different trigger fired (e.g. time, contact sensor, resident sensor), the shading branch won't match โ€” that's by design.
  2. Time window โ€” If time control is enabled, shading can only start within the configured time window (is_shading_allowed_window).
  3. Already shaded โ€” If the cover is already in the shading position, the branch may be skipped.
  4. Daily limit โ€” If "prevent multiple shading" is enabled and shading already ran today.
  5. Manual override โ€” If you manually moved the cover and "ignore shading after manual" is configured.
  6. Force active โ€” If a force function (force open/close/ventilate) is currently active.

To help diagnose your specific case, could you share:

  • The full HA automation trace (Settings โ†’ Automations โ†’ your CCA โ†’ Traces) โ€” this shows which trigger fired and which conditions failed
  • The current helper JSON (the input_text entity state)

With that info we can pinpoint exactly which condition blocked the branch.

Question to the round: Some might know the usecase in sumertime in the sleeping rooms to ventilate at darkness. Means: Shutter close in the evening and reopen eg at 00.30 at night, hence shutter and window open to leave in fresh wir. At around 4.00 early in the Morning when all are asleep the shutter should close to block rising sun.

What is the most reasonable way to handle that one ?

(here a first try but bot yet worked)

alias: CCA-2-Beschattung_Garten_Schlafzimmer Gaube rechts
description: erstellt 22.02.24
use_blueprint:
  path: hvorragend/cover_control_automation.yaml
  input:
    blind: cover.s25_og_schlazi_gaube_rechts_cover_0
    auto_options:
      - auto_shading_enabled
      - auto_up_enabled
      - auto_down_enabled
      - auto_sun_enabled
      - auto_ventilate_enabled
    time_control: time_control_input
    cover_status_options: cover_helper_enabled
    drive_time: 20
    time_up_early: "09:00:00"
    time_up_early_non_workday: "10:00:00"
    time_up_late: "09:00:00"
    time_up_late_non_workday: "10:00:00"
    close_position: 0
    time_down_late: "23:00:00"
    time_down_late_non_workday: "23:00:00"
    workday_sensor: binary_sensor.workday_sensor
    position_tolerance: 3
    shading_position: 20
    shading_azimuth_start: 30
    shading_azimuth_end: 140
    shading_weather_conditions: []
    check_config: true
    shading_forecast_temp: 19
    auto_global_condition:
      - condition: state
        entity_id: input_boolean.automatisierung_rollade_standard_automodus
        state: "on"
    shading_elevation_min: 0
    sun_elevation_up: -1.5
    sun_elevation_down: -2.6
    cover_status_helper: input_text.rolladen_status_inputhelper_garten_schlafzimmer_gaube_rechts
    individual_config:
      - prevent_shading_end_if_closed
    auto_shading_start_condition:
      - condition: state
        entity_id: input_boolean.automatisierung_rollade_sonnenschutz
        state: "on"
    ventilate_position: 50
    ventilate_tilt_position: 35
    auto_ventilate_force: input_boolean.automatisierung_rollade_beluftung_nichtschliessen
    auto_ventilate_condition:
      - condition: time
        after: "00:30:00"
        before: "04:30:00"
    shading_sun_brightness_start: 4000
    shading_sun_brightness_end: 3000
    shading_min_temperatur2: 12
    shading_waitingtime_start: 900
    shading_waitingtime_end: 1200
    auto_shading_end_condition: []
    brightness_time_duration: 0
    drive_delay_random: 0
    open_tilt_position: 80
    shading_temperatur_sensor2: sensor.pirateweather_temperature
    shading_forecast_type: weather_attributes
    ignore_after_manual_config:
      - ignore_opening_after_manual
    reset_override_config: reset_timeout
    reset_override_time: "23:00:00"
    auto_shading_start_force: input_boolean.automatisierung_rollade_sonnenschutz_garten_seite_force
    auto_down_force: input_boolean.automatisierung_rollade_alle_schliessen
    is_shading_end_immediate_by_sun_position: false
    reset_override_timeout: 240
    shading_brightness_sensor: sensor.0x001788010e4eed6e_illuminance
    shading_temperature_hysteresis1: 1
    shading_temperature_hysteresis2: 1
    shading_forecast_temp_sensor: sensor.pirateweather_daytime_high_apparent_temperature_0d
    shading_forecast_sensor: weather.pirateweather
    shading_temperature_max_sensor: sensor.pirateweather_daytime_high_temperature_0d
    shading_temperature_max: 19

Nighttime Ventilation in Summer โ€“ Recommended Setup

The use case (close in the evening โ†’ reopen at night for fresh air โ†’ close again before sunrise) is best solved by combining CCA's Force Ventilation feature with a simple separate automation that toggles the force entity on a time schedule.

Why not auto_ventilate_condition?

Important: The auto_ventilate_condition input only gates normal ventilation triggered by window contact sensors. It does not restrict the Force Ventilation entity (auto_ventilate_force). If your force entity is permanently on, the cover stays in forced ventilation mode all day, regardless of any time condition set in auto_ventilate_condition.

Setup

1. Create an input_boolean for Force Ventilation (if you don't have one already), and assign it to auto_ventilate_force in the CCA blueprint config.

2. Create a small helper automation that toggles the boolean on/off at your desired times:

automation:
  - alias: "Bedroom nighttime ventilation - Start"
    trigger:
      - platform: time
        at: "00:30:00"
    action:
      - action: input_boolean.turn_on
        target:
          entity_id: input_boolean.your_ventilation_force_boolean

  - alias: "Bedroom nighttime ventilation - End"
    trigger:
      - platform: time
        at: "04:00:00"
    action:
      - action: input_boolean.turn_off
        target:
          entity_id: input_boolean.your_ventilation_force_boolean

3. Remove auto_ventilate_condition from your CCA config (set it to empty/default) โ€“ the timing is now handled by the on/off toggle of the force entity.

How it works

Time What happens
23:00 CCA closes the cover normally (bas=cls)
00:30 Helper automation turns force boolean on โ†’ CCA immediately sets frc=vnt โ†’ cover moves to ventilation position
04:00 Helper automation turns force boolean off โ†’ CCA auto-recovers to background state (bas=cls) โ†’ cover closes again
09:00 CCA opens the cover normally (bas=opn)

Why this approach works well

  • Force has the highest priority in CCA's cascade โ€“ no other trigger (shading, closing, etc.) can override it while active
  • Automatic recovery: When the force ends at 04:00, CCA returns to the correct background state (closed, since the closing time was 23:00)
  • Clean separation: CCA handles all cover logic, the helper automation only controls when ventilation is active
  • Easy to adjust: Change the times in the helper automation without touching the CCA config. You can also add conditions (e.g., only in summer, only above a certain outside temperature)
1 Like

New Update

CCA 2026.05.27 V2

  • :bug: Fix: Contact sensor "window closed" branches no longer destroy active shading pending phase (pnd, ts.due, ts.arm) โ€” briefly opening and closing a door/window during shading-start or shading-end pending no longer prevents shading from executing (#484)
  • :bug: Fix: "Window closed" branches no longer fire spuriously when cover is at open position but was never in ventilation mode โ€” removed overly broad in_open_position fallback from the "was ventilating before" OR condition (#484)
  • :bug: Fix: Shading end never triggered when only elevation (or only azimuth) was configured as end condition โ€” the combined sun-position trigger t_shading_end_pending_5 used OR logic for azimuth and elevation in a single template, so when azimuth left the range first (without meeting end conditions), the trigger stayed TRUE and never re-fired when elevation later dropped below threshold (#483)
1 Like

@Herr.Vorragend
Hello,
I can't figure out why the shutter is closed. I set it to open at 7:30 a.m. (which works fine), and the shading control kicks in early in the afternoon (south-facing), but at 10:00 a.m., after I close the window, the shutter closes.
I've been trying to figure this out for three days now (but haven't had much luck...)

The configuration, trace, and helper files are here
Files CCA

If I do an update, do I have to reconfigure something or does it take over everything from the version Version: 2026.01.26

just re-import the blueprint again and everything is fine... except new features that might need configuration but they are mostly optional.

@Herr.Vorragend one more thing I just saw, the Forecast option is also named "above threshold" for the Shading End function and I am not sure if its just wrong naming or if the option itself is wrong to be used in Shading End Function because it would check above threshold and not below threshold as I would expect it to do.

Good catch โ€” it's just a wrong label, not a logic bug.

The underlying logic is correct: shading ends when the forecast temperature
drops below your threshold (forecast < threshold โˆ’ hysteresis), exactly as
you'd expect. Only the dropdown label was wrong โ€” it still said "above threshold",
copied from the START side instead of being inverted like the other END conditions
(azimuth โ†’ outside, brightness โ†’ below end, etc.).

Fixed the END labels:

  • ๐Ÿ“Š Forecast Temperature โ†’ now "below threshold"
  • ๐ŸŒฆ๏ธ Forecast Weather Conditions โ†’ now "no longer matching configured conditions"
    (same copy/paste issue โ€” the END logic checks not matching)

Pure label change, no behavior impact. Your existing config keeps working as before.

The text has just been corrected.

1 Like

This is fixed now: fix: window-closed contact handler must follow effective_state, not bare presence by hvorragend ยท Pull Request #488 ยท hvorragend/ha-blueprints ยท GitHub

New Update

CCA 2026.05.28

  • :bug: Fix: Cover no longer closes when the window is closed while a resident is present but privacy-closing is not configured. The contact "window closed" handler treated any resident presence as a privacy-close trigger ("Return to open" required the resident to be absent; "Return to close" fired on mere presence). It now mirrors effective_state: privacy-close applies only when resident_closing_enabled is configured, or when opening is not permitted (resident_allow_opening unset). With bas=opn and no shading, the cover correctly returns to the open position after the window closes.
1 Like

@Herr.Vorragend:
short hint to your cover_status_tile_card:
i moved the cover manually at 5:28 pm, than in the card the following text is shown: "hold until 5:28 pm"!

But that makes no sence! It should be "hold SINCE..." or "hold until ..." but than with the rigth ending time, in my case 5:28 pm + 120 min (reset time of the manual override) or the specified time for the reset!

EDIT: i see that you possibly corrected this yesterday :smiley:

1 Like

How can I use this tile card?

New Update

CCA 2026.05.28 V2

  • :sparkles: Feature: New input "Independent Temperature Threshold" (shading_independent_temp) for the "Independent Shading via Temperature Comparison" mode โ€” previously this mode shared the same threshold as the normal forecast condition, causing both paths to be blocked simultaneously when the threshold wasn't met. The dedicated threshold can be set lower (e.g. 23 ยฐC) while keeping a stricter value in the AND conditions, without either path interfering with the other (#491)
  • :wrench: Improvement: Clarified selector label and description for "Also trigger if Temperature Sensor 2 exceeds Forecast Temperature Value" โ€” the previous label implied a forecast-vs-sensor comparison but the actual logic checks whether Sensor 2 exceeds the (independent) threshold
1 Like