Adaptive Cover

May 31, 2026 Β· View on GitHub

πŸ‡«πŸ‡· Documentation en franΓ§ais

Version Home Assistant

logo logo

Adaptive Cover

This Custom-Integration provides sensors for vertical and horizontal blinds based on the sun's position by calculating the position to filter out direct sunlight.

This integration builds upon the template sensor from this forum post Automatic Blinds

Features

  • Individual service devices for vertical, horizontal and tilted covers

  • Three strategy modes: basic, climate, security

  • Binary Sensor to track when the sun is in front of the window

  • Sensors for start and end time

  • Auto manual override detection

  • Climate Mode

    • Weather condition based operation
    • Presence based operation
    • Switch to toggle climate mode
    • Sensor for displaying the operation modus (winter, intermediate, summer)
    • Diagnostic sensor exposing all intermediate climate decision values
  • Security Mode (v1.9+)

    • Automatically closes covers when nobody is home
    • Per-group switch (visible only when a presence entity is configured)
    • Hub switch for global activation across all groups
    • Manual override always wins β€” covers in manual control are never moved
    • Automatic return to adaptive positioning when presence is restored
    • Fail-safe: unavailable presence sensor β†’ security stays inactive
  • Adaptive Control

    • Turn control on/off
    • Control multiple covers
    • Set start time to prevent opening blinds while you are asleep
    • Set minimum interval time between position changes
    • Set minimum percentage change
  • All Blinds hub device (v1.8+)

    • Single aggregate cover entity controlling every blind at once
    • 4-state control select (Auto / Off / All open / All closed)
    • ON/OFF switch for Alexa voice control ("Alexa, turn on / turn off the blinds")
    • Security switch for Alexa ("Alexa, activate blind security")
    • Scene shortcuts for automations
    • Native Alexa, Google Assistant and Assist support

Installation

Add https://github.com/kamahat/adaptive-cover as custom repository to HACS. Search and download Adaptive Cover within HACS.

Restart Home-Assistant and add the integration.

Manual

Download the adaptive_cover folder from this github. Add the folder to config/custom_components/.

Restart Home-Assistant and add the integration.

Setup

Adaptive Cover supports (for now) three types of covers/blinds; Vertical and Horizontal and Venetian (Tilted) blinds. Each type has its own specific parameters to setup a sensor. To setup the sensor you first need to find out the azimuth of the window(s). This can be done by finding your location on Open Street Map Compass.

When adding the integration for the first time, a menu is shown:

  • Add a cover group β€” configure a Vertical, Horizontal or Tilt blind group (one per window or room).
  • Add 'All Blinds' aggregator β€” creates the singleton hub device that controls all groups at once. Created automatically on first setup if not yet present.

Cover Types

VerticalHorizontalTilted
alt textalt textalt text
MovementUp/DownIn/OutTilting
variablesvariablesvariables

Modes

This component supports three strategy modes: a basic mode, a climate (comfort/energy saving) mode that works with presence and temperature detection, and a security mode that closes covers when nobody is home.

