Simple Bathroom Fan

I looked and I can’t find anything that fits my needs. I am looking for a simple smart app that if the bathroom light is on for more than say 3 min, it turns the exhaust fan on. On the flip of that, if the light has been off for more than 5 min, turn the fan off. Does anyone know if this exist? Seems simple, I was surprised I could not find something. Every thing I found was based on Humidity and or motion.


Well… there are a lot of “simple” SmartApp ideas that haven’t been implemented just because the idea hasn’t been thought of!

For better or worse, SmartThings doesn’t have the resources or inclination to program every possible combination (though they are working on a more flexible / friendly “Rules Engine / Wizard” that will perhaps make it easier to implement ideas-requirements such as yours without requiring custom Groovy programming…).

The Platform is open and “easy enough” for many folks to write and share a SmartApp to do what you suggest, though. Usually free, just for asking!

One potential challenge, though, is that on/off detection of a light controlled by a lightswitch is not necessarily reported to SmartThings (lookup “Lutron Patent” via a Search :mag: – in short, non-licensed light brands are not permitted to send report their status change). I think SmartThings eventually (?) realizes the light is on via periodic refresh polling, but that will affect the reliability of the “3 minutes on” / “5 minutes off” portion of your specification.

Given @tgauchat’s caution about how quickly your switch turning on or off will be visible by ST, here is the code that does what you said. If the time is set to zero for either time setting, then the fan switch will turn on or off immediately with the other switch.


     *  Bath Fan On/Off
     *  Copyright 2015 Bruce Ravenel
     *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
     *  in compliance with the License. You may obtain a copy of the License at:
     *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
     *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
     *  for the specific language governing permissions and limitations under the License.
        name: "Bath Fan On/Off",
        namespace: "bravenel",
        author: "Bruce Ravenel",
        description: "Turn bath fan on after some period of time",
        category: "My Apps",
        iconUrl: "",
        iconX2Url: "",
        iconX3Url: "")
    preferences {
    	section("When this switch is turned on...") {
    		input "switch1", "capability.switch", title: "Which?", required: true, multiple: false
        section("This many minutes later...") {
        	input "minutesOn", "number", title: "How many?", required: true, multiple: false
        section("Then turn on this fan switch...") {
        	input "fanSwitch", "capability.switch", title: "Which?", required: true, multiple: false
        section("And then turn it off this many minutes...") {
        	input "minutesOff", "number", title: "after the switch turns off", required: true, multiple: false
    def installed() {
    	log.debug "Installed with settings: ${settings}"
    def updated() {
    	log.debug "Updated with settings: ${settings}"
def initialize() {
    subscribe(switch1, "switch.on", switchOnHandler)
    subscribe(switch1, "", switchOffHandler)

    state.fanOn = false

def switchOnHandler(evt) {
    if(minutesOn > 0) runIn(minutesOn*60, fanToggle) else fanToggle()

def switchOffHandler(evt) {
    if(minutesOff > 0) runIn(minutesOff*60, fanToggle) else fanToggle()

def fanToggle() {
    if(state.fanOn) else fanSwitch.on()
    state.fanOn = !state.fanOn
1 Like

Thanks for the code, Bruce!

Sanity check might be required, maybe?, so as not to make sure not to turn the fan on after it has been turned off … i.e., unschedule the switchOnHandler in the fanOff() method.

You can only get to fanOff() by going through switchOffHandler(), which does the unschedule(). So I don’t think there’s any way something can still be scheduled when fanOff() runs. Unless you’re talking about someone actually turning the fan off by its switch, or on for that matter. I just took @LadySapphy’s directions.

Doh! You’re right.

I neglected to notice that unschedule() without parameters would take care of that situation.

Yeah, it wipes everything.

Funny thing about this particular app is that it’s one where the lag in z-wave switches (non instant reporting ones) probably doesn’t matter very much. She wants the fan to come on after 3 minutes. I doubt she’ll care if it’s 3:20. Same with turning it off.

1 Like

Does runIn(0, method) run the method() right away, or does it fail?


Just tested it and it worked just as I wanted it too.


What you should do is read the code and figure out how it works. It’s a very simple app. You’d be amazed how easy it is to do things like this to customize your setup.

As far as the Lutron patent. I have not seen that issue with the Levitons I use. 2-3 second lag on average, I have seen a few 30 second lag, but all of my Smarthings were running at the pond scum when I seen that.

1 Like

I code in C# and Powershell in my day job. I will look at the code as well and learn from it. With the kids and spring sports, time is at a premium right now.

1 Like

Also, think about putting a keypad or mini remote to use in ST to get around the Lutron instant reporting issue.

keypad or mini remote press, turns switch on/off and can trigger other automation. May not be the coolest solution, but beats having to replace the switch / dimmer to something that can report in instantly.

1 Like

I modified the code above to get rid of unschedule(), which is a known bad actor. I was using it so a pending off would not continue after an intervening on. I used a different mechanism. By turning the fan on/off logic into a toggle (which it was anyway), the scheduling of a new turn on or turn off event in the future (from flipping the switch), will replace any pending fan on/off.

1 Like

Thanks!! I updated the code on mine, I will let you know if I have any issues.


First, thank you, Bruce!

I am using your Simple Bathroom Fan code, and it is almost perfect for me. The imperfection (for me) is that, when the light switch is toggled on while the fan is already running, the fan shuts off. (This happens when one person leaves the bathroom and turns off the light, and then another person immediately enters the bathroom and turns the light back on.) Is there a bit of code that will reset the program whenever the light is turned on so, effectively, the fan will remain running for second person turning on the switch and continue for the (full) preferred time after the second person turns off the switch?

I am not a programmer, but I am capable of tweaking code when given half-decent directions.

Thank you!

I think Bruce left the community. I replaced this code with Rule Machine, and then Replace Rule Machine with CoRE. I recommend you try CoRE.