As part of automation all my lights in the house, I also automated the lights in my toilet room.

To detect if someone’s using the toilet I installed a motion sensor.
I initially was planning to do this with a door sensor, by quickly realised there would be too many situations in which I’d get false triggers or incorrect states. For example: someone not fully closing the door when using the toilet or someone opening the door when someone’s already on the toilet.

I also added an override using the physical light switch that keeps the lamp on even when the motion sensor didn’t detect any motion anymore. This is mainly to make sure the light wouldn’t go out when you’re sitting very still. It also helps with visitors who might not know about the automated lights as the switch’s physical position will also reflect the lamp’s status, giving it a ’natural’ feeling.

And I also added a little twist, which I’ll explain later in this blog post.

All of this was done in Node-RED, but it should be possible to do this with Home Assistant automations as well.

Image of woman on toilet bowl with smartphone
This isn’t me :) kudos to Roman Odintsov on Pexels

Requirements (shopping list)

Below is a list of the items I used:

If you have Live and Neutral available at the switch or at the light fixture, you could use a Shelly 1 or Shelly 1PM instead. Then you also won’t need the bypass.

Install the Shelly


I’m going to assume you only have a single switch and a single (set of) light(s) in your toilet room. Check out this wiring diagram if you have a 2-way/3-way/n-way switch.

First check which wires you have available and whether you have sufficient space to install a Shelly, usually behind the switch plate or in the light fixture.
At the switch, you should at least have a Permanent Live wire feeding the switch and a Switched Live wire going from the switch to the lamp.
At the ceiling fixture, you should at least have the Switched Live wire and a Neutral wire. Depending on how your wiring is done, you may have the Permanent Wire going to the switch in here as well.

If you only have access to Permanent Live and Switched Live where you’d like to install the Shelly, you’ll need a Shelly 1L. Most likely you’ll also need the Bypass as the power draw of the (LED) lights will be too low, causing a slight glow when the light’s supposed to be turned off.
If you also have Neutral available, I’d advise going for the Shelly 1 or 1PM instead, as you then don’t need the Bypass.

Have a look at the wiring diagram on the Shelly Knowledge Base to see how you should hook up the Shelly.

Wiring diagram for a Shelly 1L with a single switch, no Neutral line, and with bypass
Wiring diagram for the Shelly 1L

It’s important that you connect the switch between the Sx and SW1 terminals when using the Shelly 1L. Do not connect the switch to the Live wire.

The bypass is installed parallel to the lamp, between Switched Live and Neutral. Don’t wire it to Permanent Live or in series to the lamp.

Setup and adding to Home Assistant

First hook the Shelly up to your WiFi using the Shelly Web UI Method and add it to the Shelly Cloud and/or Shelly mobile app if you want to.

Then there’s some configurations you can do (from the web ui):

  • Give the Shelly a Device Name and Channel Name. This will later be reflected in Home Assistant once you integrate the Shelly.
  • Set Button 1 Type to Toggle Switch. This will allow you to still control the light via the switch should the automation not work and will allow you to turn the light of before the automation does. You could also set it to Detached and only rely on the automation.
  • Power on default mode can be set to Off or Switch 1 depending on whether you want the light to be off after a power failure or to match the switch state.
  • Under LED Light Control you can enter Disable Wi-Fi status light to save a bit of power as you won’t see the Shelly anymore once its behind the switch plate.

Next, add the Shelly to Home Assistant.

  • If you’re using the built-in Shelly integration in Home Assistant, I’d advise setting up Unicast CoIoT to improve the reliability.
  • You can also add the Shelly to Home Assistant using MQTT.

Installing the Aqara Motion Sensor

Physical installation

A motion sensor usually works best if the movement is perpendicular to the motion sensor instead of towards the sensor. So it’s best to install the sensor at a side wall instead of across the door at a height of 1.2 to 2.1 metres.

The Aqara motion sensor comes with a small foot and some sticky tape, so it very easy to install.

Drawing of a toilet room with a lamp, switch and motion sensor
Sketch of motion sensor installation

Setup and adding to Home Assistant

The Aqara sensors communicate over Zigbee. That’s why you’ll need a Zigebee gateway like the Conbee II which will manage the Zigbee devices.