ModePriorityDescription
basic3 (base)Pure sun-position tracking
climate2Adapts to temperature β€” summer / winter / intermediate
security1 (highest)Closes covers on absence β€” overrides all other logic including outside the time window
flowchart TD
    START(["β˜€οΈ Sun data update"])

    START --> CTRL{"Toggle Control\nswitch ON?"}
    CTRL -- No --> DEFAULT["↩️ Return default\nposition"]

    CTRL -- Yes --> SECURITY{"πŸ›‘οΈ Security mode\nON + no presence?"}
    SECURITY -- "Yes\n(absent)" --> SECPOS["πŸ›‘οΈ Security position\n0% or min_position\n(0% if no climate\nor summer branch)"]
    SECURITY -- No --> TIME{"Within active\ntime window?"}
    TIME -- No --> SUNSET["πŸŒ™ Return sunset /\ndefault position"]

    TIME -- Yes --> MANUAL{"Manual override\nactive?"}
    MANUAL -- Yes --> HOLD["πŸ”’ Hold current\nposition"]

    MANUAL -- No --> SUN{"Sun in field of view\nAND elevation > 0?"}
    SUN -- No --> DEFAULT

    SUN -- Yes --> CLMODE{"Climate\nMode?"}

    %% ── BASIC MODE ────────────────────────────────
    CLMODE -- No --> CALC["πŸ“ Calculate optimal\nposition from sun geometry"]
    CALC --> LIMITS

    %% ── CLIMATE MODE ──────────────────────────────
    CLMODE -- Yes --> PRES{"Presence\ndetected?"}
    PRES -- "No" --> PNONE["min_position or 0%"]

    PRES -- "Yes" --> WCHECK{"❄️ WINTER?\ntemp_winter < temp_low\ntemp_winter = inside preferred\n              outside as fallback"}
    WCHECK -- Yes --> OPEN["πŸͺŸ Open fully (100%)\nsolar gain"]

    WCHECK -- No --> SCHECK{"🌑️ SUMMER?\ntemp_summer > temp_high\nAND outside_high\ntemp_summer = outside if temp_switch=ON\n              else inside\noutside_high = outside > temp_summer_outside\n              (True if not configured)"}
    SCHECK -- Yes --> TRANSP{"Transparent / perforated blind?\n(filters only β€”\ncannot fully block heat)"}
    TRANSP -- "Yes\n(filter only)" --> CALC
    TRANSP -- "No\n(opaque)" --> CLOSE["πŸͺŸ Close fully (0%)\nblock heat"]

    SCHECK -- "No\n(intermediate)" --> LIGHT{"Not sunny? β€” OR of 3 conditions\nβ‘  lux ≀ threshold  (if switch ON + entity set)\nβ‘‘ irradiance ≀ threshold  (if switch ON + entity set)\nβ‘’ weather state not in sunny list\nAbsent/OFF sensor = neutral"}
    LIGHT -- "Yes\n(at least one true)" --> DEFAULT
    LIGHT -- "No\n(all false β†’ sunny)" --> CALC

    %% ── COMMON FINAL STEPS ────────────────────────
    LIMITS["πŸ”§ Apply min / max position limits\n+ blind spot correction\n+ delta position check"]
    OPEN --> LIMITS
    CLOSE --> LIMITS
    PNONE --> LIMITS
    SECPOS --> LIMITS

    LIMITS --> RESULT(["βœ… Apply new position\nto cover(s)"])

    %% ── STYLES ────────────────────────────────────
    style CLOSE   fill:#f28b82,color:#000
    style OPEN    fill:#81c995,color:#000
    style CALC    fill:#78b7f5,color:#000
    style RESULT  fill:#34a853,color:#fff
    style HOLD    fill:#fbbc04,color:#000
    style SUNSET  fill:#aecbfa,color:#000
    style DEFAULT fill:#e8eaed,color:#000
    style SECURITY fill:#ff9800,color:#fff,stroke:#e65100
    style SECPOS   fill:#ff9800,color:#fff,stroke:#e65100
    style PNONE    fill:#e8eaed,color:#000
    style LIGHT    fill:#8e44ad,color:#fff,stroke:#6c3483
    style WCHECK  fill:#1a5276,color:#fff
    style SCHECK  fill:#922b21,color:#fff

Execution priority: Security (1) > Climate (2) > Basic (3). Security is evaluated before the time window check.

Climate classification β€” three mutually exclusive branches (temp_low < temp_high by design):

BranchConditionTemp reference
WINTERtemp_winter < temp_lowinside preferred, outside fallback β€” always
SUMMERtemp_summer > temp_high AND outside_highoutside if temp_switch=ON, else inside
INTERMEDIATEneither WINTER nor SUMMERβ€”

Why the asymmetry? WINTER checks indoor comfort. SUMMER optionally uses outdoor temp (temp_switch=ON) to confirm genuine heat outside. WINTER wins in the edge case where both conditions are true simultaneously (only possible when temp_switch=ON).

Basic mode

This mode uses the calculated position when the sun is within the specified azimuth range of the window. Else it defaults to the default value or after sunset value depending on the time of day.

Climate mode

This mode calculates the position based on extra parameters for presence, indoor temperature, minimal comfort temperature, maximum comfort temperature and weather (optional).

Climate strategies

  • No Presence: Returns min_position (or 0% if not configured). No temperature calculation needed.

  • Presence (or no Presence Entity set):

    • Winter (temp_winter < temp_low): Opens fully (100%) to capture solar heat.
      • temp_winter = indoor temperature (outdoor as fallback if indoor not configured).
    • Summer (temp_summer > temp_high AND outside_high): Closes or shades.
      • temp_summer = outdoor temperature if temp_switch=ON, else indoor.
      • outside_high = extra guard: outdoor > temp_summer_outside threshold (True by default if not set).
      • Transparent/perforated blind β†’ calculate position (filtering only)
      • Opaque blind β†’ close fully (0%)
    • Intermediate: "not sunny?" is an OR of three independent sources:
      • lux ≀ threshold / irradiance ≀ threshold (only if switch ON and entity configured)
      • weather state not in sunny list
      • One source true β†’ default position. All false β†’ adaptive calculation.

    For tilted blinds above summer threshold: slats positioned at 45Β° (found optimal).

