Jython timer cancel and hasTerminated

I have a motion sensor that sends both ON and OFF. In the case where an ON is sent, and the motion timer is running, I want to cancel the timer. So far, so good. When the motion detector sees an OFF later, it should start the timer again. But the code below reschedules the timer.

If I cancel a timer, should the hasTerminated() return true? I thought it would, but maybe not? The code below works because the reschedule starts the timer again, but this is not the path that I was expecting.

I’ve run HallMotionTimer.cancel(), so why doesn’t this line return true?:

if HallMotionTimer is None or HallMotionTimer.hasTerminated():

full code below:

HallMotionTimer = None

@rule("Motion Detection ON", description="actions for motion detection", tags=[])
@when("Item HallMotion changed to ON")
def MotionDetectedOn(event):
    # away or vaction motion
    global HallMotionTimer
    if items["HouseMode"] == DecimalType(1):
        MotionDetectedOn.log.info("Motion detected by {}".format(event.itemName))
        if not items["PuckHold"] == NULL:
            events.sendCommand("PuckString", "PUCK_ON")
    if HallMotionTimer is not None and not HallMotionTimer.hasTerminated():
        MotionDetectedOn.log.info("cancelling hall motion off timer")

@rule("Motion Detection OFF", description="actions for motion detection", tags=[])
@when("Item HallMotion changed to OFF")
def MotionDetectedOff(event):
    global HallMotionTimer
    MotionDetectedOff.log.info("Motion not detected by {}".format(event.itemName))
    if HallMotionTimer is None or HallMotionTimer.hasTerminated():
        MotionDetectedOff.log.info("Motion not detected by {}, off timer started".format(event.itemName))
        HallMotionTimer = ScriptExecution.createTimer(DateTime.now().plusMinutes(3),
                lambda: events.sendCommand("PuckString", "PUCK_OFF"))
        MotionDetectedOff.log.info("Puck off timer reschedule")

IIRC, hasTerminated will only return True if the timer went off and the lambda was executed. If you cancel the timer before it ran, I think hasTerminated will continue to return False. I could be missremembering though and am not in a place where I can create a test to verify.

NOTE: this is how Timers work and really has nothing to do with Jython. The same behavior will occur in JavaScript or Rules DSL.

So you probably need to reset HallMotionTimer to None right after you cancel it.