openhab_rules_tools
Version:
Functions and classes to make writing openHAB rules in JS Scripting easier.
145 lines (131 loc) • 4.31 kB
JavaScript
const { time } = require('openhab');
const helpers = require('./helpers');
/**
* Implements a manager for Timers with a simple interface. Once built, call
* check to create a timer or to reschedule the timer if it exists. Options
* exist to call a function when the timer expires, when the timer already
* exists, and a boolean to determine if the timer is rescheduled or not.
*/
class TimerMgr {
/**
* Constructor
*/
constructor() {
// Stores the timer and the functions:
// - timer: timer Object
// - notFlapping: function to call when timer expires
// - flapping: function to call when check is called and timer already exists
this.timers = {};
}
/**
* Function to call when null was passed for the func or flappingFunc.
*/
#noop() {
// do nothing
}
/**
* If there is no timer associated with key, create one to expire at when and
* call func (or #noop if func is null).
* If there is a timer already associted with key, if reschedule is not
* supplied or it's false cancel the timer. If reschedule is true, reschedule
* the timer using when.
* If there is a timer already associated with key, if a flappingFunc is
* provided, call it.
* @param {string} key the identifier of the timer in the TimerMgr instance
* @param {*} when any representation of time of duration, see time.toZDT
* @param {function} func function to call when the timer expires
* @param {boolean} [reschedule=false] optional flag, when present and true rescheudle the timer if it already exists
* @param {function} [flappingFunc] optional function to call when the timer already exists
* @param {string} [name] timer name displayed in openHAB
* @param {boolean}[recreate=false] optional flag, when present and true the timer will be recreated with the new values instead of cancelled, evaluated after reschedule
*/
check(key, when, func, reschedule, flappingFunc, name, recreate) {
const timeout = time.toZDT(when);
// timer exists
if (key in this.timers) {
if (reschedule) {
this.timers[key]['timer'].reschedule(timeout);
}
else {
this.cancel(key);
}
if (flappingFunc) {
flappingFunc();
}
if (recreate) {
this.check(key, when, func, reschedule, flappingFunc, name, false);
}
}
// timer doesn't already exist, create a new one
else {
var timer = helpers.createTimer(when, () => {
// Call the passed in func when the timer expires.
if (key in this.timers && 'notFlapping' in this.timers[key]) {
this.timers[key]['notFlapping']();
}
// Clean up the timer from the manager.
if (key in this.timers) {
delete this.timers[key];
}
}, name, key);
this.timers[key] = {
'timer': timer,
'flapping': flappingFunc,
'notFlapping': (func) ? func : this.#noop
};
}
}
/**
* @param {*} key name of the timer
* @returns {boolean} true if there is a timer assocaited with key
*/
hasTimer(key) {
return key in this.timers;
}
/**
* @param {*} key name of the timer
* @returns {Duration} of time left in the timer function
* or null if timer does not exist
*/
getTimerDuration(key) {
if (key in this.timers) {
return time.Duration.between(time.toZDT(), time.toZDT(this.timers[key].timer.getExecutionTime()));
}
return null;
}
/**
* If there is a timer assocaited with key, cancel it.
* @param {*} key name of the timer
*/
cancel(key) {
if (key in this.timers) {
this.timers[key]['timer'].cancel();
delete this.timers[key];
}
}
/**
* Cancels all existing timers. Any timer that is actively running or
* has just terminated will be skipped and cleaned up in the _notFlapping
* method.
*/
cancelAll() {
for (var key in this.timers) {
var t = this.timers[key]['timer'];
if (!t.hasTerminated() && !t.isRunning()) {
this.cancel(key);
}
delete this.timers[key];
}
}
}
/**
* The TimerMgr handles the book keeping to manage a bunch of timers identified
* with a unique key.
*/
function getTimerMgr () {
return new TimerMgr();
}
module.exports = {
TimerMgr,
getTimerMgr
}