Skip to content

Advanced Use Cases Cloudy Days

Jason Rhubottom edited this page Jun 2, 2026 · 4 revisions

Handling variable cloud cover

On days with passing clouds, lux sensors can cause covers to yo-yo: lux drops below the suppression threshold, the cover opens to the default position, lux recovers, and the cover closes again. This page shows three approaches to smooth that out, from a single config change to a full template sensor workaround.


Why it happens

Cloud suppression runs at priority 60 in the pipeline. When any configured cloud-suppression input (lux, irradiance, cloud coverage, weather state) indicates it isn't sunny enough, solar tracking is skipped and the cover returns to the default position. Because lux sensors respond immediately to lighting changes, a cloud passing for two or three minutes is enough to trigger the full open-then-close cycle.

Weather entity caveat: The inputs are combined with OR logic β€” if you've configured a weather entity, a forecast of cloudy will trigger suppression even when your lux sensor is reading bright sun. Forecasts are coarse and slow to update, so if you have a reliable lux sensor it's usually best to leave the weather entity unset and let lux drive cloud suppression alone.

⚠️ Is Sunny Sensor + raw lux anti-pattern: If you configure an is_sunny_sensor (debounced binary sensor) and a Lux entity simultaneously, the two signals are OR-combined independently. is_sunny_sensor = ON prevents the weather-state trigger but does not suppress the lux check β€” a raw lux reading crossing the threshold will fire cloud suppression regardless of how stable your binary sensor is. To use is_sunny_sensor as a debounce gate, leave the Lux / Irradiance / Cloud Coverage entity fields unset (see Variant C below).


Option 1: Lower the lux threshold

The simplest fix. 3500lx triggers on brief cloud passages in many climates; a genuine overcast typically drops lux far lower. Try 1000lx and test over a few days. Most short cloud passages won't cross the threshold; the cover stays at its tracked position until the cloud clears.

Set the threshold under Sun Tracking β†’ Lux Threshold in the integration's options.


Option 2: Raise the default position

Cloud suppression returns the cover to the configured default position. If that's 0% (fully retracted), the cover swings fully open on every cloud patch. Setting the default to 20-30% limits how far it opens, so the motion is smaller even when suppression does fire.

Set the default under Position β†’ Default Position.


Option 3: Add a hold time via a template sensor

HA template binary sensors support delay_on, which only activates after the condition has been true for a set duration. Two variants, depending on what behavior you want when a genuine overcast arrives.

Variant A: partial open, cloud suppression bypassed

Remove the lux entity from the integration's cloud suppression config. Create a template binary sensor with delay_on and wire it to a Custom Position slot at priority 65:

template:
  - binary_sensor:
      - name: "Genuinely Cloudy"
        state: "{{ states('sensor.your_lux_sensor') | int < 3500 }}"
        delay_on:
          minutes: 5

Then configure a Custom Position slot:

Setting Value
Custom Position Sensor binary_sensor.genuinely_cloudy
Custom Position 20-25%
Priority 65

Behavior: brief clouds are ignored and solar tracking continues. After 5 minutes below threshold the custom position fires, holding the cover partway rather than fully open. When the cloud clears, the sensor turns off immediately and solar tracking resumes.

... β†’ Custom(65: partial open) β†’ Cloud Suppression(60: bypassed) β†’ Solar(40) β†’ ...

Variant B: keep cloud suppression, add hold time with hysteresis

Keep the lux entity in cloud suppression but feed it a debounced numeric sensor. The binary sensor uses two thresholds with hysteresis β€” it switches on after lux is below 2500lx for 5 minutes, and only switches off after lux is above 3500lx for 5 minutes. This Schmitt-trigger pattern prevents flapping when readings hover near a single threshold.

