If your septic tank or wastewater treatment system has ever overflowed without warning, you know the problem: the standard buzzer alarm only works if someone is home and within earshot. This guide shows you how to build a WiFi-connected high-level sensor that sends an instant Telegram message to your phone — wherever you are — using an ESP32, a float switch, and about €20 in parts.
No soldering required. No monthly subscription. No SIM card.
A compact waterproof sensor unit that:
| Component | Spec / Notes | Approx. Cost |
|---|---|---|
| ESP32 development board | Any 38-pin or 30-pin variant — ESP32-WROOM-32 is ideal | €4–7 |
| Float switch | IP68 rated, normally-open (NO), cable length 1–2 m. See note below on cable length. | €5–15 |
| Power supply | HLK-PM03 (3.3 V / 600 mA) — or 5 V USB adapter outdoors | €3–5 |
| Enclosure | IP65 waterproof junction box, min. 100×68×50 mm | €4–6 |
| Pull-up resistor | 10 kΩ, 0.25 W | €0.10 |
| Cable gland | PG7 or PG9, to suit float switch cable diameter | €0.50 |
| Total | ~€20–30 |
A float switch is a simple device: a small float contains a magnetic reed switch. When the water rises, the float tilts and the switch changes state. We use a normally-open (NO) float switch — the circuit is open when the float hangs down (low water), and closes when the float rises with the water level.
The ESP32 monitors the switch pin. When it detects the switch closing, it connects to your WiFi and sends a Telegram alert. When the float drops again, it sends a second message confirming the level has normalised. The ESP32 does nothing in between — it just polls the pin every 200 ms, consuming minimal power.
The HLK-PM03 power module converts 230 V mains to 3.3 V directly — one compact component, no intermediate voltage stage needed. If you prefer to avoid mains wiring inside the enclosure, power the ESP32 via a 5 V USB phone charger mounted indoors.
230 V AC (Live) ──── HLK-PM03 (L)
230 V AC (Neutral) ──── HLK-PM03 (N)
│
HLK-PM03 (+3.3V) ──── ESP32 (3V3 pin)
HLK-PM03 (GND) ──── ESP32 (GND pin)
Float switch wire 1 ──── ESP32 GPIO 4
Float switch wire 2 ──── ESP32 GND
GPIO 4 ──────── 10kΩ resistor ──── 3.3V ← pull-up
The 10 kΩ pull-up resistor holds GPIO 4 HIGH when the float switch is open (normal / low water). When the float rises and the switch closes, GPIO 4 is pulled to GND — this is the trigger condition the code looks for.
Mains safety: If you are connecting to 230 V mains, this work must comply with Irish electrical regulations (ETCI rules). If you are not a qualified electrician, power the ESP32 from an external USB adapter instead and run only the low-voltage float switch cable into the enclosure. Never work on live mains circuits.
/newbot_bot7123456789:AAGxxxxxxxxxxxxxxxxxxxxxxconfig.py
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates"id": 123456789
Tip: To notify multiple family members, create a Telegram group, add your bot to it, and use the group's chat ID instead of a personal chat ID. Everyone in the group receives every alert simultaneously.
If your ESP32 does not already have MicroPython installed:
pip install esptoolesptool.py --chip esp32 erase_flashesptool.py --chip esp32 write_flash -z 0x1000 esp32-generic-firmware.bin
Upload two files to the ESP32: config.py with your settings, and main.py which runs automatically on boot.
# ── WiFi ────────────────────────────────────────────────────
WIFI_SSID = "YourNetworkName"
WIFI_PASSWORD = "YourWiFiPassword"
# ── Telegram ─────────────────────────────────────────────────
BOT_TOKEN = "7123456789:AAGxxxxxxxxxxxxxxxxxxxxxx"
CHAT_ID = "123456789"
# ── Hardware ──────────────────────────────────────────────────
FLOAT_PIN = 4 # GPIO pin connected to float switch
DEBOUNCE_MS = 2000 # ms to wait before confirming a state change
# ── Alert messages ────────────────────────────────────────────
MSG_HIGH = "⚠️ SEPTIC ALERT: High water level detected. Please check your system."
MSG_NORMAL = "✅ Septic level back to normal."
import machine
import network
import urequests
import utime
import config
def connect_wifi():
"""Connect to WiFi, return True if successful."""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if wlan.isconnected():
return True
print("Connecting to WiFi...")
wlan.connect(config.WIFI_SSID, config.WIFI_PASSWORD)
timeout = 15
while not wlan.isconnected() and timeout > 0:
utime.sleep(1)
timeout -= 1
if wlan.isconnected():
print("Connected:", wlan.ifconfig()[0])
return True
print("WiFi connection failed")
return False
def send_telegram(message):
"""Send a message via Telegram Bot API."""
if not connect_wifi():
return
url = "https://api.telegram.org/bot{}/sendMessage".format(config.BOT_TOKEN)
payload = {
"chat_id": config.CHAT_ID,
"text": message
}
try:
r = urequests.post(url, json=payload)
print("Telegram status:", r.status_code)
r.close()
except Exception as e:
print("Send failed:", e)
def main():
# GPIO 4 with internal pull-up
# Reads HIGH (1) = switch open = normal level
# Reads LOW (0) = switch closed = HIGH WATER
pin = machine.Pin(config.FLOAT_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
last_state = pin.value()
print("Monitoring started. Pin state:", last_state)
while True:
state = pin.value()
if state != last_state:
# Debounce: wait, then re-read to confirm
utime.sleep_ms(config.DEBOUNCE_MS)
state = pin.value()
if state != last_state:
last_state = state
if state == 0:
print("HIGH WATER")
send_telegram(config.MSG_HIGH)
else:
print("Level normal")
send_telegram(config.MSG_NORMAL)
utime.sleep_ms(200)
main()
Always test on the bench before mounting inside the tank:
Local fallback: If you want an alarm even when the internet is down, wire a passive buzzer between GPIO 5 and GND and add two lines to main.py:buzzer = machine.Pin(5, machine.Pin.OUT)and toggle it whenstate == 0. A passive 5V buzzer costs under €1.
Only the float switch and its cable go inside the tank. The ESP32 enclosure stays outside — mounted on the tank lid or a nearby wall.
machine.deepsleep() between checks to extend battery life significantlyhomeassistant/sensor/septic/state| Symptom | Likely cause | Fix |
|---|---|---|
| No WiFi connection | Wrong SSID/password, or 5 GHz network | ESP32 supports 2.4 GHz only — check your router band settings |
| Telegram message not arriving | Wrong token or chat ID | Re-check config.py — both values are case-sensitive |
| False triggers / constant alerts | Float vibrating, or DEBOUNCE_MS too short | Increase DEBOUNCE_MS to 5000; secure the float cable so it cannot swing |
| Alert fires but tank looks fine | Float switch mounted too high | Lower the mounting position by 50–100 mm |
| ESP32 rebooting repeatedly | Power supply too weak for WiFi transmit | ESP32 peaks at ~500 mA during WiFi TX — replace cheap USB cable or charger |
| Works in test, fails after installation | Float cable too short, or pinched in lid | Check cable has enough slack; ensure lid closes without pinching |
| Item | Cost |
|---|---|
| ESP32 board | €5 |
| IP68 float switch (1–2 m cable) | €5–8 |
| HLK-PM03 power module | €3 |
| IP65 enclosure | €5 |
| Resistor, cable gland, terminals | €2 |
| Total | ~€20–26 |
| Monthly running cost | €0 |
Questions about the DIY build? Send a message via the contact form — happy to help troubleshoot.