There are multiple Zigbee integrations available for Home Assistant. The most popular ones are Zigbee Home Automation (ZHA), deCONZ and Zigbee2MQTT.
Each has their own pros and cons. ZHA is the “default” zigbee integration and is well supported by HA. deCONZ require the use of an add-on which uses Phoscon in the back-end and includes firmware-upgrade functionality for the Conbee. Zigbee2MQTT allows you to use a ‘satellite’ system to plug your controller into and supports a wide variety of devices.

I’m going with ZHA, but you can pick whatever Zigbee integration you like.

Installing Zigbee Home Automation

If you haven’t installed any Zigbee devices yet, the short description of the installation is:

  1. Plug the Conbee in your Home Assistant device (Raspberry Pi, Odroid, NUC, server, …) and reboot it.
  2. Under Supervisor > System > Host > 3-dot menu > Hardware you should be able to identify your ConBee II by dresden elektronik ingenieurtechnik gmbh.
  3. Go to Configuration > Integrations and click the plus icon to add the ZHA integration.
  4. In the popup, select the serial device path of the Conbee and pick ‘deconz’ as radio type.
    When asked for the device path, it’s best to pick the path from the /dev/serial/by-id as that always points to the correct device while a path like /dev/ttyUSB0 might change upon reboot.

Adding Aqara motion sensor to ZHA

You may want to temporarily take the motion sensor off its stand/foot and place it closer to the Conbee for this step.

  1. Go to Configuration > Integrations and press the Configure button under Zigbee Home Automation.
  2. Click the Add device button at the bottom-right. This will start the search procedure.
  3. With the Aqara motion sensor near the Conbee (and the battery installed), press and hold the small button for 3 seconds to reset it.
  4. ZHA should discover the motion sensor and a new device should appear.

You can now rename the device and its related entities, if you want to.

The Aqara motion sensor device will have 4 entities:

  • Motion detected
  • Occupancy detection
  • Light sensor
  • Battery percentage

For the next section, we’ll be using the “Motion detected” entity.

Setting up the Node-RED flow

There’s a few basic things we want to achieve using this Node-RED flow:

  • Have lights turn on when motion is detected.
  • Turn lights off when there’s no motion detected.
  • Have the physical switch still work as usual.

But there are also one few edge cases we want to take into account:

  • Don’t have the lights turn off after someone enters the toilet soon after someone left (because of the timer).

The flow I created for this looks like this:

Node-RED flow for toilet room lights
Automatically turn lights on/off with switch override

It’s best to explain this flow from the moment someone leaves the toilet room:

  • Once no more motion is detected a 1 minute timer is started.
    This is more useful with motion sensors that react immediately.
    The Aqara motions sensors by default have a 1 minute ‘active’ time. I.e., when motion is detected, its sensor will keep reading ‘motion detected’ for one minute, even if the motion only lasted 5 seconds.
    • When the timer runs out, the state of the switch is checked.
      • If the switch is in the ‘off’ position, the light is turned off.
      • If the switch is in the ‘on’ position, the light stays on as the flow ends.
  • If motion is detected, the light is turned on.
    • Additionally, the timer mentioned above is reset.
      This will make sure the lights don’t turn off if someone enters the toilet room within 1 minute of the previous person leaving.

Below is the JSON code for this flow:

