ESP32 Power Failure Detector for Home Assistant & ESPHome

Quick Summary (TL;DR):
A reliable ESP32 power failure detector for Home Assistant needs two independent paths: the ESP32 stays alive from a UPS or battery-backed 5 V supply, while a separate isolated signal tells it whether the monitored mains circuit is present. The easiest safe DIY method is an approved USB wall adapter plugged into the circuit you want to monitor. Its low-voltage output drives an optocoupler, dry-contact relay or correctly designed 5 V-to-3.3 V interface; the ESP32 itself remains on backup power. Do not connect 230 V directly to an ESP32 GPIO or breadboard. In ESPHome, the sense signal becomes a GPIO binary sensor with a short delayed_on_off filter. If the sense signal disappears while the ESP32 remains online, Home Assistant can distinguish a real outage from Wi-Fi loss, a reboot or an ESPHome crash. For immediate notifications during a whole-house outage, the router/access point and Home Assistant host must also stay powered. One ESP32 can also monitor separate circuits such as freezer, boiler, garage or pump supplies, record outage duration and confirm that the detector itself survived the outage.

Materials You’ll Need

ItemPurpose
ESP32 development boardRuns ESPHome and reports the mains state
UPS-backed 5 V supplyKeeps the ESP32 alive during the outage
Approved isolated USB adapterCreates a safe low-voltage mains-present signal
Optocoupler / dry-contact relayInterfaces that signal to an ESP32-safe GPIO
UPS-backed router/APKeeps the local network alive
UPS-backed Home Assistant hostReceives, records and acts on the event
Optional extra sensing adaptersMonitor individual circuits

The Architecture That Actually Works

Monitored mains circuit
      ↓
approved 5V adapter
      ↓
optocoupler / dry contact
      ↓
ESP32 GPIO

UPS / battery backup
      ↓
ESP32 power

UPS-backed router + Home Assistant
      ↓
notification + history

The detector must survive the outage. If the ESP32 is powered from the same outlet it monitors, Home Assistant only sees the node disappear and cannot prove why.

Why ‘ESP32 Offline’ Is Not a Good Power-Cut Detector

  • mains power failure
  • ESP32 reboot
  • Wi-Fi access-point failure
  • router failure
  • Home Assistant API disconnect
  • ESPHome crash
  • bad USB cable or PSU
  • OTA update

A dedicated mains-sense input tells you specifically that the monitored supply disappeared while the monitoring node remained alive.

The Three Failure Domains

DomainWhat can failWhat you need
Mains senseMonitored circuit loses powerIndependent isolated sense signal
ESP32 powerDetector itself loses powerUPS/battery-backed supply
Network / Home AssistantEvent cannot reach HAUPS-backed router/AP + HA host

Safest DIY Method: Isolated USB Adapter

A small approved USB charger already performs the dangerous mains-to-low-voltage isolation. Plug it into the circuit you want to supervise and use only its low-voltage output as the mains-present signal. This keeps mains wiring out of the ESP32 enclosure.

230V monitored outlet
→ approved USB adapter
→ 5V DC
→ optocoupler / dry contact
→ ESP32-safe GPIO

Option A: USB Adapter + Optocoupler

MONITORED SIDE
5V adapter + → resistor → optocoupler LED → adapter GND

ESP32 SIDE
3.3V → pull-up → GPIO → optocoupler transistor → ESP32 GND

When mains is present, the optocoupler changes the GPIO state. When mains disappears, the transistor releases. This creates a very clean logical separation between the sensing supply and ESP32 side.

Option B: USB Adapter + Small Relay

A small 5 V relay coil powered by the monitored adapter is even easier to understand. Its dry contact connects the ESP32 GPIO to ground. The trade-offs are mechanical noise, slower release and contact wear, though outage sensing changes state so rarely that wear is usually irrelevant.

Option C: USB Adapter + Divider

Because the USB adapter has already isolated the low-voltage output from mains, you can reduce its 5 V output to a safe ESP32 logic level with a resistor divider if the grounds are intentionally shared. An optocoupler or dry contact is usually cleaner when you want the sensing adapter and ESP32 power supplies to remain independent.

5V sense output
   │
  10kΩ
   │
   ├──── ESP32 GPIO (~3.3V)
   │
  20kΩ
   │
  GND

Do Not Connect 230 V Directly to ESP32

Do not build a mains resistor divider into an ESP32 GPIO and do not use a random non-isolated AC detector board unless you understand its isolation, creepage, clearance, enclosure and protection requirements. For a domestic DIY Home Assistant project, an approved plug-in low-voltage adapter is much easier to reason about safely.

Power the ESP32 Independently

  • UPS-backed USB output
  • small DC UPS module
  • battery-backed 5 V board
  • another genuinely independent supply when monitoring only one local circuit

For whole-house outage detection, another normal mains circuit is not enough. Use actual battery or UPS backup.

Basic ESPHome GPIO Input

