If you are implementing step 3 with a timer that is not how your rule is running. Remember that a Timer doesn’t block. You might be able to put it together as:
- start of script
- do something
- create a timer to wait a certain amount of time
- end of script
Time passes and timer goes off. Inside the timer’s function
5. check an item’s state …
Even without this exception you can’t achieve this with a Timer. If you are trying to use Thread.sleep to wait, well that’s a different problem and that’s never going to work. Messing with the thread is forbidden in GraalVM.
It sounds like what you are really after is a Design Pattern: Looping Timers. That gives you the concept. Here is a partially tested JS Scripting implementation I’m working on.
const {timeUtils} = require('openhab_rules_tools');
/**
* @namespace LoopingTimer
*/
/**
* Implements a looping Timer which is passed a function that is expected to return
* a when supported by timeUtils.toDateTime. The loop will reschedule the timer based
* on that returned when or, if it return null the looping stops.
*/
class LoopingTimer {
/**
* Constructor, creates a logger.
*/
constructor() {
this.logger = log('rules_toools.LoopingTimer');
this.logger.debug("Looping Timer created");
}
/**
* Kicks off the timer loop. Schedules a timer to call func at when
* @param {function} func function to call at when, must return a when to continue the loop or null to stop
* @param {*} when any of the types supported by timeUtils.toDateTime
*/
loop(func, when) {
this.logger.debug('Looping timer - loop called with {}', when);
this.func = func;
if(!when) this.expired();
else {
this.logger.debug('Creating new timer from loop');
this.timer = actions.ScriptExecution.createTimer(
timeUtils.toDateTime(when),
() => this.expired());
}
}
/**
* Called when the timer expires. Calls the passed in function and
* reschedules it based on the returned when value, or ends if null was
* returned.
*/
expired() {
this.logger.debug('expired called');
var when = this.func();
if(when) {
this.logger.debug('Creating new timer in expired')
this.timer = actions.ScriptExecution.createTimer(
timeUtils.toDateTime(when),
() => this.expired());
}
}
/**
* Cancels the timer if it exists and hasn't already terminated.
*/
cancel() {
if(this.timer && !this.hasTerminated()) {
this.timer.cancel();
}
}
/**
* Returns true of the timer doesn't exist or has terminated.
*/
hasTerminated() {
return !this.timer || this.timer.hasTerminated();
}
}
module.exports = {
LoopingTimer
}
Instantiate the LoopingTimer Object and call loop with the function to call and time to run it. The function needs to return null when it’s time to stop looping or with when to run the function again.
This will be a part of my openhab_rules_tools library sometime soon.