Security mode

Security mode closes covers automatically when nobody is home, regardless of the current climate branch and regardless of the configured time window.

Requires a presence entity to be configured in the entry options. Without one, the switch exists but has no effect.

SituationTarget position
No climate mode0% (fully closed)
Climate mode + summer branch0% (fully closed)
Climate mode + winter or intermediatemin_position (or 0% if unset)

Key behaviours:

  • Manual override always wins β€” covers already in manual control are never moved by security
  • Automatic return β€” when presence is restored, adaptive positioning resumes without manual action
  • Fail-safe β€” unavailable presence sensor β†’ security inactive
  • Outside time window β€” security applies even outside the configured start/end hours

Variables

Common

VariablesDefaultRangeDescription
Entities[]Denotes entities controllable by the integration
Window Azimuth1800-359The compass direction of the window, discoverable via Open Street Map Compass
Default Position600-100Initial position of the cover in the absence of sunlight glare detection
Minimal Position1000-99Minimal opening position for the cover β€” also used by security mode in winter/intermediate
Maximum Position1001-100Maximum opening position for the cover
Field of view Left901-90Unobstructed viewing angle from window center to the left, in degrees
Field of view Right901-90Unobstructed viewing angle from window center to the right, in degrees
Minimal ElevationNone0-90Minimal elevation degree of the sun to be considered
Maximum ElevationNone1-90Maximum elevation degree of the sun to be considered
Default position after Sunset00-100Cover's default position from sunset to sunrise
Offset Sunset time0Additional minutes before/after sunset
Offset Sunrise time0Additional minutes before/after sunrise
Inverse StateFalseCalculates inverse state for covers fully closed at 100%

Vertical

VariablesDefaultRangeDescription
Window Height2.10.1-6Length of fully extended cover/window
Glare Zone0.50.1-2Objects within this distance of the cover receive direct sunlight

Horizontal

VariablesDefaultRangeDescription
Awning Height20.1-6Height from work area to awning mounting point
Awning Length (horizontal)2.10.3-6Length of the awning when fully extended
Awning Angle00-45Angle of the awning from the wall
Glare Zone0.50.1-2Objects within this distance of the cover receive direct sunlight

Tilt

VariablesDefaultRangeDescription
Slat Depth30.1-15Width of each slat
Slat Distance20.1-15Vertical distance between two slats in horizontal position
Tilt ModeBi-directionalmode1: single direction 0°–90Β° / mode2: bi-directional 0°–180Β°

Automation

VariablesDefaultRangeDescription
Minimum Delta Position11-90Minimum position change required before another change can occur
Minimum Delta Time2Minimum time gap between position changes (minutes)
Start Time"00:00:00"Earliest time a cover can be adjusted after midnight
Start Time EntityNoneOverrides start_time if set
Manual Override Duration15 minMinimum duration for manual control status to remain active
Manual Override reset TimerFalseResets duration timer each time the position changes while the manual control status is active
Manual Override ThresholdNone1-99Minimal position change to be recognized as manual change
Manual Override ignore intermediate statesFalseIgnore StateChangedEvents that have state opening or closing
End Time"00:00:00"Latest time a cover can be adjusted each day
End Time EntityNoneOverrides end_time if set
Adjust at end timeFalseMake sure to always update the position to the default setting at the end time

Climate

VariablesDefaultRangeExampleDescription
Indoor Temperature EntityNoneclimate.living_room | sensor.indoor_tempUsed for WINTER check; fallback for SUMMER when temp_switch=OFF
Minimum Comfort Temperature210-86WINTER threshold β€” below this, open 100% for solar gain
Maximum Comfort Temperature250-86SUMMER threshold β€” above this, close 0% to block heat
Outdoor Temperature EntityNonesensor.outdoor_tempUsed for SUMMER when temp_switch=ON; optional WINTER fallback
Outdoor Temperature ThresholdNoneExtra SUMMER guard: activates only when outdoor temp also exceeds this. Inactive when not set.
Use Outside Temperature (temp_switch)FalseON β†’ outdoor temp primary for SUMMER check. WINTER always uses indoor.
Presence EntityNoneUsed for both climate mode AND security mode
Weather EntityNoneweather.homeTemperature source when no sensor; also drives "not sunny" check
Weather ConditionNoneStates considered "sunny" β€” state not in list β†’ contributes "not sunny" (OR with lux + irradiance)
Transparent BlindFalseEnable if blind is perforated/mesh β€” filters only, keeps adaptive positioning in summer
Lux EntityNonesensor.luxMeasured lux
Lux Threshold1000Below threshold β†’ "not sunny" (OR with irradiance + weather). Switch OFF = neutral.
Irradiance EntityNonesensor.irradianceMeasured irradiance
Irradiance Threshold300Below threshold β†’ "not sunny" (OR with lux + weather). Switch OFF = neutral.