[{"id":"ed2e1cbc.08f93","type":"server-state-changed","z":"ef850b1b.00efb","name":"Movement detected","server":"2ce15169.23b9de","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"binary_sensor.toilet_motion_sensor","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","haltifstate":"true","halt_if_type":"bool","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"x":130,"y":240,"wires":[["695553c8.4a6f0c","59bb07c3.40c378"],["d59925e4.632f2"]]},{"id":"59bb07c3.40c378","type":"api-call-service","z":"ef850b1b.00efb","name":"Turn light on","server":"2ce15169.23b9de","version":1,"debugenabled":false,"service_domain":"light","service":"turn_on","entityId":"light.toilet_lamp","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":370,"y":240,"wires":[[]]},{"id":"c9acffbd.23f0c8","type":"api-call-service","z":"ef850b1b.00efb","name":"Turn light off","server":"2ce15169.23b9de","version":1,"debugenabled":false,"service_domain":"light","service":"turn_off","entityId":"light.toilet_lamp","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":710,"y":340,"wires":[[]]},{"id":"8058a839.544e","type":"api-current-state","z":"ef850b1b.00efb","name":"Switch on?","server":"2ce15169.23b9de","version":1,"outputs":2,"halt_if":"true","halt_if_type":"bool","halt_if_compare":"is","override_topic":false,"entity_id":"binary_sensor.toilet_switch","state_type":"habool","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":530,"y":340,"wires":[[],["c9acffbd.23f0c8"]]},{"id":"d59925e4.632f2","type":"delay","z":"ef850b1b.00efb","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":360,"y":340,"wires":[["8058a839.544e"]]},{"id":"695553c8.4a6f0c","type":"change","z":"ef850b1b.00efb","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":280,"wires":[["d59925e4.632f2"]]},{"id":"1aa0cdfe.eb810a","type":"comment","z":"ef850b1b.00efb","name":"","info":"More information on this flow can be found at","x":160,"y":320,"wires":[]},{"id":"2ce15169.23b9de","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

The twist

As I alluded to a few times, I also added a little twist to my flow.

Can you figure out from the screenshot below what I did? ;)

Node-RED flow for toilet room timer
Let people know they’ve been pooping too long :D

When the light in the toilet room has been on for 15 minutes the light is toggled shortly as some sort of hint to the person sitting on the toilet.
Time to put away the smartphone/book/… and get back to business ;)

Here’s the JSON code for this flow:

[{"id":"770017d9.000b48","type":"server-state-changed","z":"ef850b1b.00efb","name":"Light on","server":"2ce15169.23b9de","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"light.toilet_lamp","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","haltifstate":"true","halt_if_type":"bool","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"x":100,"y":60,"wires":[["f9c49225.ef2f98"],[]]},{"id":"f9c49225.ef2f98","type":"stoptimer","z":"ef850b1b.00efb","duration":"15","units":"Minute","payloadtype":"num","payloadval":"0","name":"","x":300,"y":60,"wires":[[],["8d25fbe6.f8fdc8"]]},{"id":"8d25fbe6.f8fdc8","type":"api-current-state","z":"ef850b1b.00efb","name":"Light still on?","server":"2ce15169.23b9de","version":1,"outputs":2,"halt_if":"true","halt_if_type":"bool","halt_if_compare":"is","override_topic":false,"entity_id":"light.toilet_lamp","state_type":"habool","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":510,"y":60,"wires":[["de1a4ca9.6fe9f"],[]]},{"id":"5fb82301.096bd4","type":"api-call-service","z":"ef850b1b.00efb","name":"Light toggle","server":"2ce15169.23b9de","version":1,"debugenabled":false,"service_domain":"light","service":"toggle","entityId":"light.toilet_lamp","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":910,"y":60,"wires":[[]]},{"id":"de1a4ca9.6fe9f","type":"trigger","z":"ef850b1b.00efb","name":"0.5s toggle","op1":"off","op2":"on","op1type":"str","op2type":"str","duration":"500","extend":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":710,"y":60,"wires":[["5fb82301.096bd4"],["5fb82301.096bd4","d4adc37e.d3099"]]},{"id":"fe70c04d.b3e158","type":"link in","z":"ef850b1b.00efb","name":"Reset","links":["d4adc37e.d3099"],"x":155,"y":100,"wires":[["f9c49225.ef2f98"]]},{"id":"d4adc37e.d3099","type":"link out","z":"ef850b1b.00efb","name":"Reset","links":["fe70c04d.b3e158"],"x":835,"y":100,"wires":[]},{"id":"1aa0cdfe.eb810a","type":"comment","z":"ef850b1b.00efb","name":"","info":"More information on this flow can be found at","x":460,"y":100,"wires":[]},{"id":"2ce15169.23b9de","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Note: the In/Out nodes might not be required, as the flow should restart automatically after the light turns on again.

There you go: we have automated our (toilet room) lights using a motion sensor!

Liked my automation? Got ideas for improvements? Reach out to me on Twitter!