ESP32 Smart Doorbell with Home Assistant (Chime + Notifications + Snapshot)

A classic doorbell can be upgraded into a smart doorbell with just:

  • An ESP32
  • A doorbell button
  • A relay to trigger an existing chime
  • Optional ESP32-CAM for snapshots

With Home Assistant you can:

  • Keep your physical chime
  • Get mobile notifications when someone rings
  • Attach an image snapshot from a camera
  • Log and automate everything (quiet hours, different sounds, etc.)

This guide covers:

  • Simple button + relay wiring
  • ESPHome configuration
  • Home Assistant automations for chime + notification + snapshot
  • An outline of a MQTT version for your usual style

1. Hardware Overview

Base setup (no camera):

  • ESP32 DevKit
  • Doorbell push button (momentary switch)
  • Relay module (3.3 V logic input, dry-contact)
  • Existing low-voltage chime (ideally 8–24 V AC or DC), or a 5–12 V DC buzzer
  • Low-voltage PSU (for ESP32 + relay; or reuse doorbell transformer if suitable)

Optional add-on:

  • ESP32-CAM module near the door
  • 5 V supply for ESP32-CAM
  • 3D-printed or weatherproof housing

⚠️ If your doorbell is powered by mains voltage, only work on the low-voltage side of the transformer and follow local regulations. When in doubt, treat anything on 230 V as off-limits and get an electrician.


2. Concept: How the Smart Doorbell Works

We want three things:

  1. Detect button press → ESP32 reads a GPIO from the doorbell pushbutton.
  2. Ring a chime
    • Either via relay contacts across the existing chime button input
    • Or by directly powering a low-voltage buzzer
  3. Notify Home Assistant
    • Event → HA sends mobile push + (optional) camera snapshot

We’ll do the main implementation with ESPHome & native API.
After that, a quick MQTT variant.


3. Wiring

3.1 Button → ESP32

Wire the button as a simple contact to ground:

ESP32 GPIO  → one side of button
ESP32 GND   → other side of button

We’ll use the internal pull-up so:

  • Button released → GPIO = HIGH
  • Button pressed → GPIO = LOW

Example pin: GPIO 32.

3.2 Relay → Chime

Two typical options:

A. Existing low-voltage chime (recommended)

Most wired doorbells have:

  • Transformer → low voltage (e.g. 8–12 V AC)
  • Chime unit
  • Button wired in series

We emulate the button with a relay:

Chime transformer/chime low-voltage line:

[TRANSFORMER] --- [CHIME] ---[PB1]----(button)----[PB2]

Relay COM  → PB1
Relay NO   → PB2

The existing physical button remains in parallel:

PB1 ---- Button ---- PB2
PB1 ---- Relay COM
PB2 ---- Relay NO

ESP32 → Relay module:

ESP32 3.3V  → Relay VCC
ESP32 GND   → Relay GND
GPIO 25     → Relay IN

B. Direct DC buzzer

If you don’t have an existing chime:

  • Use a 5–12 V DC buzzer or chime module
  • Drive it via relay or MOSFET from a DC PSU
  • Logic is the same: ESP32 toggles the relay for ~1 second.

METHOD 1 – ESPHome Doorbell Node

We’ll create:

  • A binary_sensor for the doorbell button
  • A switch for the relay / chime
  • A doorbell event for Home Assistant
  • Optional integration with an ESP32-CAM

4. ESPHome Base Config

esphome:
  name: esp32-doorbell
  platform: ESP32
  board: esp32dev

wifi:
  ssid: "YOUR_WIFI"
  password: "YOUR_PASSWORD"

logger:
api:
ota:

5. Relay as Chime Output

We want a momentary relay pulse whenever HA or the ESP32 rings the doorbell.

switch:
  - platform: gpio
    id: doorbell_relay
    name: "Doorbell Chime Relay"
    pin: 25
    restore_mode: ALWAYS_OFF
    icon: mdi:bell-ring
    on_turn_on:
      - delay: 800ms    # ring duration
      - switch.turn_off: doorbell_relay

You can hide this from the UI later if you prefer to trigger via automations only:

    internal: true

6. Button Input – Doorbell Press

binary_sensor:
  - platform: gpio
    id: doorbell_button
    name: "Doorbell Button"
    pin:
      number: 32
      mode:
        input: true
        pullup: true
    filters:
      - invert: true          # pressed = ON
      - delayed_on: 30ms      # debounce
      - delayed_off: 50ms
    device_class: occupancy
    on_press:
      - logger.log: "Doorbell pressed!"
      - switch.turn_on: doorbell_relay
      - homeassistant.event:
          event: esphome_doorbell_pressed
          data:
            source: esp32-doorbell

Behaviour:

  • Short press → ESP32 logs, rings relay, sends an HA event esphome_doorbell_pressed.
  • Home Assistant can use either:
    • binary_sensor.doorbell_button state change, or
    • the esphome_doorbell_pressed event as a trigger.

7. Optional ESP32-CAM Snapshot Integration

