Build a DIY Flo: whole-house water monitor and automatic shutoff with an ESP32
Commercial smart shutoffs like the Moen Flo watch your main water line, spot leaks from the way water flows, and close a valve before a burst pipe floods the house. This build does the same job with an ESP32, an inline flow sensor, a pressure sensor and a motorized ball valve. Everything runs locally in Home Assistant, with no subscription.
Read this first. This project cuts into your main water line. If you aren't comfortable sweating copper or crimping PEX, have a plumber fit the valve and sensors; the electronics are low voltage and safe to build on the bench. If your house's electrical ground is bonded to metal water pipe, a plastic flow sensor breaks that bond. Fit a bonding jumper across the new section, and check your local code.
- Cost
- $80–150
- Time
- An afternoon, plus plumbing
- Difficulty
- Advanced
- Skills
- Plumbing, 12 V wiring
How it catches a leak
A leak looks different from normal use, so the monitor watches for three patterns:
- A burst: very high flow that keeps going. The ESP32 closes the valve on its own after two minutes, even if Home Assistant or Wi-Fi is down.
- A running fixture: water that never stops, like a toilet flapper stuck open or a hose left on. Home Assistant warns you after flow has run nonstop for longer than any normal use.
- A slow drip: too small for the flow sensor to see. At night, Home Assistant closes the valve and watches the pressure for five minutes. If it falls, water is escaping somewhere. This is the same trick the Flo calls its MicroLeak test.
A leak probe under the water heater or washer adds a fourth check: if it gets wet, the valve closes at once.
Parts
- An ESP32 DevKit.
- A hall-effect water flow sensor sized for your main line, usually 3/4" or 1". It must be rated for drinking water and your line pressure.
- A 12 V motorized ball valve, full port, the same size as your main. Get a 3-wire or 5-wire model; they open and close from a single 12 V supply.
- A 0–100 psi pressure transducer with a 0.5–4.5 V output, 1/4" NPT thread.
- A 2-channel relay module.
- A 12 V, 2 A power supply for the valve, and a small 12 V to 5 V buck converter for the ESP32.
- Four resistors: two 10 kΩ and two 20 kΩ, plus a 1 MΩ for the leak probe.
- A leak probe and an enclosure that will stay dry next to the plumbing.
- ESP32 DevKitView on AmazonPhoto: Edwiyanto, CC BY-SA 4.0

- Hall-effect water flow sensor (3/4" or 1")Illustration
- 12 V motorized ball valve (3- or 5-wire)Illustration
- 0–100 psi pressure transducer (0.5–4.5 V)Illustration
- 2-channel relay modulePhoto: Suyash Dwivedi, CC BY-SA 4.0

- 12 V 2 A power supplyIllustration
- 12 V to 5 V mini buck converterIllustration
- Resistor assortmentView on AmazonPhoto: Afrank99, CC BY-SA 2.5

