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 PIR turns the lights off on anyone who sits still. A door contact alone cannot tell whether the person stayed in the room. Wasp-in-a-box uses both. The room is the box. If motion is seen while the door is closed, the occupant cannot have left, so occupancy stays on until the door opens again. Lights and climate follow that helper, not the raw motion sensor.
Entity ids below are stand-ins (binary_sensor.front_door_contact, binary_sensor.room_motion, input_boolean.room_occupied). The pack ships the same logic as a blueprint with !input selectors. Do not publish which room the contact belongs to.
What problem it solves
You want lights and climate to stay on for someone reading or working in a closed room, and to release when they actually leave, without an mmWave sensor and without a motion timeout that guesses wrong.
How it works
For a contact with device_class: door, on is open and off is closed. If your sensor is inverted, fix that before you trust the helper.
- Latch — motion goes
onwhile the door isoff(closed). Turninput_boolean.room_occupiedon. A later motionoffdoes not clear it. Sitting still is the point. - Entry — motion while the door is still open also turns the helper on (someone is in the doorway). When they close the door and stop moving, the helper stays on, because clearing is not allowed while the door is closed.
- Leave — the helper turns off only when the door is open and motion has been
offfor a short delay (pack default 30 seconds). Walking out keeps the lights up until the PIR actually drops. A door that stays shut keeps the latch even if motion has been off for an hour. - Actions — occupied actions run when the helper turns on (lights, climate resume, or whatever you list). Clear actions run when it turns off. Put a short off-delay on the lights if the doorway feels abrupt. Climate can follow the helper directly.
- Bypass — an optional boolean forces the helper off and holds it there while the bypass is on. Use it when someone left and shut the door behind them (see the limitation below). Turning the bypass off does not invent occupancy; the next real motion edge does.
mode: queued so a motion edge during the clear delay is not dropped. The helper is the state that survives a restart. A wait_template inside one run does not.
Limitation
Shutting the door as you leave can look the same as shutting it as you enter. If the helper was already on, closing the door keeps it on until the door opens again or you flip the bypass. That is the box rule, not a bug in the condition. A PIR aimed at the door swing makes it worse. Aim the sensor at the part of the room where a person sits, and keep its onboard retrigger short so Home Assistant sees real edges.
A room with a second door needs every door in one group. One unmonitored door breaks the assumption.
Hardware notes
- Door. Any
binary_sensoryou already have. Group several contacts if the room has more than one way out. The blueprint treats the group the same as one sensor: open if any member is open. - Motion. Any motion binary. A PIR you already have is enough. The HC-SR501 is the “nothing is installed” option. Set its delay pot short and let the clear delay in this automation be the timer.
- Loads. Lights and climate stay in the action lists. The helper does not know room names. Do not point clear-actions at a climate entity that also has its own motion automation, or the two will fight.
Snippet
Stand-in ids. Replace them, or use the blueprint inputs in the pack.
mode: queued
max_exceeded: silent
trigger:
- platform: state
entity_id: binary_sensor.room_motion
to: "on"
id: motion
- platform: state
entity_id: binary_sensor.room_motion
to: "off"
for:
seconds: 30
id: still
- platform: state
entity_id: binary_sensor.front_door_contact
to: "on"
id: door_open
- platform: state
entity_id: input_boolean.room_occupied
to: "on"
id: occupied
- platform: state
entity_id: input_boolean.room_occupied
to: "off"
id: vacant
- platform: state
entity_id: input_boolean.room_bypass
to: "on"
id: bypass
action:
- choose:
- conditions:
- condition: trigger
id: bypass
sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.room_occupied
- conditions:
- condition: state
entity_id: input_boolean.room_bypass
state: "on"
sequence:
- stop: "Bypass is holding the room vacant"
- conditions:
- condition: trigger
id: motion
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.room_occupied
- conditions:
- condition: trigger
id: still
- condition: state
entity_id: binary_sensor.front_door_contact
state: "on"
sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.room_occupied
- conditions:
- condition: trigger
id: door_open
- condition: state
entity_id: binary_sensor.room_motion
state: "off"
sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.room_occupied
- conditions:
- condition: trigger
id: occupied
sequence:
- service: light.turn_on
target:
entity_id: light.room
- service: climate.turn_on
target:
entity_id: climate.room
- conditions:
- condition: trigger
id: vacant
sequence:
- service: light.turn_off
target:
entity_id: light.room
- service: climate.turn_off
target:
entity_id: climate.room
The motion trigger latches occupancy whether or not you later add a “door must be closed” condition. The clear is what checks the door. Motion that goes off while binary_sensor.front_door_contact is off (door shut) does not match the still-branch, so the helper stays on. The door-open trigger clears immediately only when motion is already off; otherwise the 30 second still-trigger finishes the exit.
light.room and climate.room are stand-ins for the loads you actually want. Drop either service if that room has no such entity.
Setup outline
- Create
input_boolean.room_occupiedandinput_boolean.room_bypass. Confirm the door contact readsonwhen the door is open. - Import the blueprint (or paste the automation) and fill the door, the motion sensor, the helper, the clear delay, and the occupied / clear actions.
- Shut the door, wave, stand still for longer than the PIR timeout. The helper stays on and the lights stay on.
- Open the door and leave. After motion drops and the clear delay passes, the helper turns off and the clear actions run.
- Flip the bypass, wave, and confirm the helper stays off until the bypass is off again.
Troubleshooting
- Lights drop while you sit with the door shut. Clear is not checking the door, or a second automation is still using raw motion. Disable the old motion-off automation for those lights.
- Room stays occupied after you left and closed the door. The helper was on, and the box rule will not clear it while the door stays shut. Open the door once, or turn the bypass on. Aim the PIR off the door so the next exit is a clean “door open, then still.”
- Never latches. The motion sensor’s device class or state is not
on, or the bypass is on. Watch Developer Tools while you walk through. - Clears the moment the door opens, in the dark. The door-open branch is not requiring motion to be off, or the clear delay is 0. Keep the delay at least as long as the PIR’s hold time.
- Door contact is backwards.
onmeans open fordevice_class: door. An inverted contact latches and clears on the wrong edge. Invert it in the sensor, not with a second boolean in this automation. - Two doors, one sensor. The unmonitored door is a hole in the box. Group every contact that can let someone out.
Credits
Based on the community blueprint WITB+ (Wasp in the Box Plus). This write-up is an original occupancy latch: motion while the door is shut holds lights and climate until the door opens, with a short clear delay on the way out and a bypass for the shut-door exit.