Fresh air with ESP8266 and Home Assistant (part 2)

Building a MQTT controller for HRV: the software.
 2020-04-26

This is the second post about hooking up Heat Recovery Ventilator to Home Assistant. Previously, I wrote about the hardware aspect and here I’ll discuss the software that is needed to make it all work.

ESP8266 Firmware

There are several IoT frameworks available for ESP8266. I’ve decided to build my solution on top of Homie for ESP8266.

Homie is a thin and simple MQTT convention for the IoT, it integrates very well with Home Assistant and supports advanced features like initial setup of devices and OTA firmware updates. Homie implementation for ESP8266 is well-designed and is a pleasure to work with.

I published the HRV controller firmware I wrote for on Github. My goals were:

  • Expose an easy-to-use MQTT interface for HRV.
  • Provide means to manually control the HRV in case my Home Automation system is down.
  • Provide a visual indication of the currently active mode, and the device health in general.

MQTT interface

I implemented handling of just one command topic, hrv-control/hrv/schedule/set, which controls the mode of operation. Publishing one the of following strings to this topic changes the mode:

  • off - HRV is turned off.
  • 10_50 - HRV is turned on for 10 minutes, then turned off for 50 minutes (low fan speed).
  • 20_40 - HRV is turned on for 20 minutes, then turned off for 40 minutes (low fan speed).
  • low - Constant-on, low fan speed operation.
  • high - Constant-on, high fan speed operation.

Current operation mode and fan speed are published to these topics:

  • hrv-control/hrv/schedule - currently active schedule (same values as above).
  • hrv-control/hrv/status - short human-readable status: OFF, 10 / 50, 20 / 40, LOW, HIGH.
  • hrv-control/hrv/text - long human-readable status. Example: HRV is on 10/50 schedule, fan is off now.
  • hrv-control/hrv/fan - current fan mode: off, low, high.

This is of course very bare-bones, but I wanted to implement all the “smarts” in the home automation system, not in the firmware: Home Assistant configuration files or Python code is much easier to change and reason about than the firmware inside ESP8266.

Manual control and indication

The controller has only one LED and one button, so control and indication is a bit spartan, but it does what I need:

LED blinks indicate the currently active schedule:

  • Off mode: turn LED on for 50ms every 3 seconds, just for the indication that the device is functional.
  • 10/50 mode: LED blinks with the 10/60 duty cycle, 0.5 seconds on / 2.5 seconds off.
  • 20/40 mode: LED blinks with the 20/60 duty cycle, 1 second on, 2 seconds off.
  • Low on: LED is mostly on, with 50ms off period every 3 seconds.
  • High on: LED blinks rapidly.

Every short button press triggers a mode change, cycles through all the modes. A long press for more than 5 seconds activates “configuration reset”, so the device could be associated with a new access point, for example. While in this mode, Homie switches the device to AP mode, and it’s as simple as connecting to it with your phone and filling in a web form in a captive portal.

Integrating with Home Assistant

Home Assistant supports a generic MQTT HVAC component, which I could use to connect HRV to Home Assistant. However, the UI does not make sense for HRV: we don’t control or measure temperature, we just change the fan mode. So I used an “input select” and automation to respond to and send commands to MQTT:

input_select:
 hrv:
   name: "HRV Mode"
   options:
     - "off"
     - "10_50"
     - "20_40"
     - "low"
     - "high"
   icon: mdi:air-conditioner

# Set HRV mode selector based on HRV data.
automation:
 - alias: Set HRV Mode Selector
   trigger:
     platform: mqtt
     topic: 'homie/hrv-control/hrv/schedule'
   action:
      service: input_select.select_option
      data_template:
       entity_id: input_select.hrv
       option: '{{ trigger.payload }}'
 
 # HRV mode selector changed. Update HRV
 - alias: HRV Mode Selector Moved
   trigger:
     platform: state
     entity_id: input_select.hrv
   action:
     - service: mqtt.publish
       data_template:
         topic: 'homie/hrv-control/hrv/schedule/set'
         retain: true
         payload: '{{ states.input_select.hrv.state }}'

# HRV state/mode sensors
sensor:
 - name: 'HRV fan state'
   platform: mqtt
   state_topic: 'homie/hrv-control/hrv/fan'
 - name: 'HRV fan mode'
   platform: mqtt
   state_topic: 'homie/hrv-control/hrv/schedule'

As you can see above, it’s just an “input select” to set the mode in the UI, and two automations to bidirectionally bind the “input select” to the HRV MQTT control topics. The two MQTT sensors are just for indication / charting purposes.

Demo

Here’s a short video of the system assembled and how it operates:

What’s next?

The actual automatic control of the HRV is still work in progress. The air quality sensors that I built were not satisfactory, so right now the system is being controlled mostly manually. Once I can reliably monitor CO2 and particulate matter levels, I’ll revisit this idea of fully automatic ventilation control.

See also

Fresh air with ESP8266 and Home Assistant (part 1)

Building a MQTT controller for HRV: the hardware.