My bathroom fan timer looks like this:
Switch Light_GF_Bath // Light switched
Switch Motor_GF_Bath // Fan Switch
Number Motor_GF_Bath_afterrun // How long should the Fan work after switching light off
var long StartTime_Bath = 0
var long runtime_Bath = 0
var long StopTime_Bath = 0
var Timer VentiTimeOn = null
var Timer VentiTimeOff = null
rule "Ventilator Bad"
when
Item Light_GF_Bath received command
then
if(receivedCommand==ON) {
if (Motor_GF_Bath.state==OFF) {
// first ON command, so create a timer to turn the light off again
StopTime_Bath = 0
StartTime_Bath = now.millis
logDebug("Nachlauf","Light ON @ {}", StartTime_Bath)
if (VentiTimeOn!=null) {
VentiTimeOn.cancel
VentiTimeOn = null
}
VentiTimeOn = createTimer(now.plusSeconds(10), [|
sendCommand(Motor_GF_Bath, ON)
])
}
}
else if(receivedCommand==OFF) {
// remove any previously scheduled timer
if(VentiTimeOn!=null) {
logDebug("Nachlauf","Light OFF @ {}", now.millis)
VentiTimeOn.cancel
VentiTimeOn = null
}
logDebug("Nachlauf","Motor_GF_Bath = {}", Motor_GF_Bath.state)
if(Motor_GF_Bath.state==ON) {
runtime_Bath = (now.millis - StartTime_Bath)
logDebug("Nachlauf","runtime_Bath = {} msec", runtime_Bath)
logDebug("Nachlauf","StartTime_Bath = {} ; runtime_Bath = {} msec", StartTime_Bath, runtime_Bath)
if (runtime_Bath > 900000)
Motor_GF_Bath_afterrun.postUpdate(900)
else if (runtime_Bath > 300000)
Motor_GF_Bath_afterrun.postUpdate(300)
else if (runtime_Bath > 120000)
Motor_GF_Bath_afterrun.postUpdate(120)
else
Motor_GF_Bath_afterrun.postUpdate(0)
}
StartTime_Bath = 0
}
end
rule "Nachlauf"
when
Item Motor_GF_Bath_afterrun received update
then
logDebug("Nachlauf","Nachlaufzeit = " + Motor_GF_Bath_afterrun.state.toString + " sec")
sendCommand(Motor_GF_Bath, ON)
var myStop = now.millis + 1000 * (Motor_GF_Bath_afterrun.state as DecimalType).intValue
if (myStop > StopTime_Bath) {
logDebug("Nachlauf","neuer Nachlauf länger als alter Nachlauf")
logDebug("Nachlauf","Stoptime_Bath = {} ; myStop = {}", StopTime_Bath, myStop)
if (VentiTimeOff!=null) {
VentiTimeOff.cancel
VentiTimeOff = null
}
StopTime_Bath = myStop
VentiTimeOff = createTimer(now.plusSeconds((Motor_GF_Bath_afterrun.state as DecimalType).intValue), [|
if (Light_GF_Bath.state==OFF)
sendCommand(Motor_GF_Bath, OFF)
StopTime_Bath = 0
])
}
else {
logDebug("Nachlauf","alter Nachlauf länger als neuer Nachlauf")
logDebug("Nachlauf","Stoptime_Bath = {} ; myStop = {}", StopTime_Bath, myStop)
}
end
I built this rule when starting with openHAB1.0, so I’m pretty sure I could do it better today but the rule works as intended.
If light is switched on longer than two minutes, the fan will stay on two minutes after lights off,
if light was switched on longer than five Minutes, the fan will stay on five Minutes after lights of.
If light was switched on for longer than fifteen Minutes, the fan will stay on fifteen minutes after lights off.
If someone switches the lights on while the fan is running, the scheduled timer is cancelled and the new stop time is calculated in consideration of the old stop time.
Let’s say I was showering for 15 Minutes, leaving the bath and someone enters to wash hands (very likely to last less than two minutes), the fan would stop immediately, but the rule knows of the old timer and schedules the old stop time.