binary_sensor:
  - platform: gpio
    id: mains_present
    name: "Mains Power Present"
    device_class: power
    pin:
      number: GPIO25
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on_off: 1s

The exact inversion depends on the optocoupler or relay wiring. Verify the physical state: the entity must read ON when mains is actually present.

Why delayed_on_off Helps

ESPHome binary sensors support delayed_on, delayed_off and delayed_on_off filters. A short local delay rejects relay bounce, adapter discharge noise and very brief power flicker. One second is a sensible starting point for general outage monitoring.

Power dip < 1s
→ ignored

Power absent > 1s
→ Mains Power Present = OFF

Create a Power Failure Entity

binary_sensor:
  - platform: template
    id: power_failure
    name: "Power Failure"
    device_class: problem
    lambda: |-
      return !id(mains_present).state;

Keep both Mains Power Present and Power Failure. The raw state is useful for diagnostics; the inverted problem entity is cleaner for alerts.

Home Assistant Power-Lost Notification

alias: Mains power failure
triggers:
  - trigger: state
    entity_id: binary_sensor.mains_power_present
    to: "off"
    for: "00:00:02"
actions:
  - action: notify.mobile_app_phone
    data:
      title: "Power Failure"
      message: "Mains power has been lost."

Home Assistant state triggers can require the new state to remain stable for a chosen period before the automation fires.

Power-Restored Notification

alias: Mains power restored
triggers:
  - trigger: state
    entity_id: binary_sensor.mains_power_present
    to: "on"
    for: "00:00:10"
actions:
  - action: notify.mobile_app_phone
    data:
      title: "Power Restored"
      message: "Mains power is stable again."

A longer restore confirmation helps avoid repeated alerts if utility power comes back briefly and drops again.

Use Two-Level or Three-Level Alerts

Power lost > 2 seconds
→ immediate information alert

Power lost > 5 minutes
→ sustained-outage warning

Power lost > 30 minutes
→ freezer / UPS / remote-property escalation

Track Detector Uptime

sensor:
  - platform: uptime
    name: "Power Detector Uptime"
    type: seconds

If mains failed but ESP32 uptime continued uninterrupted, your backup power worked. If uptime reset, the detector itself also lost power.

Expose Detector Online Status

binary_sensor:
  - platform: status
    name: "Power Detector Online"
Mains PresentDetector OnlineInterpretation
ONONNormal
OFFONConfirmed monitored power failure
UnknownOFFDetector/network failure; mains state not proven

The Router and Home Assistant Need Backup Too

A surviving ESP32 cannot report through a dead access point. For whole-house alerts, back up the router/firewall, Wi-Fi AP, Home Assistant host and any required switch. If you need remote notifications, the modem/ONT and ISP path also matter.

Whole-House Outage Setup

Normal non-UPS outlet → sensing adapter
UPS outlet → ESP32
UPS outlet → router/AP
UPS outlet → Home Assistant

Monitor Individual Circuits

One ESP32 can supervise multiple circuits by using one isolated sensing adapter/interface per circuit. This is excellent for detecting a tripped freezer, boiler, pump, garage or outbuilding circuit even when the rest of the property still has power.

Main mains adapter → GPIO25
Freezer circuit    → GPIO26
Boiler circuit     → GPIO27
Garage circuit     → GPIO32

Multi-Circuit ESPHome Example

binary_sensor:
  - platform: gpio
    name: "Main Mains Present"
    id: main_mains
    pin:
      number: GPIO25
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on_off: 1s

  - platform: gpio
    name: "Freezer Circuit Present"
    id: freezer_mains
    pin:
      number: GPIO26
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on_off: 1s

  - platform: gpio
    name: "Boiler Circuit Present"
    id: boiler_mains
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on_off: 1s

Why Circuit Monitoring Is Better Than Waiting for Consequences

ScenarioInterpretation
Main ON, freezer OFFLikely local breaker/outlet failure
Main OFF, freezer OFFLikely utility/whole-house outage
Main ON, boiler OFFHeating problem may simply be missing electrical supply
Pump circuit ON, no water movementElectrical supply exists; pump/mechanical fault remains

Freezer Protection

A dedicated freezer-circuit detector can notify you within seconds. Pair it with a DS18B20 temperature sensor for a second independent layer: power loss is the cause signal; rising temperature is the consequence signal.

Freezer power OFF
→ immediate electrical alert

Freezer temperature rising
→ later thermal alert

Boiler and Heating Use Case

Monitoring the boiler supply helps Home Assistant distinguish “boiler has no electricity” from thermostat, burner or control-system faults.

Pump / Sump Use Case

Power availability is valuable diagnostic information, but it only proves that electrical supply exists. Combine it with current, flow or level feedback if actual pump operation matters.

UPS and Server Rack Monitoring

Utility input present?
→ grid state

UPS output present?
→ protected load still powered

UPS battery telemetry
→ remaining runtime

Can This Detect Brownout Voltage?

A simple USB adapter only tells you whether its input remains high enough to keep producing output. It does not measure true AC voltage magnitude. If you need RMS voltage, current, frequency, power factor or kWh, use an isolated energy meter or Modbus meter.

