An Introduction to ESPhome

What is the purpose of this guide?

This guide is part of a collection of community-written guides aimed at aiding HA users on their journey.

This guide is intended to give an overview of how ESPhome works (in broad brushstrokes) to empower anyone willing to do a little research to get started with making their own ESP-based devices. This will not cover all the nuances of configuring ESP devices nor tell you how to configure your specific ESP device for your specific use-case.

This will only briefly touch on using ESPhome outside of HA. There are a number of variations depending on installation type, host OS, etc. making it next to impossible to cover all the bases.

ESPresence is similar in the vein that it uses ESP-based devices, but is purpose built, as the name implies, for doing room-based presence detection. This will not be covered.

Additionally, ESPHome device can be configured to use MQTT instead of the native HA integration, but, again, this would be an option for more experienced users and out-of-scope for this guide.

Procedite ad periculum vestrum

Pertinent Links

Let’s get these out of the way upfront:

What is ESPhome?

To quote the project’s explanation directly:
“ESPHome is a system to control your microcontrollers by simple yet powerful configuration files and control them remotely through Home Automation systems.”

Essentially, it’s a python package that makes for simple configuration of ESP-based devices allowing those of us without experience in programming microcontrollers to leverage these inexpensive, yet powerful devices to make our own devices/sensors/whatever. It’s basic function is to take user-provided configurations in YAML format, generate a firmware file, and flash an ESP device with it. This includes the mechanisms to handle flashing over-the-air via WiFi, via USB, etc.

Why do I care?

The main benefit of ESPHome is that it allows users to create nearly any IoT-type device they can imagine (depending on skills of course) without reliance on a vendor-specific integration. It leverages local network communications making it fast, relatively secure, and negating the need for additional hardware (e.g., Zigbee/Z-Wave USB coordinator). They are fully customizable from a configuration standpoint (within the confines of python and the device(s) binaries) as well. This provides loads of benefits such as writing automations that occur directly within the ESP device without needing an external system like HA. It also means the user has full control over what the device does, what it exposes externally, and even allows you to stick a device at a remote site with connectivity back to HA via Wireguard.

Parts Involved

  • Physical device
  • ESPHome configuration.yaml file
  • ESPHome
    • ESPHome add-on
    • ESPHome python package installed in Window/MacOS/Linux/Docker container
  • ESPHome integration

Flow Chart For Wiki Editors

This chart was created using Excalidraw. Once in the tool, copy and paste this into the window and it will re-create the drawing. Please be sure to copy the entire drawing and paste it into the code block below for any updates:

