# Design Pattern: Recursive Timers

**URL:** <https://community.openhab.org/t/design-pattern-recursive-timers/17114>\
**Category:** Tutorials & Examples\
**Tags:** designpattern\
**Created:** [November 22, 2016, 9:15pm UTC](https://community.openhab.org/t/design-pattern-recursive-timers/17114 "2016-11-22T21:15:24Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 27, 2017, 2:10am UTC](https://community.openhab.org/t/design-pattern-recursive-timers/17114/2 "2017-01-27T02:10:55Z")

</div>

(I think there are still a few typos in above)

I’ve been playing with this recursive timer, to combine it with some countdown ideas stolen from here

> [@Timer progress/remaining in sitemap](https://community.openhab.org/t/timer-progress-remaining-in-sitemap/7381/6):
>
> Thanks for this. Hacky or not, it is very useful. Though I did opt for now.plusMinutes to save a few processes. I now use it with a selection menu, where the value of the selection is used as the timer. I signed up to the crowdsourced wifi service [fon](https://fon.com/) which allows you to use any Fon hotspot around the world for free. Providing you share a little bit of yours. They give you a little router to plug into your own. All secured from your local network. I explicitly asked about where the traffic (…

**My objective** , to create a countdown timer for e.g. motion activated lights. Must be able to reschedule for that purpose. Cannot use “expire binding” methods as timer durations are variable depending on context – home/away etc.  
Ordinary so far, but I also wanted to be able to inspect remaining time from rules for smarter behaviour - e.g. as my light zones may be triggered from different causes for different durations, I want a rule to able to see if an existing timer is longer or shorter than what is now proposed.

Using recursion, we create a one-minute timer that decrements a Number Item. Lambdas, closures, recursion - all gives me headaches! Eventually I figured out my major obstacle was that the actual timer in Rik’s version is anonymous, and so could not be cancelled or rescheduled from a rule. The uncancelled timer contains a snapshot of the ‘old’ counter, so trying to simply update counter value fails.  
The trick is put _both_ the recursive function in a hashmap (so it can call itself) and the timer it spawns into another (where rules can cancel it).

Here is my example for OH1;

**test items**

```csv
Number my_countdown "minutes counter [%s min]" 
Switch test_countdown "Simulate trigger or cancel"

```

you can put those on a sitemap to play

**rules file**

```php
// an array of timers for each lighting zone
val Map<String, Timer> lightTimers = newHashMap
// an array of countdown functions, a workaround for rescheduling
val Map<String, Object> lightTickers = newHashMap

// lambda function for recursive countdown timers i.e.
// a timer that can re-call itself upon expiry for a periodic effect
// param1 = Number Item counter
// param2 = the timer map array (so it can be cancelled)
// param3 = the function array, needed for recursion
// param4 = recursive function itself
// We host it in a Map because the Timer will not have access to change the global var itself
// but can make a call on the Map if we pass it into the lambda to update the contents.

val org.eclipse.xtext.xbase.lib.Functions$Function4 doCountdown = [
	NumberItem myDelay,
	Map<String, Timer> timersMap,
	Map<String, Object> functionMap,
	org.eclipse.xtext.xbase.lib.Functions$Function4 makeTicker |
		val int ddelay = (myDelay.state as DecimalType).intValue
		timersMap.put(myDelay.name, null) // destruct old
		if(ddelay > 0) {
			timersMap.put(myDelay.name, createTimer(now.plusMinutes(1)) [ |
				myDelay.postUpdate(ddelay-1)
				functionMap.put(myDelay.name, makeTicker.apply(myDelay, timersMap, functionMap, makeTicker))
                                ]
			)
		} else {
			functionMap.put(myDelay.name, null)
			logInfo("testing", "countdown complete")
                            // if you want to update Items here, you will need to pass those into the lambda as well
                            // I chose instead to have rules triggered from counter Item changing to 0
		}
]

rule "test trigger"
	when
		Item test_countdown changed
	then
		if (test_countdown.state == ON) {
			my_countdown.sendCommand(5)
		} else {
			my_countdown.sendCommand(0)
		}
end

// send an integer minute count for start or reschedule, or 0 for abort

rule "Timeout setting"
	when
		Item my_countdown received command
	then
		val oldTimer = lightTimers.get(my_countdown.name)
		if (oldTimer != null) {
			logInfo("testing", "cancel existing ticker") 
			oldTimer.cancel
			lightTimers.put(my_countdown.name, null)
			lightTickers.put(my_countdown.name, null)
		}
		if (my_countdown.state > 0) {
			logInfo("testing", "ticker startup")
			lightTickers.put(my_countdown.name, doCountdown.apply(my_countdown, lightTimers, lightTickers, doCountdown))
		} else {
			logInfo("testing", "countdown zeroed")
		} 
end

```

I do not think this is 100% bombproof - at the least there is a chance that testing for a null timer in the rule could happen in the instant where a previous function is between ‘ticks’ i.e. nulled the last timer and just about to set a new one. Not likely though; the result could be two countdown sequences fighting over one counter, but that should be a smaller problem than it sounds. Eventually it reaches zero!

---

_[View the full topic](https://community.openhab.org/t/design-pattern-recursive-timers/17114)._