You can:

  • Use a separate ESP32-CAM running ESPHome with esp32_camera:
  • Add a camera entity in HA (e.g. camera.door_camera)
  • On doorbell press, request a snapshot and send notification with the image

Example ESPHome for ESP32-CAM (very minimal idea):

esphome:
  name: esp32-doorcam
  platform: ESP32
  board: esp32cam

wifi:
  ssid: "YOUR_WIFI"
  password: "YOUR_PASSWORD"

logger:
api:
ota:

esp32_camera:
  name: "Door Camera"
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  resolution: 800x600

(Exact pins depend on module; you’d use the standard ESPHome example for your specific ESP32-CAM board.)

In Home Assistant, this becomes camera.door_camera.


8. Home Assistant Automations

We’ll use the ESPHome event esphome_doorbell_pressed as the central trigger.

8.1 Basic Doorbell Notification + Chime (redundant, but clear)

If you want HA to also control the relay (instead of ESPHome doing it directly), you can remove switch.turn_on: doorbell_relay from ESPHome and move all logic into HA.

Example automation using the event:

automation:
  - alias: "Doorbell – Chime + Notification"
    trigger:
      - platform: event
        event_type: esphome_doorbell_pressed
    action:
      - service: switch.turn_on
        target:
          entity_id: switch.doorbell_chime_relay
      - service: notify.mobile_app
        data:
          title: "Doorbell"
          message: "Someone is at the door"

If you keep the ESPHome on_press action to ring locally, use this automation only for the notification.

8.2 Snapshot + Notification (ESP32-CAM or Other Camera)

Assuming you have:

  • camera.door_camera

Automation:

  - alias: "Doorbell – Snapshot + Mobile Notification"
    trigger:
      - platform: event
        event_type: esphome_doorbell_pressed
    action:
      - service: camera.snapshot
        target:
          entity_id: camera.door_camera
        data:
          filename: "/config/www/snapshots/doorbell_{{ now().timestamp() }}.jpg"

      - delay: "00:00:02"  # Give snapshot time to save

      - service: notify.mobile_app
        data:
          title: "Doorbell"
          message: "Someone is at the door"
          data:
            image: "/local/snapshots/doorbell_{{ now().timestamp() | int - 2 }}.jpg"

Notes:

  • /config/www maps to /local in HA URLs.
  • The timestamp trick gives a roughly matching filename; you can simplify to a static filename if you don’t care about history.

8.3 Quiet Hours (Do Not Disturb)

Disable chime at night, but still get a silent notification:

  - alias: "Doorbell – Silent Night Mode"
    trigger:
      - platform: event
        event_type: esphome_doorbell_pressed
    condition:
      - condition: time
        after: "23:00:00"
        before: "07:00:00"
    action:
      - service: notify.mobile_app
        data:
          title: "Doorbell (Silent)"
          message: "Someone rang the doorbell during quiet hours"

And update the main chime automation with a time condition to exclude night.


METHOD 2 – MQTT Doorbell (Your Style)

If you want the ESP32 to speak pure MQTT:

  • Button press → ESP32 publishes home/doorbell/button message
  • Relay control → HA sends commands to an MQTT switch

9.1 Home Assistant MQTT Entities

Binary_sensor for button:

mqtt:
  binary_sensor:
    - name: "Doorbell Button"
      state_topic: "home/doorbell/button"
      payload_on: "PRESSED"
      payload_off: "IDLE"
      device_class: occupancy

Switch for chime:

mqtt:
  switch:
    - name: "Doorbell Chime Relay"
      command_topic: "home/doorbell/chime/set"
      state_topic: "home/doorbell/chime/state"
      payload_on: "ON"
      payload_off: "OFF"
      retain: false

ESP32 behaviour:

  • On button press:
    • Publish "PRESSED" then (optionally) "IDLE" shortly after
  • On "ON" command to .../chime/set:
    • Pulse relay and afterwards publish "OFF" to state topic

All the notification/snapshot automations remain the same, just triggered from binary_sensor.doorbell_button instead of an ESPHome event.


10. Practical Tips

  • Debounce: mechanical buttons bounce; ESPHome delayed_on is enough in most cases.
  • Local chime even if HA is down: keep switch.turn_on: doorbell_relay in ESPHome’s on_press, so doorbell still rings even if HA/MQTT is offline.
  • Camera choice: if ESP32-CAM image quality is not good enough, use any IP camera; you only need a camera entity for snapshots.
  • Power: use a reliable PSU; a doorbell that reboots whenever someone presses it is… sub-optimal.

Summary

With a single ESP32 and relay you get a smart, still-local doorbell:

  • Button press detected via GPIO
  • Relay triggers existing chime
  • Home Assistant sends notifications and snapshots
  • Quiet hours and advanced logic are just YAML away

The optional ESP32-CAM (or any IP camera) adds the “who is at the door?” piece without needing an expensive commercial smart doorbell.

Share your love

Newsletter Updates

Enter your email address below and subscribe to our newsletter

Leave a Reply

Your email address will not be published. Required fields are marked *