Over the past few years I've seen many implementations of automatic bathroom fans, ranging from very complex (and probably not needed) to overly simplistic that seem to just not be good. I'm not sure if my implementation warrants being shared, but this is my absolute most reliable automation in my house, bar none. I set it up two years ago and have never had to reset, restart, or fix this. It's bulletproof and turns on and off at perfect times.
My approach to automatic bathroom fans are simple, if the humidity in a bathroom is higher than the average humidity of that floor (excluding bathroom), the fan should turn on until it equalizes, with some swing.



Sensors used: a smart relay (Sonoff), a temperature & humidity sensor (Aqara), and a button for manual fan control (Aqara). Any sensors will work but I found this combo extremely reliable.
I'm using zigbee devices to perform all of this, specifically the above sensors. The relay is wired inside of the bathroom fan box, and an additional button is mounted near the toilet, in case you dropped a steamer and need the fan for smell and not humidity.
Here are some more specific details:
Generic Hygrostat
Home Assistant has a cool feature called Generic Hygrostat, analagous to Generic Thermostats, which let you combine switches with humidity sensors to create a hygrostat. All of the control for turning the fan on/off is based around this.


Generic Hygrostat and settings used for this setup. Set it to dehumidifier and put a dry tolerance to allow for a little swing, like a thermostat.
Note: If you are using the same Sonoff relay I am using, you have to fix the registration of the device to a switch, instead of its default as a light. Example below:
zha:
device_config:
b4:35:22:ff:fe:fb:e5:43-1:
type: 'switch'
This goes in configuration.yaml
and you can pull the device MAC from ZHA
inside of Home Assistant. There's probably a similar way to do this for Zigbee2MQTT
.
Now, control over the fan is done through this hygrostat instead of manually having to flip the device switch. You can put a set point and have it automatically turn on/off, just like a thermostat. Elegant!
Auto On/Off
Now that the hygrostat is created. I create a grouped sensor called Home Humidity
that combines all humidity sensors on that floor (could also be the entire house) without that bathroom fan in the group. You can find this in Helpers > Combine the State of Several Sensors
and add them all with arithmetic mean.
Below is an automation that updates the set point of the hygrostat we created everytime the state of the grouped sensor changes. It will auto update and track the bathroom hygrostat to the rest of the house:
alias: Upstairs Bathroom Hygrostat Temp Set
description: ""
mode: single
triggers:
- entity_id:
- sensor.home_humidity
trigger: state
conditions: []
actions:
- action: humidifier.set_humidity
metadata: {}
data:
humidity: "{{ float(states('sensor.home_humidity')) + float(15) }}"
target:
entity_id: humidifier.upstairs_bathroom_hygrostat
You may notice the + float(15)
, which will add 15% humidity to the grouped sensor. This is how the fan will turn on automatically when the shower is on, or anything else causing humidity. Any time the humidity in the bathroom exceeds the house humidity + 15%, the fan kicks on and it will automatically kick off once humidity drops.
You can sometimes get away with just having a static humidity target set, 80%
for example, but where I live, in cold winter months, humidity can drop very low inside the house. I found it better to follow the average and turn the fan on when it goes above that average.
Thats it! This setup is bulletproof, running for years without issue. Hope it's useful.