Binary Detector vs Energy Meter

NeedBest tool
Power present / absentESP32 isolated binary sense
Specific breaker tripCircuit-specific binary sense
Actual AC RMS voltageIsolated voltage/energy meter
Frequency / power factor / kWhModbus/PZEM/energy meter
UPS battery runtimeUPS telemetry / DC voltage monitor

Slow Adapter Discharge

Some USB adapters hold their 5 V output for hundreds of milliseconds or several seconds after mains is removed because of internal capacitors. Your reported outage time therefore includes adapter discharge plus ESPHome filtering. Test the actual adapter during commissioning.

Asymmetric Failure and Restore Filtering

filters:
  - delayed_on_off:
      time_on: 10s
      time_off: 2s

This can report failure quickly but require a longer stable period before declaring restoration. Because inversion changes which physical condition maps to ON, verify polarity first.

Design the Input Fail-Safe

Prefer a sensing arrangement where a broken wire produces “power absent” rather than falsely reporting healthy mains. A wiring failure then causes an alert instead of silently masking a real outage.

Generator Monitoring

You can monitor utility present, generator present and protected-load present as separate isolated inputs. The ESP32 should supervise the system, not replace a certified automatic transfer controller.

Utility = OFF
Generator = ON
Protected load = ON

→ utility outage occurred
→ generator successfully supplied load

Do Not Use This as a Life-Safety System

ESP32/Home Assistant monitoring is excellent for convenience and diagnostics. It is not a certified fire, medical, generator-transfer or life-safety alarm. Keep required dedicated protection and control hardware.

Complete ESPHome Configuration

esphome:
  name: mains-power-detector
  friendly_name: Mains Power Detector

esp32:
  board: esp32dev
  framework:
    type: esp-idf

logger:

api:
  encryption:
    key: !secret power_api_key

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

binary_sensor:
  - platform: gpio
    id: mains_present
    name: "Mains Power Present"
    device_class: power
    pin:
      number: GPIO25
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on_off: 1s

  - platform: template
    id: power_failure
    name: "Power Failure"
    device_class: problem
    lambda: |-
      return !id(mains_present).state;

  - platform: status
    name: "Power Detector Online"

sensor:
  - platform: uptime
    name: "Power Detector Uptime"
    type: seconds

Commissioning Test

  • Confirm the ESP32 is powered from backup.
  • Confirm router/AP and Home Assistant are also backed up.
  • Verify Mains Power Present = ON with the monitored outlet live.
  • Unplug only the sensing adapter.
  • Confirm the ESP32 stays online while Mains Power Present changes OFF.
  • Confirm Home Assistant records the event and sends the notification.
  • Restore power and verify the stable-restored delay.
  • Finally simulate the actual breaker/outlet failure.

Troubleshooting

ProblemLikely cause
Mains always ONWrong inversion, adapter accidentally on UPS outlet, interface permanently active
Mains always OFFNo adapter output, wrong GPIO, broken opto/relay wiring, missing pull-up
State flickersFloating input, relay bounce, noisy interface, marginal adapter
ESP32 goes offline during outageDetector is not actually on independent backup power
ESP32 stays online but no phone alertRouter/HA/ISP/notification path failed
Repeated restore alertsUtility restoration unstable; increase stable-ON delay

Measure the low-voltage sensing signal first. Do not keep changing YAML to compensate for an electrical wiring problem.

Recommended Home Assistant Entities

  • Mains Power Present
  • Power Failure
  • Power Detector Online
  • Power Detector Uptime
  • Optional UPS Battery
  • Optional Freezer / Boiler / Garage Circuit Present

Best Overall Architecture

Monitored non-UPS outlet
→ approved 5V adapter
→ optocoupler / dry contact
→ ESP32 GPIO

UPS
├─ ESP32
├─ router/AP
└─ Home Assistant

Home Assistant
├─ immediate outage alert
├─ sustained outage escalation
├─ restore notification
└─ outage history/duration

Final Recommendation

The biggest mistake in an ESP32 power-failure project is powering the detector from the circuit it is supposed to report. If the ESP32 dies with the mains, Home Assistant only sees an unavailable device and cannot prove what happened.

Keep the ESP32 on UPS-backed power and sense the monitored circuit separately. For DIY installations, an approved USB adapter feeding an optocoupler or dry contact is simple, cheap and keeps dangerous mains away from the ESP32.

Use a short ESPHome debounce for clean local detection, then let Home Assistant handle immediate alerts, sustained-outage escalation, restoration notifications and outage history. Back up the network path too if you want alerts during a whole-house outage.

With that architecture, one inexpensive ESP32 can distinguish a utility outage from an ESPHome/network failure, detect individual circuit trips, confirm backup-power survival and build a useful record of outage frequency and duration.

Related ESP32 Guides

Datasheets & External Resources

All external framework references are collected here so the main article keeps readers inside esp32.co.uk.

Share your love