ESPHome + Home Assistant: Build Your First Custom Sensor in 30 Minutes
Get started with ESPHome and Home Assistant. Flash an ESP32, configure YAML, and build a temperature/humidity sensor that auto-discovers in HA. Complete walkthrough with working config.
ESPHome + Home Assistant: Build Your First Custom Sensor in 30 Minutes
Off-the-shelf Zigbee sensors work fine until you need something specific — a sensor in an enclosure that fits a particular spot, a relay that triggers on a condition no commercial product supports, or a board that combines three functions for $4 instead of buying three $30 devices.
That is where ESPHome comes in. It turns cheap ESP32 and ESP8266 boards into fully integrated Home Assistant devices with zero custom firmware code. You write YAML. ESPHome compiles it, flashes it, and the device shows up in HA automatically.
I use ESPHome nodes across my 700+ entity system for things commercial sensors cannot do. This guide gets you from zero to a working temperature/humidity sensor reporting to Home Assistant in about 30 minutes.
What ESPHome Actually Is
ESPHome is a firmware generator. You describe what your microcontroller should do in a YAML file — which GPIO pins to read, what sensors are attached, how to connect to WiFi — and ESPHome compiles that into firmware, flashes it to the board, and handles the HA integration automatically via its native API.
No Arduino IDE. No C++. No MQTT broker (unless you want one). The device appears in Home Assistant as a native integration with auto-discovered entities.
The key workflow:
1. Write a YAML config file
2. ESPHome compiles it into firmware
3. Flash the firmware to your ESP board (USB the first time, OTA after that)
4. Home Assistant auto-discovers the device
5. Edit the YAML and push updates over WiFi — no USB cable needed
Why ESPHome Over Tasmota or WLED
**Tasmota** is great for flashing off-the-shelf smart plugs and switches. It is a general-purpose firmware with a web UI. But when you need custom sensor logic, conditional behavior, or tight HA integration, you hit its limits fast. Tasmota communicates via MQTT, which means running a broker, configuring topics, and writing HA discovery configs yourself for anything non-standard.
**WLED** is purpose-built for addressable LEDs and it is the best at that. If you only need LED control, use WLED. But it does not do sensors, relays, or general GPIO.
**ESPHome** fills the gap: custom hardware configs with native HA integration, no broker, OTA updates, and a YAML-only workflow. If you are building a device that talks to Home Assistant, ESPHome is the right tool almost every time.
Use Tasmota if you are reflashing an existing commercial device. Use WLED if you only need LED strips. Use ESPHome for everything else.
Hardware: What to Buy
ESP32-S3 (Recommended)
The ESP32-S3 is the current best choice. Dual-core, built-in USB, Bluetooth LE, plenty of GPIO, and enough RAM for most projects. A dev board costs $4-8 on AliExpress or $10-15 on Amazon.
Good boards:
ESP8266 (Budget Option)
The ESP8266 is older, single-core, fewer GPIOs, and less RAM. But it costs $2-3, and for simple single-sensor nodes it works fine. The **Wemos D1 Mini** is the classic choice — small, cheap, USB-C on newer revisions.
Do not buy ESP8266 for new projects if you plan to add features later. The memory limits will bite you. Spend the extra $3 on an ESP32.
For This Guide
You need:
Total cost: under $15.
First Flash: The Web Installer
The fastest way to get ESPHome running on a new board is the web installer. No software to install on your computer.
1. Open [web.esphome.io](https://web.esphome.io) in Chrome or Edge (must support Web Serial)
2. Plug your ESP32 into your computer via USB
3. Click **Connect** and select the serial port
4. Click **Prepare for first use**
5. Follow the prompts to connect it to your WiFi network
That is it. The board now runs a basic ESPHome firmware and is connected to your network. You will configure the actual functionality through the ESPHome dashboard next.
Install the ESPHome Add-on (HA OS / Supervised)
If you are running Home Assistant OS or Supervised:
1. Go to **Settings > Add-ons > Add-on Store**
2. Search for **ESPHome**
3. Install and start it
4. Open the ESPHome dashboard from the sidebar
For HA Container or Core, run ESPHome as a standalone tool:
pip install esphome
or
docker run -d --name esphome \
-p 6052:6052 \
-v /config/esphome:/config \
esphome/esphome
YAML Config Anatomy
Every ESPHome device config has the same structure. Here is the skeleton:
esphome:
name: office-sensor
friendly_name: "Office Sensor"
esp32:
board: esp32-s3-devkitc-1
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
Fallback hotspot if WiFi fails
ap:
ssid: "Office-Sensor-Fallback"
password: "fallback123"
captive_portal:
logger:
api:
encryption:
key: !secret api_encryption_key
ota:
password: !secret ota_password
Let me break down each block.
`esphome:`
The device identity. `name` becomes the hostname and the entity prefix in HA. Keep it lowercase with hyphens. `friendly_name` is what shows in the HA UI.
`esp32:` / `esp8266:`
Board definition. This tells ESPHome which chip you are using so it compiles the right firmware. Common values:
`wifi:`
Your network credentials. Always use `!secret` references that point to a `secrets.yaml` file in your ESPHome directory — never hardcode passwords in device configs.
The `ap:` block creates a fallback hotspot if the device cannot connect to WiFi. Combined with `captive_portal:`, you can reconfigure WiFi credentials from your phone without reflashing. This has saved me multiple times after changing router passwords.
`logger:`
Enables serial and wireless logging. Leave it on during development. You can view logs in the ESPHome dashboard in real time.
`api:`
The native API that Home Assistant uses to communicate with the device. The encryption key is generated automatically when you create a new device in the ESPHome dashboard. This replaces MQTT — the device talks directly to HA with auto-discovery.
`ota:`
Over-the-air updates. After the first USB flash, every subsequent firmware update goes over WiFi. This is the single best feature of ESPHome — you never have to unscrew an enclosure or pull a board out of a wall to update it.
Build 1: DHT22 Temperature and Humidity Sensor
Wire the DHT22 to your ESP32:
| DHT22 Pin | ESP32 Pin |
|-----------|-----------|
| VCC (pin 1) | 3.3V |
| Data (pin 2) | GPIO4 |
| NC (pin 3) | — |
| GND (pin 4) | GND |
Add a 10k pull-up resistor between VCC and Data if your DHT22 module does not have one built in. Most breakout boards include it already.
Here is the complete config:
esphome:
name: office-sensor
friendly_name: "Office Sensor"
esp32:
board: esp32-s3-devkitc-1
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Office-Sensor-Fallback"
password: "fallback123"
captive_portal:
logger:
api:
encryption:
key: !secret api_encryption_key
ota:
password: !secret ota_password
sensor:
pin: GPIO4
model: DHT22
temperature:
name: "Temperature"
filters:
humidity:
name: "Humidity"
update_interval: 30s
Flash this config to your board:
1. In the ESPHome dashboard, click the three dots on your device and select **Install**
2. Choose **Wirelessly** (if already flashed once) or **Plug into this computer** for first flash
3. Wait for the compile and upload to finish (~60 seconds)
Go to **Settings > Devices & Services** in Home Assistant. You will see a notification that a new ESPHome device was discovered. Click **Configure**, enter the encryption key, and the device is integrated. Two entities appear: `sensor.office_sensor_temperature` and `sensor.office_sensor_humidity`.
That is a working sensor node. Under $15 in hardware. No soldering beyond the header pins if your board does not come with them pre-soldered.
Build 2: GPIO Binary Sensors
Binary sensors are even simpler. A reed switch on a door, a PIR motion detector, a button — anything that is either on or off.
Example: a door sensor using a magnetic reed switch wired between GPIO5 and GND.
binary_sensor:
pin:
number: GPIO5
mode:
input: true
pullup: true
name: "Workshop Door"
device_class: door
filters:
The `pullup: true` enables the internal pull-up resistor so you do not need an external one. The `delayed_on/off` filters debounce the signal — mechanical switches bounce for a few milliseconds when they change state, and without filtering you will get rapid on/off/on/off events.
Setting `device_class: door` tells Home Assistant this is a door sensor, which controls the icon, history display, and which automations templates suggest it for.
You can put multiple sensors on one board. A single ESP32 can handle a DHT22, three reed switches, a PIR sensor, and a relay — all in one YAML file, all as separate entities in HA.
binary_sensor:
pin:
number: GPIO5
mode:
input: true
pullup: true
name: "Workshop Door"
device_class: door
filters:
pin:
number: GPIO18
mode:
input: true
pullup: true
name: "Workshop Motion"
device_class: motion
filters:
Automations Using ESPHome Sensors
Once your ESPHome sensors are in Home Assistant, they work exactly like any other entity. No special handling needed.
Example: turn on a light when the workshop motion sensor triggers and turn it off after 5 minutes of no motion.
automation:
alias: "Workshop Motion Light"
trigger:
entity_id: binary_sensor.workshop_motion
to: "on"
action:
target:
entity_id: light.workshop_bench
data:
brightness_pct: 100
alias: "Workshop Motion Light Off"
trigger:
entity_id: binary_sensor.workshop_motion
to: "off"
for: "00:05:00"
action:
target:
entity_id: light.workshop_bench
Or trigger notifications based on temperature thresholds:
alias: "Server Room Temperature Alert"
trigger:
entity_id: sensor.office_sensor_temperature
above: 85
action:
data:
title: "Temperature Alert"
message: "Office sensor reading {{ states('sensor.office_sensor_temperature') }}F"
ESPHome sensors update Home Assistant in real time over the native API. There is no polling interval on the HA side — the device pushes state changes as they happen.
OTA Updates: The Killer Feature
After the first USB flash, you never touch a cable again. Edit the YAML, click **Install > Wirelessly**, and the firmware updates over WiFi in about 30 seconds.
This matters more than you think. Once a sensor is mounted inside an enclosure and screwed to a wall, the idea of taking it down, opening the case, and plugging in a USB cable to change one line of YAML is a non-starter. OTA means you can iterate on the config from your desk.
A few OTA tips:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.50
gateway: 192.168.1.1
subnet: 255.255.255.0
What to Build Next
Once you have the basics working, ESPHome opens up a lot:
Each of these follows the same pattern: add a few lines of YAML, flash OTA, entities appear in HA.
---
If you want a collection of production-tested automations that work with ESPHome sensors and the rest of the Home Assistant ecosystem, the [Automation Cookbook](https://beslain.gumroad.com/l/ha-automation-cookbook) has ready-to-use YAML configs for motion lighting, presence detection, climate control, and more. Use code **LAUNCH50** for 50% off.
---
*This post is part of [The Automated Home](/) — practical Home Assistant guides from a 700+ entity production system.*
Enjoyed this guide?
Get more like it delivered weekly. Real configs, tested YAML, zero fluff.
Join 0+ smart home builders. No spam, unsubscribe anytime.