template:
  - binary_sensor:
      - name: "Lux Below Threshold"
        unique_id: lux_below_threshold
        delay_on:
          minutes: 5
        delay_off:
          minutes: 5
        state: >
          {% set lux = states('sensor.your_lux_sensor') | float(0) %}
          {% if lux < 2500 %}
            true
          {% elif lux > 3500 %}
            false
          {% else %}
            {{ this.state == 'on' }}
          {% endif %}

  - sensor:
      - name: "Debounced Lux"
        unique_id: debounced_lux
        unit_of_measurement: lx
        device_class: illuminance
        state: >
          {% if is_state('binary_sensor.lux_below_threshold', 'on') %}
            0
          {% else %}
            10000
          {% endif %}

Use sensor.debounced_lux as the lux entity in cloud suppression with threshold 3500lx.

Behavior: Brief dips below 2500lx are ignored; cloud suppression only fires once it's been genuinely dim for 5 minutes. Once active, it stays active until lux climbs back above 3500lx for 5 minutes β€” so a momentary patch of sun during an overcast doesn't bounce the cover. The two-threshold band (2500 / 3500) plus the symmetric delays gives smooth, predictable behavior in mixed conditions.

... β†’ Cloud Suppression(60: fires after 5 min below 2500lx, releases after 5 min above 3500lx) β†’ Solar(40) β†’ ...

Thanks to @MSL-DA for contributing this hysteresis pattern.

Variant C: direct binary sensor (cloud suppression only)

If you only need the hold time for cloud suppression and have no other use for a numeric debounced lux value, you can skip the second template sensor entirely. Create a single "Is Sunny" binary sensor with inverted Schmitt logic β€” ON when bright, OFF when dim β€” and wire it straight to the integration's Is Sunny binary sensor field.

template:
  - binary_sensor:
      - name: "Is Sunny"
        unique_id: is_sunny_debounced
        delay_on:
          minutes: 5
        delay_off:
          minutes: 5
        state: >
          {% set lux = states('sensor.your_lux_sensor') | float(0) %}
          {% if lux > 3500 %}
            true
          {% elif lux < 2500 %}
            false
          {% else %}
            {{ this.state == 'on' }}
          {% endif %}

In the integration options, open Light Sensors & Cloud Suppression, turn on Enable cloud suppression (the master switch), and set Is Sunny binary sensor to binary_sensor.is_sunny_debounced. Leave the Lux sensor entity unset β€” this binary sensor is doing the work. When it reads OFF, cloud suppression fires regardless of weather state; when ON or unavailable, the integration tracks the sun normally (falling back to weather logic if the sensor is unknown).

Behavior: same Schmitt-trigger and hold-time characteristics as Variant B. Cloud suppression fires when the sensor has been OFF (lux < 2500) for 5 minutes and releases once it has been ON (lux > 3500) for 5 minutes.

... β†’ Cloud Suppression(60: fires after 5 min below 2500lx, releases after 5 min above 3500lx) β†’ Solar(40) β†’ ...

Prefer Variant B if you want to reuse a numeric debounced lux value elsewhere in HA (e.g., dashboard cards, other automations). Prefer Variant C if cloud suppression is the only goal β€” one sensor is sufficient.


Choosing between the variants

Variant A Variant B Variant C
Brief cloud (< 5 min) Cover stays at solar-tracked position Cover stays at solar-tracked position Cover stays at solar-tracked position
Extended cloud (> 5 min) Cover moves to configured partial position Cover moves to default position Cover moves to default position
Cloud suppression handler fires No Yes Yes
Template sensors needed 1 binary 1 binary + 1 numeric 1 binary
Decision trace during cloud solar or custom_position cloud_suppression cloud_suppression

Use Variant A when you want the cover to hold at a specific partial position during overcast. Use Variant B when you want the standard cloud-suppression fallback delayed and you want a debounced numeric lux value reusable elsewhere in HA. Use Variant C when you only need the cloud-suppression hold time β€” one binary sensor wired to Is Sunny binary sensor is enough.


Diagnosing the behavior

Check sensor.{your_device}_decision_trace. The state shows which handler won; the trace attribute lists every handler that evaluated and why. During a cloud patch you should see cloud_suppression (Variant B, or no debounce configured) or solar / custom_position (Variant A).


Related pages

Clone this wiki locally