Home Assistant

Occupancy lighting with a lux gate

PIR or mmWave occupancy turns lights on only when the room is dim, holds them while any sensor is on, and can dim before the final off. A keep-on helper blocks that off for guests.

Difficulty · BeginnerSetup · 20–45 minutesHA · 2024.10 or newer
Get the pack · from $19Have us set it up

Some hardware links on this page are affiliate links. As an Amazon Associate I earn from qualifying purchases. We may earn a commission if you buy through them, at no extra cost to you. See the affiliate disclosure.

A motion light that ignores the sun burns through the afternoon. One that drops the moment a PIR times out drops on anyone reading. This pack turns lights on when any selected occupancy sensor is on and the room is under a lux threshold, waits after the last sensor clears, and only then dims or switches off. A helper can hold the lights for guests. An optional second condition (someone home) keeps a pet from switching the room on.

Entity ids are blueprint inputs. Do not publish which room the sensor watches.

A dim path that only runs at night, without a lux sensor, is adaptive night path. A bathroom that also runs a fan from the door is bathroom light and fan timers. Holding occupancy until a door opens, with no lux test, is wasp-in-a-box occupancy. This one is the everyday room light.

What problem it solves

You want lights that follow PIR or radar, stay off when daylight is enough, and give a dim warning before they go out, without a second automation fighting the brightness.

How it works

The sensor’s device class must be occupancy, motion, or presence, and the state must be on while the room is in use. Occupied means any selected sensor is on.

  1. On — a sensor turns on. If an enable entity is set, it has to be on too (a “someone is home” boolean, so the house can be dark and the lights stay off). If a lux sensor is set, its reading has to be under the threshold (default 60 lux). Brightness and color temperature are optional: 0 percent and 0 K leave the bulb on its last setting. A fade-in can be 0.
  2. Lux grace — for a few seconds after the lights switched off (default 0, so off), the lux check is skipped. Some sensors keep reporting the bright reading of the bulbs that just went out, which would block a person who turned around in the doorway.
  3. Off delay — when sensors go off, the automation waits (default 300 seconds) inside the action, not with a for: on the trigger. mode: restart means a new on cancels that wait and runs the on branch again. The delay is from the last sensor to clear, because a new on restarts the run. After the wait, every reachable sensor still has to be off. unavailable does not count as occupied and does not, by itself, block the off.
  4. Manual off during the exit — the off step only runs if at least one of the off-target lights is still on. If you already switched them off, the sequence stops instead of turning them back on.
  5. Dim before off — optional. After the delay the lights fade to a dim level (default 20 percent over 30 seconds) and hold (default 5 minutes). A sensor on during that hold restarts the automation and restores the on state. Then they turn off.
  6. Keep on — optional helper. While it is on, the off branch does not run. Turning the helper off in an empty room starts the normal off. Turning it off while someone is still there does not kill the lights, because the off branch also requires every sensor to be clear.
  7. Schedule — optional. When enabled, the on branch also requires a schedule helper to be on. The off branch does not check the schedule, so lights can still go out after the window ends.

The on targets and the off targets are separate. A porch light can come on with the hall and stay out of the dim group.

Needs Home Assistant 2024.10 or newer (the blueprint uses triggers: / actions:).

Hardware notes

  • PIR. Any motion binary you already have. An HC-SR501 is the “nothing is installed” option. Set its onboard hold short and let this blueprint’s off delay be the timer.
  • mmWave. An LD2410C on an ESP32-C6, wired as in the mmWave presence guide, stays on while someone sits still. Use it when a PIR’s timeout is the bug you are fixing. Device class should be occupancy.
  • Lux. Optional. A sensor in the same room, device class illuminance. Skip it and the lights follow occupancy in daylight too. The grace period is for sensors that are blinded by the bulb.
  • Bulbs. Dim-before-off needs a light that accepts brightness_pct. A switch-only relay can still use the pack with dimming left off.
  • Board. Only if the PIR or radar is a bare module. A mains-powered ESP32-C6 pattern is enough. Leave the strap pins alone.

Snippet

The pack ships a blueprint. This is the on gate and the restarting off delay:

mode: restart
max_exceeded: silent

trigger:
  - platform: state
    entity_id: !input occupancy_sensors
    to: "on"
    id: occupied
  - platform: state
    entity_id: !input occupancy_sensors
    to: "off"
    id: clear

action:
  - choose:
      - conditions:
          - condition: trigger
            id: occupied
          - condition: numeric_state
            entity_id: !input illuminance_sensor
            below: !input lux_threshold
        sequence:
          - action: light.turn_on
            target: !input lights_on
            data:
              brightness_pct: !input brightness_pct
      - conditions:
          - condition: trigger
            id: clear
        sequence:
          - delay:
              seconds: !input off_delay_seconds
          - action: light.turn_off
            target: !input lights_off

The real blueprint’s lux condition is skipped when no illuminance sensor is selected, and again during the grace period. The clear branch also refuses to run while the keep-on helper is on, and it re-checks that every reachable sensor is still off after the delay. Dim-before-off replaces the bare light.turn_off with a dim, a hold, and then the off.

Setup outline

  1. Confirm each sensor’s device class and that it reads on when you walk in. Import the blueprint.
  2. Select the sensors, the lights to turn on, and the lights to turn off. Set the lux threshold if you have a sensor. Set brightness to 0 if the bulbs should keep their own level.
  3. Set the off delay in seconds (10 for a hall, 300 for a desk). Leave dim-before-off and the keep-on helper off until the basic on/off is right.
  4. Walk in under the threshold: lights on. Stand still with a PIR only: lights follow the PIR’s own hold plus your delay. Walk in again during the delay: lights stay on. Cover the lux sensor in daylight and confirm they stay off above the threshold.
  5. Turn dim-before-off on and confirm a new step into the room during the dim hold restores the on brightness. Turn the keep-on helper on and confirm the room does not go dark when you leave.

Troubleshooting

  • Sensor never triggers. Device class is missing (opening, door, or none). The blueprint only lists occupancy, motion, and presence. Mirror the state onto an input_boolean if the device will not take a class, and select that boolean only if you also give it a matching class — or widen the selector in a local copy. Check Developer Tools while you walk.
  • Lights on in the afternoon. No illuminance sensor is selected, or the threshold is above the daylight reading. Watch the lux entity at the hour you care about and set the threshold under that.
  • Lights refuse to come back on after they just went off. The lux sensor still reads the bulb. Raise the grace period (a few seconds is enough for most; the input allows up to 300).
  • Lights drop while you sit. The sensor is a PIR and its hold expired. That is what the PIR reports. Add an mmWave sensor to the same list, or lengthen the off delay.
  • Dim never happens. Dim-before-off is off, the off targets are switches rather than lights, or you turned the lights off yourself before the dim step (the sequence stops when none of them are on).
  • Guests go dark. The keep-on helper is off, or it is not the entity the blueprint is watching. Turning it off in an empty room is supposed to start the off sequence.
  • Pet turns the lights on. Set the enable entity to a person-home boolean. While that entity is off, occupancy does not turn lights on. Off still runs.

Credits

Based on the community blueprint Clean & Simple Universal Occupancy Lighting for PIR & Radar Sensors, v2.1 (forum thread). This write-up is an original overview of the lux gate, the restarting off delay, dim-before-off, and the keep-on helper.

Changelog

v1.0 · Oct 27, 2026: First publish.