If you don’t care about the log statement this whole block of code could be reduced to:
PresenceTimer?.cancel
PresenceTimer = null
Use the method instead of the action where ever possible.
anyPhonesPresent.sendCommand(ON)
This might have been your problem. It is possible (not certain) that if you wrote this as a logDebug and the logging was set to Info level this line may not have executed since the Rules Engine knows that nothing would ever be done with the log statement.
It is a good practice to not mix your side effects (i.e. the rescheduling of the timer) with your logging anyway and if what I’m guessing is what happened, this only reinforces why that is a bad idea.
val rval = PresenceTimer.reschedule(now.plusMinutes(10))
logInfo(name, "reschedule:retVal=" + rval)
You can get rid of a lot more of this code by using Design Pattern: Expire Binding Based Timers which would turn your rules into:
rule "Phones Present"
when
Item presenceDevices changed
then
val name = "PhonesPresent"
logInfo(name, "presenceDevices = " + presenceDevices.state) // semicolon is not needed
if(presenceDevices.state == ON) { // only use === when one of the operands are null
if(PresenceTimer.state == ON) PresenceTimer.postUpdate(OFF) // Cancel Expire based timer
if(anyPhonesPresent.state != ON) anyPhonesPresent.sendCommand(ON)
}
else {
logInfo(name, "Setting timer...")
PresenceTimer.sendCommand(ON) // schedule/reschedule Expire based timer
}
end
// Expire timer expired
rule "Presence Timer"
when
Item PresenceTimer received command OFF
then
logInfo("PresenceTimer", "To: present")
anyPhonesPresent.sendCommand(OFF)
end