As a backend dev who runs his own network, NAS, and home lab, I kept getting interrupted mid-game and during meetings to check if the bathroom was free. Walking over to check is the whole problem, especially during moments when I can't afford to take time to step away. So I built a notifier in Home Assistant.
Now, anyone in the house opens the Home Assistant app, sees the live occupancy status, and taps one button to get pinged the moment the bathroom is free. Whoever is inside also gets alerted when someone is waiting, which was the original motivation.
What You Need
- A door contact sensor paired to Home Assistant (Zigbee, Z-Wave, or WiFi, anything that exposes a
binary_sensor) -
input_boolean.guest_bathroom_queuecreated in Settings β Device & Services β Helpers β Toggle - Home Assistant Companion app installed on family devices for push notifications
- A separate guest VLAN if you want the auto-login flow (optional)
How It Works
A door contact sensor (binary_sensor.contact_sensor_bathroom_door_intrusion) drives everything. "off" = door closed = occupied. "on" = door open = available.
Note: This can vary depending on the sensor model. Please verify and adjust the provided YAML accordingly.
One input_boolean.guest_bathroom_queue tracks whether anyone is waiting. I deliberately kept this as a shared boolean rather than tracking individual users. It doesn't matter who is waiting, making state management much simpler.
Three automations handle the core logic.
1. Someone joins the queue
Triggers 3 seconds after guest_bathroom_queue flips on. The delay filters out accidental taps.
alias: Notify users when guest is waiting for bathroom
triggers:
- trigger: state
entity_id: input_boolean.guest_bathroom_queue
from: "off"
to: "on"
for:
seconds: 3
actions:
- action: notify.family_devices
data:
title: Bathroom
message: someone is waiting for the bathroom
mode: single
2. Bathroom becomes free while someone is waiting
Fires when the door opens and guest_bathroom_queue is still on. Turns off the queue, then notifies.
alias: Notify Guest When Bathroom Free
triggers:
- trigger: state
entity_id: binary_sensor.contact_sensor_bathroom_door_intrusion
from: "off"
to: "on"
conditions:
- condition: state
entity_id: input_boolean.guest_bathroom_queue
state: "on"
actions:
- action: input_boolean.turn_off
target:
entity_id: input_boolean.guest_bathroom_queue
- action: notify.family_devices
data:
title: Bathroom
message: Bathroom is free π»
mode: single
3. Someone cancels their request
Triggers when guest_bathroom_queue flips back off while the door is still closed, meaning they cancelled manually, not because the bathroom freed up.
alias: Cancel Bathroom Request
triggers:
- trigger: state
entity_id: input_boolean.guest_bathroom_queue
from: "on"
to: "off"
conditions:
- condition: state
entity_id: binary_sensor.contact_sensor_bathroom_door_intrusion
state: "off"
actions:
- action: notify.family_devices
data:
title: request cancelled
message: user canceled their bathroom request
mode: single
The Dashboard Card
The card has two states driven by binary_sensor.contact_sensor_bathroom_door_intrusion.
Door open β green icons, shows time since it opened.
Door closed β door icons, shows time since it closed, plus a queue button.
I used conditional cards to handle the two states rather than a custom component. It's more YAML, but everything stays in the dashboard config.
The button toggles input_boolean.guest_bathroom_queue. When the queue is active, the icon turns orange, indicating someone is waiting. Tapping it again cancels the request.
Note: The card_mod blocks are optional. It just handles button sizing and color. If you don't have the card-mod HACS frontend integration installed, remove those blocks, and everything still works.
card:
type: vertical-stack
cards:
- type: conditional
conditions:
- condition: state
entity: binary_sensor.contact_sensor_bathroom_door_intrusion
state: "on"
card:
type: tile
entity: binary_sensor.contact_sensor_bathroom_door_intrusion
name: β
Bathroom is Available
icon: mdi:door-open
color: green
hide_state: false
state_content:
- last_changed
vertical: true
tap_action:
action: none
icon_tap_action:
action: none
features_position: bottom
- type: conditional
conditions:
- condition: state
entity: binary_sensor.contact_sensor_bathroom_door_intrusion
state: "off"
card:
type: vertical-stack
cards:
- type: tile
entity: binary_sensor.contact_sensor_bathroom_door_intrusion
name: πͺ Bathroom is Occupied
icon: mdi:door-closed
color: red
vertical: true
hide_state: false
tap_action:
action: none
icon_tap_action:
action: none
state_content:
- last_changed
- type: conditional
conditions:
- condition: state
entity: input_boolean.guest_bathroom_queue
state: "off"
card:
type: button
entity: input_boolean.guest_bathroom_queue
icon: mdi:account-outline
name: Wait for Bathroom
tap_action:
action: toggle
card_mod:
style: |
ha-card {
margin: 0 auto;
width: 200px;
text-align: center;
}
- type: conditional
conditions:
- condition: state
entity: input_boolean.guest_bathroom_queue
state: "on"
card:
type: vertical-stack
cards:
- type: button
entity: input_boolean.guest_bathroom_queue
icon: mdi:human-male
name: Waiting for Bathroom
tap_action:
action: toggle
card_mod:
style: |
ha-card {
margin: 0 auto;
width: 200px;
text-align: center;
color: orange;
}
- type: markdown
content: >
<div style="text-align:center; font-size:16px; color:
orange;">
π You're in the queue! We'll notify you when it's your turn.
</div>
Notifying All Devices Without Repeating Yourself
You can call individual device services directly in automations:
actions:
- action: notify.mobile_app_mom_big_tablet
data:
message: Bathroom is free π»
- action: notify.mobile_app_kevin_f6
data:
message: Bathroom is free π»
That works. The problem is every automation that needs to notify everyone repeats the same device list. Add a new phone, edit every automation.
Instead, define a notify group once in configuration.yaml:
notify:
- platform: group
name: family_devices
services:
- service: mobile_app_device_1
- service: mobile_app_device_2
- service: mobile_app_device_3
- service: mobile_app_device_4
Now every automation calls notify.family_devices. Add or remove a device in one place.
Triggered when someone joins the queue

Triggered when the bathroom becomes free

Guest Access via Trusted Networks
Guests connect to a dedicated VLAN (192.168.10.0/24). A guest WiFi password alone isn't enough here. Anyone with the password could browse to Home Assistant and see the full dashboard. The VLAN lets me scope exactly what they can access at the network level, and Home Assistant auto-logs them in as a guest user when they're on that subnet, bypassing the password prompt.
In configuration.yaml:
homeassistant:
auth_providers:
- type: trusted_networks
trusted_networks:
- 192.168.10.0/24
allow_bypass_login: true
trusted_users:
192.168.10.0/24: <your_guest_user_id>
- type: homeassistant
Navigate to http://<your-ha-ip>:8123/config/users and click the guest user. The ID is shown explicitly in the first row.
Guests who don't have the Home Assistant app get a QR code to the bathroom dashboard. They land on the card, see live status, and can join the queue, but they can't access anything else.
The guest dashboard itself is restricted to two user IDs via the visible field, so the isolation is enforced at the Home Assistant layer.





Top comments (0)