A leak sensor under the washing machine is cheap. On its own it only beeps or sends a notification, and if nobody is home the water keeps running. Pair it with a motorised valve on the main water line and Home Assistant can close the supply within seconds of the first drop reaching the sensor.
The automation itself is a few lines. Most of the work is making sure it still fires after a restart, when a sensor has just dropped off the network, or when the valve is unreachable, because those are exactly the moments you will not be watching.
What you need
- Leak sensors. In Home Assistant they appear as binary sensors with the
moisturedevice class, which shows Wet (on) and Dry (off). Zigbee, Z-Wave, Wi-Fi and ESPHome sensors all work the same way once they are in Home Assistant. - A motorised shut-off valve on the main supply, fitted after the water meter and the main manual valve. Leave the plumbing to a plumber if you are not sure. Depending on the integration, the valve appears as a valve entity or as a switch. Valve entities were added in Home Assistant 2024.1 and have the states
open,opening,closedandclosing, plus actions such asvalve.close_valveandvalve.open_valve. - The Home Assistant Companion app on the phones that should get the alarm.
Before you buy a valve, read what it does when it loses power or loses its connection. Some stay where they are, some have a battery, some can be closed by hand. That determines what happens in the scenarios further down.
Where to put the sensors
Put them where water collects first: on the floor under the washing machine and the dishwasher, under the kitchen and bathroom sinks, next to the boiler or water heater, by the water filter and under the main valve itself. The sensor sits flat on the floor with its contacts down. If the floor slopes, the lowest point is the right spot, not the middle of the cabinet.
One sensor per appliance is better than one per room. A sensor two metres from the leak may stay dry until the floor is already covered.
Group the sensors
Create one helper that is on whenever any sensor is wet: Settings > Devices & services > Helpers > Create helper > Group > Binary sensor group. Add all leak sensors and leave All entities turned off. According to the Group documentation, such a group is on if at least one member is on, off otherwise, and unavailable only if all members are unavailable.
The group keeps the automation short, and a new sensor only needs adding to the group. In the examples below it is called binary_sensor.water_leak_any.
The shut-off automation
alias: "Water leak: close main valve"
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.water_leak_any
to: "on"
- trigger: homeassistant
event: start
conditions:
- condition: state
entity_id: binary_sensor.water_leak_any
state: "on"
actions:
- action: valve.close_valve
target:
entity_id: valve.main_water
- continue_on_error: true
action: notify.mobile_app_your_phone
data:
title: "Water leak"
message: >
Wet: {{ expand('binary_sensor.water_leak_any')
| selectattr('state', 'eq', 'on')
| map(attribute='name') | join(', ') }}. Main valve closing.
data:
push:
interruption-level: critical
ttl: 0
priority: high
channel: alarm_stream
- wait_for_trigger:
- trigger: state
entity_id: valve.main_water
to: "closed"
timeout: "00:01:00"
continue_on_timeout: true
- if:
- condition: template
value_template: "{{ not wait.completed }}"
then:
- action: notify.mobile_app_your_phone
data:
title: "Water leak: valve did not close"
message: "Close the main water valve by hand."
data:
push:
interruption-level: critical
ttl: 0
priority: high
channel: alarm_stream
If your valve is a switch, replace the first action with switch.turn_off (or turn_on, depending on how the integration maps it) and wait for that state instead. Replace notify.mobile_app_your_phone with the notify action of each phone.
The details matter more than they look:
- The valve closes first. If the notification service fails, the valve is already closed.
continue_on_error: truelets the rest of the automation run even if that notification step fails. - A plain State trigger with only
to: "on". The automation trigger docs point out that most entity triggers do not react when an entity goes fromunavailableorunknownto a state, while the State trigger does. A Zigbee sensor that drops out, gets wet and reconnects reports exactly that change. - The start trigger. If a sensor gets wet while Home Assistant is restarting, the change to
onhappens before the automation is listening. With a start trigger and the condition, the automation checks the group once Home Assistant is up and closes the valve if anything is still wet. - Critical notifications. On iOS,
interruption-level: criticalmakes the notification play a sound even when Do Not Disturb is on or the phone is muted; the Companion docs name water leak sensors as a typical use. On Android,ttl: 0withpriority: highdelivers the notification at once even if the phone has been idle, andchannel: alarm_streamplays it through the alarm stream, so it rings even in silent mode. Each phone ignores the keys meant for the other system. - Checking that the valve really closed. The scripts documentation says that an action whose target is unavailable does not fail. Home Assistant skips the target, logs a warning and moves on. Without the wait at the end, an unreachable valve would leave you with a notification saying the valve is closing while the water keeps running. The timeout of one minute is an example; set it a little longer than your valve needs to close.
Do not let an automation reopen the valve when the sensor dries. A sensor can dry out while water is still pouring somewhere else. Open the valve by hand or from the dashboard once you have found the cause.
Watch the sensors themselves
A dead leak sensor looks exactly like a dry one, so two more automations are worth adding.
The first warns you when a sensor drops off the network:
alias: "Water leak sensor offline"
triggers:
- trigger: state
entity_id:
- binary_sensor.leak_washing_machine
- binary_sensor.leak_kitchen_sink
- binary_sensor.leak_boiler
to: "unavailable"
for: "01:00:00"
actions:
- action: notify.mobile_app_your_phone
data:
message: "{{ trigger.to_state.name }} has been offline for an hour."
The second watches the batteries. Most battery sensors also create a battery entity in percent. Use a Numeric state trigger on those entities with Below set to a level that leaves you time to buy new cells, for example 20%. The entity names differ between integrations, so pick them from the device pages.
The group is no substitute for these alerts: it only turns unavailable when every member is offline, so one missing sensor does not show up in its state.
Exercise the valve
A ball valve that stays open for years can stiffen. A general operating manual from the valve maker CO-AX says valves should be operated regularly, at least every six months, and some leak protection kits do this on their own: the FloodStop water heater kit from OnSite PRO, built around a LeakSmart valve, lists automatic monthly cycling of the valve among its features.
If yours does not, add a monthly automation. Pick a night hour when nobody uses water, close the valve, wait until it reports closed, open it again and notify yourself if either step does not finish:
alias: "Main valve monthly exercise"
triggers:
- trigger: time
at: "03:30:00"
conditions:
- condition: template
value_template: "{{ now().day == 1 }}"
- condition: state
entity_id: binary_sensor.water_leak_any
state: "off"
actions:
- action: valve.close_valve
target:
entity_id: valve.main_water
- wait_for_trigger:
- trigger: state
entity_id: valve.main_water
to: "closed"
timeout: "00:01:00"
- action: valve.open_valve
target:
entity_id: valve.main_water
- wait_for_trigger:
- trigger: state
entity_id: valve.main_water
to: "open"
timeout: "00:01:00"
continue_on_timeout: false
- action: notify.mobile_app_your_phone
data:
message: "Monthly valve test finished, valve is open."
The open action runs even if the first wait times out, so the valve is not left closed by accident. If the second wait times out, the automation stops before the confirmation, and a missing monthly message is your signal to check the valve. Check the trace to see which step failed.
Test the whole chain
- Wet a sensor: touch its contacts with a damp cloth or set it on a wet paper towel. Do not test it by pouring water on the floor next to the washing machine.
- Check that the phone rings even in silent mode and that the valve actually closes. Open a tap and make sure the flow stops.
- Dry the sensor and open the valve again by hand.
- Restart Home Assistant while one sensor is still wet and check that the valve closes after start-up.
- Repeat the test every few months, and after every change to the network or the valve.
When the valve closes, do not expect the tap to go dry at once. The test procedure for the FloLogic shut-off system warns that siphoning from pipes higher up and backflow from a thermal expansion tank can keep water flowing for some time after a shutoff. A short trickle is normal; a steady flow is not.
What this setup cannot do
Home Assistant is the weak link in this chain. If it is down, if Wi-Fi or the Zigbee network has failed, or if there is a power cut and the valve has no battery, the automation does not run. Use leak sensors with their own siren where you can, so somebody nearby hears a leak even when the automation cannot react, and know where the main manual valve is. Some commercial leak kits link sensors directly to their valve with their own control panel. If you want a backup that does not depend on Home Assistant, that is the kind of system to look at.