- Water leak probe cablesIllustration
- Plastic project enclosureIllustration
Where it goes on the pipe
Install everything just after your existing main shutoff, in this order: main shutoff → motorized valve → flow sensor → pressure sensor → the house. Keep the old manual shutoff so you can still turn the water off by hand. The pressure sensor must sit downstream of the motorized valve, or the nightly drip test can't work.
Point the flow sensor's arrow the way the water flows, and give it a few inches of straight pipe on each side so the reading stays steady.
Don't want to cut the pipe? You can measure flow without plumbing by reading your water meter's internal magnet with a QMC5883L magnetometer taped to the meter. It counts water just as well, but you lose the shutoff and the pressure test unless you fit the valve anyway.
Wiring
| Part | Wire | Goes to |
|---|---|---|
| 12 V supply | +12 V / − | Buck converter input, relay COM terminals, valve common |
| Buck converter (5 V out) | OUT+ / OUT− | ESP32 5V (VIN) / GND |
| Flow sensor | Red / black / yellow | 5V / GND / 10 kΩ to GPIO27, 20 kΩ from GPIO27 to GND |
| Pressure transducer | Red / black / signal | 5V / GND / 10 kΩ to GPIO34, 20 kΩ from GPIO34 to GND |
| Relay module | VCC / GND / IN1 / IN2 | 5V / GND / GPIO26 (open) / GPIO25 (close) |
| Relay 1 NO | Valve OPEN wire | |
| Relay 2 NO | Valve CLOSE wire | |
| Leak probe | Two contacts | GPIO32 and GND, with 1 MΩ from GPIO32 to 3.3V |
The flow and pressure sensors run on 5 V, so their signals go through a 10 kΩ / 20 kΩ divider that brings 5 V down to about 3.3 V for the ESP32.
Valve wire colors vary between makers, so go by your valve's label or listing. A 3-wire valve has one common wire and one wire each for open and close. 12 V on the open wire turns it open, and 12 V on the close wire turns it closed; limit switches inside stop the motor at each end. A 5-wire valve adds two feedback wires that report when it is fully open or fully closed.
The ESPHome config
The valve shows up in Home Assistant as a valve you can open and close. The leak probe and the burst check close it directly on the ESP32, so they work even when Home Assistant doesn't.
switch:
- platform: gpio
id: relay_open
pin: GPIO26
restore_mode: ALWAYS_OFF
interlock: [relay_close]
internal: true
- platform: gpio
id: relay_close
pin: GPIO25
restore_mode: ALWAYS_OFF
interlock: [relay_open]
internal: true
valve:
- platform: template
name: "Main water"
id: main_valve
optimistic: true
open_action:
- switch.turn_on: relay_open
- delay: 20s
- switch.turn_off: relay_open
close_action:
- switch.turn_on: relay_close
- delay: 20s
- switch.turn_off: relay_close
sensor:
- platform: pulse_meter
pin: GPIO27
name: "Water flow"
id: water_flow
unit_of_measurement: "L/min"
device_class: volume_flow_rate
state_class: measurement
accuracy_decimals: 2
internal_filter: 1ms
timeout: 1min
filters:
- multiply: 0.002222 # 1 / 450 pulses per litre
total:
name: "Water used"
unit_of_measurement: "L"
device_class: water
state_class: total_increasing
accuracy_decimals: 1
filters:
- multiply: 0.002222
- platform: adc
pin: GPIO34
name: "Water pressure"
id: water_pressure
attenuation: 12db
update_interval: 5s
unit_of_measurement: "psi"
device_class: pressure
state_class: measurement
accuracy_decimals: 1
filters:
- multiply: 1.5
- lambda: 'return (x - 0.5) * 25.0;'
- sliding_window_moving_average:
window_size: 6
send_every: 1
binary_sensor:
- platform: gpio
pin: GPIO32
name: "Water heater leak"
device_class: moisture
filters:
- invert:
- delayed_on: 2s
on_press:
- valve.close: main_valve
- platform: template
name: "Burst pipe suspected"
device_class: problem
lambda: 'return id(water_flow).state > 30.0;'
filters:
- delayed_on: 2min
on_press:
- valve.close: main_valve
Add your usual esphome, esp32, wifi, api and ota blocks at the top. The 20-second delay covers the slowest valves; the limit switches stop the motor sooner, so a longer delay does no harm.
Calibrate it
Flow
Every flow sensor has its own pulses-per-litre figure, and the number in the listing is only a starting point. To check yours, note the Water used total, fill a bucket of known size from a tap, then compare. If 10 litres reads as 9.2, multiply both multiply values by 10 ÷ 9.2.
Pressure
Compare the reading with a cheap gauge on an outdoor tap. If it's off by a fixed amount, add an offset filter after the lambda. Most homes sit between 40 and 80 psi.
The burst threshold
30 L/min (about 8 gallons a minute) is roughly two showers and a washing machine at once. Run everything you might ever run together, watch the peak flow, and set the threshold comfortably above it.
Water use in Home Assistant
Water used has the right device class and state class for Home Assistant's water dashboard. Go to Settings → Dashboards → Energy, find Water consumption, and add it. You'll get daily and hourly water use next to your electricity.
Home Assistant automations
- Running water warning: notify when Water flow stays above 0 for 45 minutes. Raise it if you have long irrigation runs, or add a condition that the sprinklers are off.
- Away mode: when everyone leaves, close the valve, or warn on any flow at all while the house is empty.
- Nightly drip test: at 3 a.m., if flow is zero, close the valve and save the pressure. Wait five minutes. If the pressure has dropped by more than 2 psi, notify that a slow leak is likely. Then open the valve again. Skip the test if anyone uses water while it runs.
- Leak probes elsewhere: any leak sensor in the house can close the valve too, through a Home Assistant automation.
- Exercise the valve: close and reopen it once a month so it doesn't seize. Do it at night, when nobody is using water.
A pressure drop during the test isn't always a leak. A water heater that's heating pushes pressure up, and one that's cooling can pull it down a little. If you get false alarms, run the test at a time the heater is idle, or raise the 2 psi threshold.
What it costs compared with a Flo
A commercial smart shutoff typically costs several hundred dollars before installation. The parts here come to roughly $80–150, depending mostly on the valve size and brand. The trade-off is the work: you're responsible for the plumbing, the calibration, and making sure it fails safe.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| Flow always reads zero | The arrow points the wrong way, or the sensor's output needs a pull-up. Try a 10 kΩ from the signal to 3.3V in place of the divider. |
| Water used is off by a steady percentage | The pulses-per-litre figure doesn't match your sensor. Calibrate with a bucket and adjust both multiply values. |
| Valve hums but doesn't move | The 12 V supply is too weak, or open and close are swapped. Check the valve label and use a 2 A supply. |
| Valve shows open after a reboot when it's closed | The template valve can't see the real position. A 5-wire valve's feedback wires fix this. |
| Nightly test fails every night | Water heater cooling, or a real slow leak. Check toilets with dye tablets, then try a different test time. |