Skip to content

Advanced Use Cases Coupled Indoor Lux

Jason Rhubottom edited this page Aug 5, 2026 · 3 revisions

Indoor lux sensor behind the cover

An indoor illuminance sensor mounted behind the cover it helps control is coupled to that cover: closing the cover shades the sensor, the reading falls, and the low reading looks like "no sun" β€” so the cover reopens. This page shows an asymmetric-latch template sensor that lets you use the shaded lux reading anyway, without the feedback loop.


Why it happens

Cloud suppression treats a low lux reading as "the sun isn't out" and returns the cover to its default position. That works when the sensor sees the sky. It breaks when the sensor sees the inside of a closed cover:

  • Cover open, sun out β€” lux climbs, cloud suppression stays off, the cover tracks the sun and closes. Correct.
  • Cover closed, sun still out β€” the closed cover shades the sensor, lux drops, cloud suppression reads "no sun" and reopens the cover. Wrong β€” but the reading isn't false. It really is dim behind the cover.

Both readings are genuinely true, which is why averaging, a longer delay, or hysteresis (the Handling Variable Cloud Cover patterns) won't fix it β€” those smooth out noisy readings, and this reading isn't noisy. The sensor and the cover are wired together through the room's light: the thing being measured is caused by the thing being controlled.


The fix: an asymmetric latch

Make the sensor asymmetric. A bright reading is trustworthy β€” nothing but real sun pushes indoor lux past a few thousand. A dim reading is ambiguous β€” it might be a genuine overcast, or it might be the cover's own shadow. So: let a bright reading latch the sensor on, never let a dim reading turn it off, and clear the latch overnight so each day has to earn its own close.

template:
  - binary_sensor:
      - name: "Confirmed Sunny (asymmetric)"
        unique_id: confirmed_sunny_asymmetric
        state: >
          {% set lux = states('sensor.indoor_lux') | float(0) %}
          {% set cloudy_now = is_state('weather.home',
               ['cloudy', 'partlycloudy', 'rainy', 'snowy']) %}
          {% if state_attr('sun.sun', 'elevation') | float(0) < 5 %}
            false
          {% elif lux > 3000 %}
            true
          {% elif cloudy_now %}
            false
          {% else %}
            {{ this.state == 'on' }}
          {% endif %}

Replace sensor.indoor_lux with your own indoor lux sensor and weather.home with your weather entity. Then wire the resulting binary sensor to the Is Sunny binary sensor field under Light Sensors & Cloud Suppression, and leave Lux sensor and Irradiance sensor blank.

The branches, in order:

  1. Sun below 5Β° β†’ off. The nightly reset. It has to be first, or a stray bright reading at dusk re-latches the sensor overnight.
  2. Lux above 3000 β†’ on. Real sun latches it.
  3. Weather is cloudy β†’ off. A release path that doesn't depend on the shaded sensor.
  4. Otherwise β†’ hold the previous state (this.state == 'on'). A later dim reading falls through to here and changes nothing, so the cover's own shadow is silently ignored.

Why it self-recovers

The nightly reset is what makes the sensor do real work instead of coasting on yesterday's answer. Every morning the latch starts off, so cloud suppression parks the cover at its default position β€” which leaves the sensor exposed to the sky:

  • Sunny morning β€” lux climbs past 3000, the latch sets, the cover closes.
  • Overcast morning β€” lux stays low, the latch stays off, the cover stays open.
  • Cloud rolls in mid-day β€” the weather entity flips to cloudy, branch 3 releases the latch, the cover opens, the sensor is exposed again. When the sun returns, branch 2 re-latches it.

After a Home Assistant restart the sensor comes up unknown, so the latch starts off and the cover re-earns its close. That's the safe direction to fail β€” an unknown state opens the cover rather than trapping it shut.

You don't need a release branch for "the sun left the window." Cloud suppression only runs while the sun is inside the window's sun acceptance angle and elevation range, so a latch still sitting on after the sun exits can't do anything β€” the solar handler opens the cover on its own.


Keep the raw lux entity out of the threshold path

Every cloud-suppression input (weather state, lux, irradiance, cloud coverage) is combined with OR logic and evaluated independently. If you also wire the shaded sensor into the Lux sensor field, its raw reading will trigger suppression on its own no matter how good the latch is β€” the latch on Is Sunny and the raw lux check would fight each other. The whole point is to route the coupled signal through the latch and nowhere else.


The tradeoff, and how to close it

While the latch is held and the cover is shut, the shaded sensor can't tell you a cloud has arrived β€” you're leaning on the weather entity alone to notice, and weather entities update slowly. If you have an outdoor cloud-cover percentage sensor, add it under Cloud coverage sensor. It isn't shaded by the cover, so it ORs in as genuine mid-close cloud detection without dragging the coupled signal back into the loop.

Tune the two constants to your setup: the 3000 lux threshold (raise it if bright indirect light latches the cover on false alarms, lower it if genuine sun doesn't cross it) and the cloudy weather states list (match your weather integration's state names).


Related pages

  • Handling Variable Cloud Cover: the hysteresis and hold-time patterns for noisy lux readings, and the this.state self-reference idiom this page builds on (Variant C)
  • How It Decides: the full priority chain, including where cloud suppression and solar tracking sit
  • Sun Tracking: lux threshold, Is Sunny sensor, and other tracking settings
  • Advanced Use Cases: all advanced use case recipes

🏠 Home Β· ✨ Features Β· πŸ“° What's New

Buy Me A Coffee

πŸš€ Getting Started

🧠 Core Concepts

πŸ“ Cover Types

βš™οΈ Configuration

πŸ”Œ Entities & Services

πŸ› οΈ Operations

πŸ”§ Advanced Use Cases

🎨 Dashboard

πŸ§ͺ Testing & Simulation

πŸ“š Reference

πŸ‘©β€πŸ’» For Developers

Clone this wiki locally