Faninator
📁 Source code: View on GitHub →
Technology can solve all kinds of problems - especially when one is fearlessly willing to step over the live of what would usually be a reasonable level of effort for execution. In other words… overengineer!
The problem: The humidity in the bathroom would get too high
The solution: An overengineered humidity sensor!
This over-engineered solution was mostly born from the fact that my darling daughter would take her shower in temperatures roughly equivalent to the surface of the sun but forget to turn on the vent. The funny part is that this actually led to three or four triggers of the smoke alarm in the upstairs hall.
At the time, I was mostly just using Insteon (prior to their abrupt 2022 shutdown) and hadn’t convinced myself to bite off the work of standing up and managing a Home Assistant installation when the Insteon app and services were working well for me. Had I known then what I know now, I would’ve just popped in to the Home Assistant ecosystem since there are plenty of cheap humidity sensors that integrated well (even back in 2021) and the rest_command automation integration allows sending stuff to arbitrary HTTP endpoints.
None the less, the requirements for this thing were pretty straight forward:
- Live life on battery power!
- Capture the temperature and humidity
- Turn the fan on when the level is too high
- Report the values
The requirement for battery was driven by the fact that there was nowhere nearby in the bathroom to plug the device in - and even if there had been, a long cord is ugly. This created an interesting constraint for the project. Thankfully, the ESP8266 supports a deep sleep mode which nearly shuts the device down and draws only tiny amounts of current. Being the lazy type, I bought the biggest LiPo battery within the budget (6500mAH) so it could go something like a year without needing to be charged. Mating the board and battery with the venerable DHT22 temperature/humidity sensor completed the critical hardware layout. To make recharging easier, I added a TP4056-based charging child board.
With the hardware pretty well figured out, I still had the issue of firmware. I didn’t want to sacrifice the ability to record the data longer term, but I knew easily enough that I couldn’t rely on this device itself to record its own history. The solution I went with was to leverage my existing Prometheus deployment that’s been running in the homelab since… ever. As you may know off the bat, Prometheus uses a scraping model where it will reach out to fetch metrics on an interval. Being battery operated and sleeping most of the time, this device wouldn’t fit that model - so I tossed the pushgateway into my deployment that would allow the faninator to wake up, gather values, determine if it should stop/start the fan, and then push the observed values off for later collection.
It all worked quite well - and we never had another false alarm from the smoke detector again! The faninator continued service for a few years until I ended up replacing it. When Insteon went belly up in the most offensive way possible I ended up switching to a primarily Z-Wave smart home and the brilliant Home Assistant project. This allowed me to pick any sensor that could integrate with HASS to control the vent switch. For those curious, I picked up a Zooz ZSE40 4-in-1 sensor to control the Zooz ZEN71 on/off switch.
The software-side of the replacement consists of a Home Assistant Threshold sensor which, when “on” starts the fan, waits for the threshold to turn “off”, then waits for motion to clear before stopping the fan.

