Skip to main content

From RPi to ESPHome, from DIY to a professional solution

Avid readers of this blog may know that I have add a few temperature sensors to my heating setup (exactly 8 of them), in order to troubleshoot an issue we had as we moved into our new house. The description how I did that is described in this post.

I used DS18B20 sensors and a Raspberry Pi to monitor temperature changes which delivered measurements to my Homeassistant installation over MQTT using rpi-temperature-mqtt.

Over time, I added more and more functionality to this RPi: controlling the boiler via relays and also monitoring the serial bus of my Buderus boiler.

Adding all these functions incrementally was pretty simple, but as a professional software engineer, I was feeling increasingly uncomfortable with how I would reproduce the same installation should the RPi fail. As a software professional I believe in CI/CD systems, automated tests and deployment. Infrastructure as Code and all that.

I have to confess that this deployment was completely unlike show it should have been done: one off installation, functionality added over time, no backups.

And as with all SD cards over time, at one point it failed to boot. The kernel was oopsing in an endless loop. It was a wonder it worked for so long. 

At this point I had some experience with ESPHome and had a few ESP8266/ESP32s lying around, so I've figured I can do all what the RPi used to do with an ESP. 

For those software folks who have not yet jumped on the ESP bandwagon, here's a short introduction:

  • RISC V based CPU/MCU from single core 26Mhz to dual core 240Mhz.
  • up to 8MB of RAM (on ESP32)
  • up to 32MB flash
  • ~15 GPIO pins
  • on-board WiFi and Bluetooth Low Energy (ESP32 only) with a PCB antenna

All this for the size of a coin. Complete boards, ready to use with an USB connector for something like $5-8 on AliExpress for a beefy ESP32 board, but you can get a simpler one for $2-3 on the same site. Be sure to order a few at a time, you will need it. :)

You can program these using their native SDK or Arduino, but there are also complete firmware packages, which you can configure instead of having to code the functionality you want to achieve. Such firmware package is Tasmota or ESPEasy but for my use-cases ESPHome seems to be the best solution.

The ESPHome project aims to be the IoT counterpart of Homeassistant, e.g. its integration is the best out there and the configuration model plus the syntax is very similar to how you do things in Homeassistant.

With all of this said, I set out to configure the 8 temperature sensors, the 4 relays and the boiler monitoring functionality using a D1 mini board.

Installing esphome

ESPHome is written in Python, so it's a pip install away. I installed mine as a user within my home directory. But you can also set up a virtualenv or just use a docker image with all the necessary things installed for you.

$ pip install esphome

Creating the initial configuration

A configuration for ESPHome is a YAML file. You can create such a file from scratch, but it's always easier using the esphome wizard command, which will ask a few questions and give you a nice and simple .yml file to work on.

