ESPHome Controlled Air Freshener

I use Home Assistant to control my whole home, from the simple things like light switches and lights, to the more complex things like curtains and door locks.

Something we did when our daughter was younger, but have kept around because it's so useful, is a set of automations in our downstairs toilet (affectionately named The Cloakroom). The automations start with a motion sensor (for now, just a battery powered PIR sensor), which tells us someone has entered the cloakroom. That triggers the light to turn on, and starts a 10 minute timer within Home Assistant to turn it off. Each time motion is detected by the PIR sensor (which resets every 3 minutes), that timer resets. If for some reason the person is in the cloakroom and sat still for long enough that the light goes out, we have a button on the wall which turns it back on. If the light is already on, however, pressing the same button triggers a voice note to be broadcast in the living room and kitchen to let us know that they need assistance.

What we noticed though was that our daughter would occationally forget to flush. Without the ability to auto-flush, or at the moment to even detect whether a flush has occured, we set up a timed air freshener. The problem with the air freshener though, is that it triggers no matter whether the room has been used or not, and in such a small space the fragrance can become quite pungent when entering for the first time in a couple of days.

This is where the thought occured to integrate the air freshener into Home Assistant, by way of ESPHome.

I tried inspecting the original board within the air freshener, but it wasn't obvious through probing around how to both stop the timed trigger, and enable an on-demand trigger. After a couple of evenings poking and prodding the board to no avail, I gave up on that avenue.

Browsing AliExpress to see what random things were on offer I quickly noticed a USB-C powered board which had the same disk-shaped atomiser. After a little digging I found a ESP32/Arduino compatible board.

I have a small stock of various ESP32 boards, and decided on the small ESP32-C3 Zero for this project. I chose one without pre-soldered headers as I only needed 3 pins, and wanted to use right-angle headers to keep it compact. I soldered a row of 5 pins (I couldn't be bothered to snip any off) to the 5V, ground, 3.3V, and GPIO 0 & 1 pins.

Adding it into ESPHome on Home Assistant I then used the YAML below to make the device function:

esp32:
  board: esp32-c3-devkitm-1
  variant: esp32c3

# Don't forget to include the ESPHome basics, like ota, api, etc.

light:
  - platform: esp32_rmt_led_strip
    id: status_led
    pin: GPIO10
    num_leds: 1
    rgb_order: GRB
    chipset: WS2812
    name: "Onboard LED"

output:
  - platform: gpio
    pin: GPIO32
    id: humidifier_gpio

number:
  - platform: template
    name: "Humidifier Run Duration"
    id: run_duration
    min_value: 1
    max_value: 10
    step: 1
    initial_value: 3
    unit_of_measurement: "s"
    optimistic: true
    restore_value: true

button:
  - platform: template
    name: "Trigger Humidifier"
    icon: "mdi:spray"
    on_press:
      - script.execute: run_cycle

script:
  - id: run_cycle
    mode: restart
    then:
      - light.turn_on:
          id: status_led
          brightness: 50%
          red: 100%
          green: 0%
          blue: 0%
      
      - output.turn_on: humidifier_gpio
      - delay: !lambda "return id(run_duration).state * 1000;"
      - output.turn_off: humidifier_gpio

      - light.turn_off: status_led

I've connected the device to an Anker powerbank and double-tapped the power button to enable trickle-charge mode, but I'm going to try and tidy it all up at some point and either use the 3xAA batteries the original air freshener housing has, or fit a LiPo in the same space.

For now though it works, and with an automation to trigger a spray after the light's been off for a couple of minutes, that should keep the cloakroom smelling nice.