Blindspot

VariablesDefaultRangeDescription
Blind Spot LeftNone0-max(fov_right, 180)Start point of the blind spot on the predefined field of view
Blind Spot RightNone1-max(fov_right, 180)End point of the blind spot on the predefined field of view
Blind Spot ElevationNone0-90Minimal sun elevation for the blindspot to apply

Entities

Per-cover entry entities

The integration dynamically adds multiple entities based on the used features.

These entities are always available for each cover group:

EntityDefaultDescription
sensor.{type}_cover_position_{name}Reflects the current target position (%)
sensor.{type}_control_method_{name}intermediateActive strategy: winter, summer, intermediate
sensor.{type}_start_sun_{name}Time when the sun enters the window's FOV (updated every 5 min)
sensor.{type}_end_sun_{name}Time when the sun exits the window's FOV (updated every 5 min)
binary_sensor.{type}_manual_override_{name}offTrue when manual override is active for any blind in the group
switch.{type}_toggle_control_{name}onActivates adaptive control
switch.{type}_manual_override_{name}onEnables detection of manual overrides
button.{type}_reset_manual_override_{name}Resets manual override tags for all covers in the group

When climate mode is configured:

EntityDefaultDescription
switch.{type}_climate_mode_{name}onEnables climate mode strategy
switch.{type}_outside_temperature_{name}offtemp_switch β€” outdoor temp primary for SUMMER check
switch.{type}_lux_{name}onEnable lux threshold β€” OFF = lux ignored (neutral)
switch.{type}_irradiance_{name}onEnable irradiance threshold β€” OFF = irradiance ignored (neutral)
sensor.{type}_climate_debug_{name}Diagnostic sensor with full climate decision snapshot

When a presence entity is configured:

EntityDefaultDescription
switch.{type}_security_mode_{name}offSecurity mode β€” closes covers when no presence detected

All Blinds hub entities

The All Blinds device (auto-created on first setup) exposes:

EntityNameDescription
cover.*Les voletsAggregate cover β€” open/close/set position acts on all covers
switch.*Les voletsON/OFF adaptive control across all entries
switch.*SΓ©curitΓ© voletsON/OFF security mode across all entries that have a presence entity
select.*Control mode4-state: Auto / Off / All open (100%) / All closed (0%)
scene.*_all_openBlinds openSets all covers to 100%
scene.*_all_closedBlinds closedSets all covers to 0%

entities

All Blinds hub device

The All Blinds entry is a singleton aggregator automatically created when the integration first loads. It has its own device card in the HA UI and does not interfere with individual cover group settings.

It can also be added manually: Settings β†’ Integrations β†’ Adaptive Cover β†’ Add entry β†’ Add 'All Blinds' aggregator.

Voice control

The hub device is designed for native voice assistant integration β€” no custom routines needed:

Voice phraseEntity triggeredAction
"Alexa, turn on the blinds"switch Les volets ONAdaptive control enabled, manual overrides cleared
"Alexa, turn off the blinds"switch Les volets OFFAdaptive control disabled
"Alexa, open the blinds"cover Les volets openAll covers β†’ 100%
"Alexa, close the blinds"cover Les volets closeAll covers β†’ 0%
"Alexa, activate blind security"switch SΓ©curitΓ© volets ONSecurity mode enabled β€” covers close on absence
"Alexa, deactivate blind security"switch SΓ©curitΓ© volets OFFSecurity mode disabled

Alexa routes commands by verb type: turn on/off β†’ switch, open/close β†’ cover.
The same entity names work with Google Assistant and Assist.

To re-sync Alexa after upgrading: say "Alexa, discover my devices" or go to the Alexa app β†’ Devices β†’ More β†’ Discover devices.

Features Planned

  • Manual override controls

    • Time to revert back to adaptive control
    • Reset button
    • Wait until next manual/none adaptive change
  • Algorithm to control radiation and/or illumination


Contributors

ContributorRole
πŸ§‘β€πŸ’»KamahatFork maintainer, feature development, bug fixes
πŸ€–Claude Opus 4.7 (Anthropic)Code review, bug fixes, EN/FR documentation, changelog
⭐Bas Brussee (@basbruss)Original author

See CONTRIBUTORS.md for the full list including community contributors.