This initial config would give you a good starting point, once deployed to a board, it will try to connect to a WiFi network automatically (or automatically provide a WiFi Access Point as a fallback if it can't connect). Once connected the board can be updated remotely (over-the-air updates) and can also be autodetected by Homeassistant.

At this point the board does not do much interesting stuff, apart from being accessible and upgradeable over-the-air.

Adding temperature sensors

The temperature sensors I was using are W1 (or onewire) devices, which was originally specified by Dallas, thus ESPHome refers to this bus as "dallas". To connect up these sensors, I need to dedicate one GPIO pin as the data pin for the bus. This can be achieved by adding this to the ESPHome configuration:

dallas:
  - pin: 13


With that present I can create sensors that attach to this bus:

sensor:
  - platform: dallas
    name: "Lakás Primer Vissza"
    address: 0x8601191F191D2028
    resolution: 12
    filters:
      - delta: 0.1


You can use index or address based identification of sensors, I am using the address here to be sure I know which sensor is which. You can see that I've requested 12bit resolution (slower but more accurate) and that only changes over 0.1C are reported to Homeassistant. You can find more details in ESPHome's documentation.

Adding relays

Relays were simpler as I could dedicate a GPIO pin for each of the relays I wanted to control.

switch:
  - platform: gpio
    name: "Melegvíz Keringetés"
    pin:
      number: 5
      inverted: true

This tells ESPHome to expose a switch to Homeassistant, which when activated would flip GPIO #5, so that when the switch is on, the GPIO pin would be raised to HIGH and LOW otherwise (note the inverted attribute).

I've listed each of my relays in this manner.

Buderus bus monitoring

This was the most involved function, as the Raspberry Pi I used previously was running a Perl script to decode the bytes sniffed from the Buderus bus. I obviously could not deploy the Perl script on the D1 Mini. The solution here was a serial to TCP/IP bridge where the serial port communication is directly mirrored to a TCP connection. I then modified the Perl script to connect using TCP instead of opening a local serial port, then I've deployed it on my NAS running Linux.

For the serial bridge, I've used a 3rd party extension of ESPHome, like this:

external_components:
  - source: github://bazsi/esphome-stream-server

uart:
   id: uart_buderus
   baud_rate: 1200
   tx_pin: 16
   rx_pin: 14
   # add further configuration for the UART here

stream_server:
   uart_id: uart_buderus
   port: 6638

You can see that I've referenced the 3rd party component using "external_components" and I've even forked the esphome-stream-server repository as I had a compilation issue back then, which I am pretty sure is fixed by now.

With that, the Perl script happily running on a more resourceful Linux server would connect to port 6638 on the D1 mini where it will get the sniffed Buderus communication.

Deploying it all

The deployment of an ESPHome configuration is really easy. Just plug in the ESP board to your computer running ESPHome and run "esphome upload". That's it. Or if you prefer GUIs, just start "esphome dashboard" and upload using that interface. You can even monitor running boards over TCP/IP. Any such boards will be automatically discovered. You can tail their logs or upgrade them using a newer version of the firmware over-the-air.

Homeassistant integration

Now this is even easier. Once the board is running, Homeassistant would discover it on its "Integrations" screen. With a few clicks, any switches/sensors/whatever you configured in ESPHome will become available in Homeassistant.

Reproducibility

If this all would not be convincing enough, the YAML file that encapsulates the entire firmware configuration can be added to my home-automation git repository. Should the D1 mini ever fail, I can replace it, either the same kind or a newer one, without a hitch.


Comments

dragos said…
Hi there,
Interesting things I've been reading on your blog, being the owner of a Buderus boiler with a Logamatic 4211 control. I recently started my endeavor to find a communication solution with the boiler. I began with https://github.com/flyingflo/heat_can together with https://github.com/flyingflo/logamatic, but didn't manage to go anywhere. I'm stuck at the very beginning and I suppose I'm missing some of the basics of how this project was implemented. I was aware of Peter Holzleitner's solution, but I thought that communicating via the native bus would be a more elegant solution. Failing to make it work brought me back to Peter Holzleitner. I ordered a ready-made level shifter and while waiting for it to arrive I am struggling with the software. My programming skills are very rusty to say the least, having seldom been used during the past two decades. Not having a clue of Perl, I am currently trying to understand it and translate it to Python with the help of chatGPT. :)) I like the idea of using the ESP32 for exposing the serial over the wifi and will probably tried to replicate it. I use a few ESP32 devices with ESPhome for various home automation tasks, therefore I am optimistic about being able to replicate it. I am more concerned about the Perl software (and my Python translation), therefore I took a chance in contacting to you to ask if you would care to share anything about your specific implementation. I am mainly interested in the software, but also the wiring and other details you may consider to be relevant. Thank you in advance!

Popular posts from this blog

syslog-ng fun with performance

I like christmas for a number of reasons: in addition to the traditional "meet and have fun with your family", eat lots of delicious food and so on, I like it because this is the season of the year when I have some time to do whatever I feel like. This year I felt like doing some syslog-ng performance analysis. After reading Ulrich Deppert's series about stuff "What every programmer should know about memory" on LWN, I thought I'm more than prepared to improve syslog-ng performance. Before going any further, I'd recommend this reading to any programmer, it's a bit long but every second reading it is worth it. As you need to measure performance in order to improve it, I wrote a tool called "loggen". This program generates messages messages at a user-specifyable rate. Apart from the git repository you can get this tool from the latest syslog-ng snapshots. Loggen supports TCP, UDP and UNIX domain sockets, so really almost everything can be me

syslog-ng roadmap 2.1 & 2.2

We had a meeting on the syslog-ng roadmap today where we decided some important things, and I thought I'd use this channel to tell you about it. The Open Source Edition will see a 2.1 release incorporating all core changes currently in the Premium Edition and additionally the SQL destination driver. We are going to start development on the 2.2 PE features, but some of those will also be incorporated in the open source version: support for the latest work of IETF syslog protocols unique sequence numbering for messages support for parsing message contents Previously syslog-ng followed the odd/even version numbering to denote development/stable releases. I'm going to abandon this numbering now: the next syslog-ng OSE release is going to have a 2.1 version number and will basically come out with tested code changes only. The current feature set in PE were developed in a closed manner and I don't want to repeat this mistake. The features that were decided to be part of the Open

syslog-ng 3.0 and SNMP traps

Last time I've written about how syslog-ng is able to change message contents. I thought it'd be useful to give you a more practical example, instead of a generic description. It is quite common to convert SNMP traps to syslog messages. The easiest implementation is to run snmptrapd and have it create a log message based on the trap. There's a small issue though: snmptrapd uses the UNIX syslog() API, and as such it is not able to propagate the originating host of the SNMP trap to the hostname portion of the syslog message. This means that all traps are logged as messages coming from the host running snmptrapd, and the hostname information is part of the message payload. Of course it'd be much easier to process syslog messages, if this were not the case. A solution would be to patch snmptrapd to send complete syslog frames, but that would require changing snmptrapd source. The alternative is to use the new parse and rewrite features of syslog-ng 3.0. First, you need to f