Flow Chart Code
{"type":"excalidraw/clipboard","elements":[{"type":"diamond","version":330,"versionNonce":1926085897,"isDeleted":false,"id":"T07ICoFE5UVqH_Wln0GyN","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":666.0713326590399,"y":-83.13973539468975,"strokeColor":"#1e1e1e","backgroundColor":"transparent","width":205.99998474121094,"height":224.99998092651367,"seed":698280167,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[{"type":"text","id":"E8I4oRxwz6XEiCtTPHo23"},{"id":"5zR-5MJxm4kTMAA0m9Ag4","type":"arrow"},{"id":"9erSY_EIlgVqeG-1uJyML","type":"arrow"},{"id":"t8-w8ODQY2y4zhbUQWkI8","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":309,"versionNonce":235090921,"isDeleted":false,"id":"E8I4oRxwz6XEiCtTPHo23","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":725.8913666861395,"y":-8.389740163061333,"strokeColor":"#1e1e1e","backgroundColor":"transparent","width":86.35992431640625,"height":75,"seed":935277575,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"Physical \nESPHome\nDevice","textAlign":"center","verticalAlign":"middle","containerId":"T07ICoFE5UVqH_Wln0GyN","originalText":"Physical ESPHome Device","lineHeight":1.25},{"type":"rectangle","version":206,"versionNonce":1428606665,"isDeleted":false,"id":"bXZsfb3OX6sapARxOIg9S","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":869.0714394705633,"y":495.86018449666767,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":250.00000000000003,"height":114.00001525878906,"seed":770251559,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"59egOtlDkarP6GPyhQCB4"},{"id":"5zR-5MJxm4kTMAA0m9Ag4","type":"arrow"},{"id":"jhdIuirbnUHLUqJN9NfVU","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":142,"versionNonce":1859390889,"isDeleted":false,"id":"59egOtlDkarP6GPyhQCB4","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":914.5315072195867,"y":540.3601921260622,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":159.07986450195312,"height":25,"seed":277421639,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"ESPHome Add-on","textAlign":"center","verticalAlign":"middle","containerId":"bXZsfb3OX6sapARxOIg9S","originalText":"ESPHome Add-on","lineHeight":1.25},{"type":"arrow","version":576,"versionNonce":1827799049,"isDeleted":false,"id":"5zR-5MJxm4kTMAA0m9Ag4","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":996.2374285574065,"y":483.57443969337527,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":210.39867246755784,"height":332.57567568831195,"seed":578534759,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"bXZsfb3OX6sapARxOIg9S","focus":0.2855983471850599,"gap":12.285744803292403},"endBinding":{"elementId":"T07ICoFE5UVqH_Wln0GyN","focus":0.5843225932086189,"gap":18.538074892095423},"lastCommittedPoint":null,"startArrowhead":"arrow","endArrowhead":"arrow","points":[[0,0],[-210.39867246755784,-332.57567568831195]]},{"type":"arrow","version":1802,"versionNonce":257315273,"isDeleted":false,"id":"t8-w8ODQY2y4zhbUQWkI8","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":844.3202858574455,"y":94.69159591998749,"strokeColor":"#6741d9","backgroundColor":"transparent","width":499.89408051044165,"height":393.3083113311112,"seed":386758791,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"T07ICoFE5UVqH_Wln0GyN","focus":0.054459698650718286,"gap":23.648782610492532},"endBinding":{"elementId":"MOmYBUUhsizFOWaMAhzB-","focus":0.4244464125354685,"gap":9.14624166643253},"lastCommittedPoint":null,"startArrowhead":"arrow","endArrowhead":"arrow","points":[[0,0],[499.89408051044165,393.3083113311112]]},{"type":"rectangle","version":139,"versionNonce":1771610697,"isDeleted":false,"id":"joqI9ZkWeSJxaP1ZpQ9BG","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":864.0712105887274,"y":745.8601844966677,"strokeColor":"#f08c00","backgroundColor":"transparent","width":256.99996948242193,"height":165.99998474121094,"seed":66768807,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"gHMQaqWWuVXjvjYYSr4O3"},{"id":"jhdIuirbnUHLUqJN9NfVU","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":122,"versionNonce":1287614761,"isDeleted":false,"id":"gHMQaqWWuVXjvjYYSr4O3","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":874.3913094656805,"y":778.8601768672731,"strokeColor":"#f08c00","backgroundColor":"transparent","width":236.35977172851562,"height":100,"seed":326124231,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"ESPHome YAML \nConfiguration File\n\n/homeassistant/esphome","textAlign":"center","verticalAlign":"middle","containerId":"joqI9ZkWeSJxaP1ZpQ9BG","originalText":"ESPHome YAML Configuration File\n\n/homeassistant/esphome","lineHeight":1.25},{"type":"arrow","version":113,"versionNonce":44118921,"isDeleted":false,"id":"jhdIuirbnUHLUqJN9NfVU","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1000.8614381616767,"y":731.8601692378786,"strokeColor":"#f08c00","backgroundColor":"transparent","width":0.3148416416888722,"height":115.99998474121094,"seed":1980387815,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"joqI9ZkWeSJxaP1ZpQ9BG","focus":0.06644784155679377,"gap":14.000015258789062},"endBinding":{"elementId":"bXZsfb3OX6sapARxOIg9S","focus":-0.05037098189997817,"gap":5.9999847412109375},"lastCommittedPoint":null,"startArrowhead":null,"endArrowhead":"arrow","points":[[0,0],[-0.3148416416888722,-115.99998474121094]]},{"type":"rectangle","version":244,"versionNonce":1796340457,"isDeleted":false,"id":"BMYXb3fVk0K6f8uYQNVz4","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":811.0714089529852,"y":428.86017686727314,"strokeColor":"#1971c2","backgroundColor":"transparent","width":694.2858232770653,"height":554.0000152587891,"seed":349535495,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":93,"versionNonce":1388623305,"isDeleted":false,"id":"BSIqiEN-shVfCCNCRPVt0","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1057.257965087891,"y":936.574497458791,"strokeColor":"#1971c2","backgroundColor":"transparent","width":211.48391723632812,"height":35,"seed":55460903,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":28,"fontFamily":1,"text":"Home Assistant","textAlign":"center","verticalAlign":"top","containerId":null,"originalText":"Home Assistant","lineHeight":1.25},{"type":"rectangle","version":295,"versionNonce":1847399593,"isDeleted":false,"id":"eG-yoDGOAmDKmNuYjtJRr","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":428.07137843540704,"y":492.8601921260622,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":250.00000000000003,"height":114.00001525878906,"seed":828450631,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"DzkQOl08vN1_ASaclr03t"},{"id":"nq9L2pMAEvPF9Uwfkca-z","type":"arrow"},{"id":"9erSY_EIlgVqeG-1uJyML","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":249,"versionNonce":13014921,"isDeleted":false,"id":"DzkQOl08vN1_ASaclr03t","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":470.37145015171564,"y":524.8601997554567,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":165.3998565673828,"height":50,"seed":1567270503,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"ESPHome python \npackage","textAlign":"center","verticalAlign":"middle","containerId":"eG-yoDGOAmDKmNuYjtJRr","originalText":"ESPHome python package","lineHeight":1.25},{"type":"rectangle","version":227,"versionNonce":1291632233,"isDeleted":false,"id":"4he5jMY_4cbyrdrdMiRbW","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":423.0711495535711,"y":742.8601921260622,"strokeColor":"#f08c00","backgroundColor":"transparent","width":256.99996948242193,"height":165.99998474121094,"seed":1178026375,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"y0RUJb-7NfcXQhyc7tPHY"},{"id":"nq9L2pMAEvPF9Uwfkca-z","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":232,"versionNonce":1099630921,"isDeleted":false,"id":"y0RUJb-7NfcXQhyc7tPHY","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":441.39123317173517,"y":775.8601844966677,"strokeColor":"#f08c00","backgroundColor":"transparent","width":220.35980224609375,"height":100,"seed":486766759,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"ESPHome YAML \nConfiguration File\n\n\"environment dependent","textAlign":"center","verticalAlign":"middle","containerId":"4he5jMY_4cbyrdrdMiRbW","originalText":"ESPHome YAML Configuration File\n\n\"environment dependent","lineHeight":1.25},{"type":"arrow","version":375,"versionNonce":175023433,"isDeleted":false,"id":"nq9L2pMAEvPF9Uwfkca-z","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":559.8613771265204,"y":728.8601768672731,"strokeColor":"#f08c00","backgroundColor":"transparent","width":0.3148416416888722,"height":115.99998474121094,"seed":930859975,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"4he5jMY_4cbyrdrdMiRbW","focus":0.06644784155679377,"gap":14.000015258789062},"endBinding":{"elementId":"eG-yoDGOAmDKmNuYjtJRr","focus":-0.05037098189997817,"gap":5.9999847412109375},"lastCommittedPoint":null,"startArrowhead":null,"endArrowhead":"arrow","points":[[0,0],[-0.3148416416888722,-115.99998474121094]]},{"type":"rectangle","version":228,"versionNonce":296618761,"isDeleted":false,"id":"rsR29K_hc96YDGdrn1ewl","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":350.64276776994984,"y":425.86018449666767,"strokeColor":"#e03131","backgroundColor":"transparent","width":416.57132829938615,"height":554.0000152587891,"seed":29145831,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":183,"versionNonce":1202307561,"isDeleted":false,"id":"9zmGE4I7O5ak-EpNvL0FK","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":359.89733668736017,"y":935.8601844966677,"strokeColor":"#e03131","backgroundColor":"transparent","width":397.34783935546875,"height":35,"seed":810731015,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":28,"fontFamily":1,"text":"Windows/Linux/MacOS/Docker","textAlign":"center","verticalAlign":"top","containerId":null,"originalText":"Windows/Linux/MacOS/Docker","lineHeight":1.25},{"type":"arrow","version":217,"versionNonce":861579017,"isDeleted":false,"id":"9erSY_EIlgVqeG-1uJyML","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":556.0714089529852,"y":482.8601730525759,"strokeColor":"#2f9e44","backgroundColor":"transparent","width":196.00006103515625,"height":328.9999771118164,"seed":842689831,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"eG-yoDGOAmDKmNuYjtJRr","focus":-0.23223127255329207,"gap":10.000019073486328},"endBinding":{"elementId":"T07ICoFE5UVqH_Wln0GyN","focus":-0.5550519902030084,"gap":20.6417674736753},"lastCommittedPoint":null,"startArrowhead":"arrow","endArrowhead":"arrow","points":[[0,0],[196.00006103515625,-328.9999771118164]]},{"type":"text","version":105,"versionNonce":1588534185,"isDeleted":false,"id":"Ua0WNqnkc3q8DPA2sFOk3","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":688.1527546473867,"y":252.14595273310027,"strokeColor":"#1e1e1e","backgroundColor":"transparent","width":161.97991943359375,"height":105,"seed":1658859591,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":28,"fontFamily":1,"text":"Firmware\nInstallation\n(either/or)","textAlign":"center","verticalAlign":"top","containerId":null,"originalText":"Firmware\nInstallation\n(either/or)","lineHeight":1.25},{"type":"rectangle","version":349,"versionNonce":1065336457,"isDeleted":false,"id":"MOmYBUUhsizFOWaMAhzB-","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1245.7141952514635,"y":497.1461489175312,"strokeColor":"#6741d9","backgroundColor":"transparent","width":206.85712541852627,"height":101.71434674944192,"seed":2082508647,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"xI5gV_6rArX-KrHedN9kx"},{"id":"t8-w8ODQY2y4zhbUQWkI8","type":"arrow"},{"id":"JmKEztwgtv2zZNsYX-f8Z","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":295,"versionNonce":1207502185,"isDeleted":false,"id":"xI5gV_6rArX-KrHedN9kx","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1293.8728070940274,"y":523.0033222922522,"strokeColor":"#6741d9","backgroundColor":"transparent","width":110.53990173339844,"height":50,"seed":1212680839,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"ESPHome\nIntegration","textAlign":"center","verticalAlign":"middle","containerId":"MOmYBUUhsizFOWaMAhzB-","originalText":"ESPHome\nIntegration","lineHeight":1.25},{"type":"rectangle","version":462,"versionNonce":1130786889,"isDeleted":false,"id":"U7DYDA-ONDdHIsW843sDs","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1251.4285681588285,"y":749.7176036468841,"strokeColor":"#9c36b5","backgroundColor":"transparent","width":197.71432059151812,"height":110,"seed":336798119,"groupIds":[],"frameId":null,"roundness":{"type":3},"boundElements":[{"type":"text","id":"xmJ5Cdm7u_L4ud3IUfc6z"},{"id":"JmKEztwgtv2zZNsYX-f8Z","type":"arrow"}],"updated":1711718534907,"link":null,"locked":false},{"type":"text","version":462,"versionNonce":128155433,"isDeleted":false,"id":"xmJ5Cdm7u_L4ud3IUfc6z","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1290.3757858276344,"y":754.7176036468841,"strokeColor":"#9c36b5","backgroundColor":"transparent","width":119.81988525390625,"height":100,"seed":1622037703,"groupIds":[],"frameId":null,"roundness":null,"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"fontSize":20,"fontFamily":1,"text":"Dashboards\nAutomations\nScripts\netc.","textAlign":"center","verticalAlign":"middle","containerId":"U7DYDA-ONDdHIsW843sDs","originalText":"Dashboards\nAutomations\nScripts\netc.","lineHeight":1.25},{"type":"arrow","version":1104,"versionNonce":318847177,"isDeleted":false,"id":"JmKEztwgtv2zZNsYX-f8Z","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"angle":0,"x":1346.1800293251276,"y":748.5746767495625,"strokeColor":"#9c36b5","backgroundColor":"transparent","width":2.7339938002214694,"height":147.42832728794724,"seed":1438000103,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718696509,"link":null,"locked":false,"startBinding":{"elementId":"U7DYDA-ONDdHIsW843sDs","focus":-0.030683237494432507,"gap":1.1429268973215585},"endBinding":{"elementId":"MOmYBUUhsizFOWaMAhzB-","focus":0.06402346099205031,"gap":2.285853794642179},"lastCommittedPoint":null,"startArrowhead":"arrow","endArrowhead":"arrow","points":[[0,0],[-2.7339938002214694,-147.42832728794724]]},{"type":"line","version":107,"versionNonce":1254787305,"isDeleted":false,"id":"uFTUkWDZv7fJX0DgWuQxL","fillStyle":"solid","strokeWidth":2,"strokeStyle":"dotted","roughness":1,"opacity":100,"angle":0,"x":1172.5712334769082,"y":428.5745677582122,"strokeColor":"#1971c2","backgroundColor":"transparent","width":3.4286063058034415,"height":555.4285539899554,"seed":1932988167,"groupIds":[],"frameId":null,"roundness":{"type":2},"boundElements":[],"updated":1711718534907,"link":null,"locked":false,"startBinding":null,"endBinding":null,"lastCommittedPoint":null,"startArrowhead":null,"endArrowhead":null,"points":[[0,0],[3.4286063058034415,555.4285539899554]]}],"files":{}}

Physical device

There are an litany of individual devices supported by ESPHome. These cover everything from individual boards to preconfigured devices. A full list of officially supported devices can be found on the ESPHome site.

Physical devices come in two general flavors.

DIY

You build one yourself. This means acquiring your components, including the microcontroller and any sensors, building out the circuitry, creating the configuration file, compiling and flashing the firmware with ESPHome, and finally importing the device in HA using the ESPHome integration.

Everything from start to finish is managed by the end user.

Prebuilt

You buy something pre-configured. There are a number of vendors that sell prebuilt/pre-configured devices. These are a solid option if you want to have the benefits of ESPHome without wanting to get into building your own devices. These typically come in the form of a pre-built device that has firmware already loaded. When the device is powered on, it will broadcast a wireless network that you’ll connect to, select your WiFi network and provide credentials through your web browser, and click a button to connect the device to your network.

The upshot is that the device is still fully configurable. Meaning that you can opt to modify the configuration file for the device and use ESPHome to reflash it at any point.

ESPHome configuration.yaml file

A device-specific file used to define the configurations for the device. Creating these files is device and use-case specific. These can be created by either the ESPHome add-on or a standalone ESPHome installation.

Caveat: Whichever ESPHome instance is used to generate the configuration file is where the file will need to be managed. Meaning, if you use the add-on to create the file, then any edits will need to be done from the add-on. There are methods to allow updating from either but would be an advanced setup and not something the average user should attempt to do.

ESPHome

The python package that reads the YAML configuration and generates the firmware file based on the configurations. The package can be installed a few ways:

  1. The ESPHome add-on for HA.
  2. Manually installed on Windows, Linux, and MacOS. The only pre-requisites is that python is already installed. General instructions can be found here.
  3. Setup in a Docker container following the official instructions.

The rest of this guide will assume you are using the ESPHome add-on, but there will be some caveats touched on regarding the other installation methods.

ESPHome Integration

Used for auto-discovery of new ESPHome devices and integration into HA. This is used to pull any configured components into HA for the device. The entities that are created will be based on the configuration of the device.

The key item here is that this requires having the native API component set in the configuration of the device. If you opt to set an API key, it will be required for the integration to talk to the device. If you set the device up in the ESPHome add-on, the API key should automatically be pulled. If the device is configured outside of HA, then you will have to provide the API key when adding the device.

6 Likes

Getting Started

The bare minimum to get going is to buy a pre-built ESP device, connect it to your WiFi, and add it into HA via the ESPHome integration.

Adding a Device to the ESPHome Integration

The ESPHome integration is enabled to use mDNS for auto-discovery. Once a device is connected to your network, it should automatically show up in HA to be added.

image

If it’s not, you can opt to manually add it.

First option is to click this button:

If that doesn’t work, then you can manually add it in HA by going to Settings → Devices → Click on “Add Integration”

You’ll be prompted to provide the IP address for the device. Click through the prompts and you’re done. It will show up as a new device and will populate entities based on what the vendor configured.

Adding the ESPHome Add-on

Now, let’s assume you want to either reconfigure a pre-built device or build your own. You’re going to need to install the ESPHome package. Arguably the easiest method to install and use it is via the ESPHome add-on.

To make that even simpler, all you should need to do is click this button and select install:

Open your Home Assistant instance and show the dashboard of the ESPHome add-on.

If it doesn’t, again, you can manually install the add-on.

  1. Go to Settings → Add-ons
  2. Click on “Add-on Store” in the bottom right-hand corner.
  3. Find ESPHome in the list
    image
  4. Select “Install”
    image

Once the add-on is installed, click on “Start” to get it going.

Caveat: There are options to start the add-on when HA boots, enable the watchdog service to automatically restart it if it crashes, and whether or not you want it to show in the sidebar. All of these options are completely up to you. It’s only necessary to have the add-on running when configuring the device(s) and checking for updates.

Configuring a Device

Things can go a few different ways here. If you’re building your own device, then nothing will show up. We’ll cover this farther down.

Prebuilt Devices

Many vendors will use an option called dashboard_import for their devices along with a sub-option to pull a pre-built configuration file from a website (often Github). If that’s the case, then you’ll see an option in the add-on to “adopt” the device. Just click the button.
image

image

Caveat if this is your first device

Caveat: If this is your first device, you may see a prompt like this:

The box explains itself, but this is essentially storing your WiFI credentials so you don’t have to input them every time you set a device up. You can, of course, modify what credentials a particular device uses if you’re the type that likes separate WiFi networks depending on the device.

Additionally, another pop-up may show up with an encryption key. This is the API key for the device (mentioned in the first post). You can save it off now or retrieve it later on from the add-on, if needed.

What happens is the add-on will attempt to download the configuration file from the linked website and store it locally to be modified by the user. Once adopted, you can click on “edit” on the device card to view the configuration.

You’ll notice that this is obviously a stripped down configuration as there’s nothing in the configuration file for entities and what-not. You can follow the packages link which shows a much larger configuration file (note the dashboard_import line):

But why?

Vendors want their devices to be as simple as possible to setup and use. The way this works is that the ESPHome add-on pulls the dashboard_import file which is usually just some of the basic configuration options: device name, wifi settings, etc. When you “install” the firmware, the add-on will read the configuration file and, when it sees the line for packages, go out to the internet to pull the rest of the configurations before compiling the firmware. The packages file is cached so that the internet requirement is only needed the first time, per device.

This flow also allows vendors to modify the core configuration to add new features, fix bugs, etc. and, since the configuration is centrally managed, they don’t have to worry about getting the updated configuration to customers. The add-on will periodically check the packages link for changes.

DIY

So, you want to try your hand at making your own device. Or you want to take an existing device and build the configuration from scratch to learn. All of this will be done from the ESPHome add-on assuming that this is from the perspective of a fresh installation. Some of the prompts may change depending on what has been done with your HA installation.

  1. In the bottom right-hand corner, click on “New Device”
  2. You’ll see a pop-up prompting you to open the ESPHome Web Flasher, just click “Continue” for now.
  3. Give your device a name.
    image
  4. You’ll be presented with a list of device types. Select the option that matches the board type you’re using. With “Use recommended settings” ticked, ESPHome will generate a generic configuration file that should work based on the SoC. If you untick this option, you’ll be provided with an additional selection of official supported, vendor specific boards.
    image
  5. After selecting your board, you’ll be provided with the API key. For our scenario (using the ESPHome add-on and ESPHome integration from the same HA instance), we can ignore this.
    image

At this point, you’ll have a basic configuration that can be flashed to a device and allow it to connect to your WiFi network. You can opt to click install and move forward with installation, or click skip to make further edits to the configuration file.

image

I’ve added additional commentary so this will look mildly different for your view.

Installation

We’re almost there. Device is in hand and the configuration file is created. Now it’s time to compile and flash the firmware.

First, you need to determine your flashing method. There are a few options here.
image

For any method besides “Wirelessly”, you’ll need to know how to get your device into flash mode. This varies by device. Some are done with buttons on the device, some by grounding out a particular pin during power up, some can be done through software, etc.

Wirelessly

The easiest method, but this requires that the device is already on the network, reachable by Home Assistant, and has OTA enabled in the firmware currently on the device. As mentioned in the config commentary, if an OTA password has previously been set, you’ll need to make sure the password matches in the configuration file that you are flashing. There are ways around this, but they’re more advanced and out of scope of this guide. If all else fails, you can go the hardwired route.

If this all checks out, when you select the option ESPHome will immediately begin compiling the firmware and then will automatically upload it to the device once compiled. How long this takes drastically depends on your configuration and the hardware (physical or virtualized) that HA is running on.

Plug into this computer

This option assumes that you are accessing the add-on from a remote computer (because most of us are). Unless you’ve gone through the effort to enable HTTPS connectivity to HA (default setup), this option will not work. If you have not, this method will essentially guide you through the “Manual download” approach that we’ll cover below.

I’ve never used this method, so hopefully someone more familiar will come along and edit this post with more details.

Plug into the computer running ESPHome Dashboard

This option allows you to plug the ESP device into the machine you’re running HA on. If you are running virtualized, this also inherently means that you’ve setup passthrough from the host machine to the VM instance for the USB port or the device itself. Similarly to the OTA option, once you click this option, you’ll be prompted to select your device from a list, and ESPHome will move forward with compiling and flashing the firmware.

Manual Download

This is likely the option most folks will take for the initial installation. This option will compile the firmware and then prompt the user to download the firmware file. For 90% of users, you’ll select the “modern format” option.

  • The legacy format is for use with the ESPHome Flasher tool that pre-dates the web flasher.

After you select an option, you’re browser should show a download of a *.bin file (where the * is the device name). Some browsers may block this download, so be aware. The *.bin file is used in tandem with the ESPHome Web Flasher tool.

ESPHome Web Flasher

ESPHome Web Flasher

You’ll need three things:

  1. A computer running a Chromium-based browser
    The mobile version of Chrome is not supported as of this writing.
  2. A copy of the *.bin firmware file on the computer.
  3. The ESP device connected to the computer in flash mode.
    You may need to install drivers for this to work.

Once you’ve got that done, go to the site:

  1. Select “Connect”
    image
  2. Select the device from the prompt. It will likely show as a generic JTAG/serial device.
    image
  3. Select “Install” from the device card.
    image
  4. Select your *.bin file and click the install button
    image
  5. Wait for the installation to finish.
    Once done, ESPHome will try to do a software reboot of the device. This sometimes does not work. If your device doesn’t connect to the network with a minute or so, give it a restart to see if that helps (via the reset button if available or just remove/add power).

If everything is right, you should see the device be auto-discovered by the HA:
image

Tips

  • You can bypass creating the initial configuration using the ESPHome add-on by selecting the “Prepare for first use” option. This will also flash the device with a basic configuration that has AP mode enabled that you’ll use to connect the device to the network. This enables the rest of the configuration to be done wirelessly. Once flashed, you’ll finish the setup just like a vendor device mentioned above. Add it through the integration and adopt it into the add-on.
    image
  • There are a number of sample projects on the ESPHome main site.
  • Keeping a serial-to-USB dongle on hand is a good idea. Something like this one will do the trick.
  • There’s a wealth of documentation on the ESPHome site to help navigate things. Take advantage of it.

Re: the block diagram. The integration block should be inside the Home Assistant block.

Also, this is an English language forum

(joking).

3 Likes

This would be more accurate:

This is done. I realized the main point I was trying to drive home was the integration is not tied to the add-on.

1 Like