How to Cancel a Timer?

Currently running OH4.3.5 on RPi 4 configured with Main UI

I have a Blockly timer that closes the garage door after it has been open for 5 minutes, unless someone closes it before that.
I’d like to add a way to cancel the timer anytime before it closes the door.

My Blockly looks like this

The rule code is

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: ZWave_Node_066_ZSE43_Tilt__Left_Door_State
      state: OPEN
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      blockSource: <xml xmlns="https://developers.google.com/blockly/xml"><block
        type="oh_timer" id="Et]Oz,~@Z{eQ~39[E9IY" x="539" y="225"><field
        name="delayUnits">plusMinutes</field><field
        name="cache">shared</field><value name="delay"><shadow
        type="math_number" id="FlFIKXnGS;S5Gwzdes1a"><field
        name="NUM">10</field></shadow><block type="math_number"
        id="EV|Mqx]a*VY-+b:?~;@y"><field
        name="NUM">5</field></block></value><value name="timerName"><shadow
        type="text" id="nubay[p=ERQRvy%mW98H"><field
        name="TEXT">MyTimer</field></shadow><block type="text"
        id="-1pvW_TMF%,j.OaVHMDn"><field
        name="TEXT">LeftGarageTimer</field></block></value><value
        name="context"><shadow type="oh_logic_undefined"
        id="oM.Xe@x6^-kTz_9l=~}P"></shadow></value><statement
        name="timerCode"><block type="controls_if"
        id="E,}q%DSvRdrg5?e*Lo0p"><value name="IF0"><block type="logic_compare"
        id="!P%,5s%)b-^I^JDaG^1a"><field name="OP">EQ</field><value
        name="A"><block type="oh_getitem_state" id="./]1*lFKeu$@*YbmPx@!"><value
        name="itemName"><shadow type="oh_item"
        id="3PyiuX8TXg61EMIlr$jT"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="oh_item"
        id=";b!%,YGNGR])24wFeuxH"><mutation
        itemName="ZWave_Node_066_ZSE43_Tilt__Left_Door_State"
        itemLabel="Status"></mutation><field
        name="itemName">ZWave_Node_066_ZSE43_Tilt__Left_Door_State</field></block></value></block></value><value
        name="B"><block type="text" id="Nbm7VDdR2g-HNx4mBe%9"><field
        name="TEXT">OPEN</field></block></value></block></value><statement
        name="DO0"><block type="oh_event" id="CO;ax.j`0T_bvq-rl=nl"><field
        name="eventType">sendCommand</field><value name="value"><shadow
        type="text" id="=Hfp1*nmFgtQzFKgFY:n"><field
        name="TEXT">value</field></shadow><block type="text"
        id="0A;g^k@?:Iv?3d;eMA`g"><field
        name="TEXT">ON</field></block></value><value name="itemName"><shadow
        type="oh_item" id="I#)v2Lo[Dj%0v*g2*6G{"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="oh_item"
        id="tERRO/)^AjY=XKM-A|w*"><mutation
        itemName="ZWave_Node_074_Garage_Door_Control_Switch_1" itemLabel="Left
        Door"></mutation><field
        name="itemName">ZWave_Node_074_Garage_Door_Control_Switch_1</field></block></value></block></statement></block></statement></block></xml>
      type: application/javascript
      script: >
        if (cache.shared.exists('LeftGarageTimer') === false ||
        cache.shared.get('LeftGarageTimer').hasTerminated()) {
          cache.shared.put('LeftGarageTimer', actions.ScriptExecution.createTimer('LeftGarageTimer', time.ZonedDateTime.now().plusMinutes(5), function (timer_context) {
            if (items.getItem('ZWave_Node_066_ZSE43_Tilt__Left_Door_State').state == 'OPEN') {
              items.getItem('ZWave_Node_074_Garage_Door_Control_Switch_1').sendCommand('ON');
            }
            }, undefined));
        };
    type: script.ScriptAction



I’ve created a Cancel Timer Switch.
The question is where should the Cancel Timer Block go?

Not sure if this would work, but there is a “cancel private timer” block in the Timers and Delays section that you use in a second rule that triggers off your cancel timer switch.

That’s a valid approach but I was thinking there should be a more elegant way that includes the Cancel Timer block into the Timer rule.

There’s an example in the Docs that has it all in one rule but I was struggling to apply it to my situation.

Maybe you don’t need to cancel the timer, just make the action conditional.


Then put an expiration timer on the cancel switch of about 5 minutes.

If you don’t use @kjknauss’s suggestion to use a conditional inside the Timer, you need to use the conditional outside the timer and use the cancel timer block.

The code inside a timer doesn’t run until the timer reaches it’s scheduled time, so something outside the timer needs to cancel it.

Your rule will trigger when the state of the garage door changes.

You’ll have an if to see if the change was an OPEN or CLOSED event.

If it’s an OPEN event, create the timer.

If it’s a CLOSED event, cancel the timer.

The code inside a timer doesn’t run until the timer reaches it’s scheduled time, so something outside the timer needs to cancel it.

That was my thought…thanks for clarifying.

A second rule triggered by the Cancel switch seems like the simplest solution.

Note to use a second rule for this you must use a shared timer, not a private timer. A private timer can only be accessed by the script that created it.

Yes, I was aware of that.

I created the second rule and everything works as expected.

Thanks!