Skip to content

Commit 31285c4

Browse files
authored
Merge pull request #107 from rkoshak/oh4Updates
Updates to library for OH 4
2 parents 4400d39 + a3894f7 commit 31285c4

23 files changed

+369
-330
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ New to OH 3.4 release, a system wide cache has been added where variables can be
8585
On can pull, and if it doesn't exist instantiate a Object in one line inside your rule.
8686

8787
```
88-
var timers = cache.shared.get('timers', () new timerMgr.TimerMgr());
88+
var timers = cache.shared.get('timers', () TimerMgr());
8989
```
9090

9191
It is important to use unique keys across all your rules to avoid collisions.

countdownTimer.js

+22-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { loopingTimer } = require('openhab_rules_tools');
1+
const { LoopingTimer } = require('openhab_rules_tools');
22
const { time, items } = require('openhab');
33

44
/**
@@ -27,16 +27,16 @@ class CountdownTimer {
2727

2828
// Start the countdown timer
2929
this.countItem = countItem;
30-
this.countdownTimer = new loopingTimer.LoopingTimer();
31-
this.countdownTimer.loop(this._iterateGenerator(this), 0, name); // start now
30+
this.countdownTimer = LoopingTimer();
31+
this.countdownTimer.loop(this.#iterateGenerator(this), 0, name); // start now
3232
}
3333

3434
/**
3535
* Determines the number of seconds left and updates the count Item. If the
3636
* time left is less than a second, 0 is the value posted.
3737
* @param {CountdownTimer} ctx Context to access the timer information from inside the countdown Timer's lambda
3838
*/
39-
_updateItem(ctx) {
39+
#updateItem(ctx) {
4040
let left = (ctx.timeLeft.compareTo(ctx.ONE_SEC) < 0) ? 0 : ctx.timeLeft.seconds();
4141
items.getItem(ctx.countItem).postUpdate(left);
4242
}
@@ -46,9 +46,9 @@ class CountdownTimer {
4646
* the time has run out, calling updateItem each time.
4747
* @param {CountdownTimer} ctx Context to access the timer information from inside the looping timer
4848
*/
49-
_iterateGenerator(ctx) {
49+
#iterateGenerator(ctx) {
5050
return () => {
51-
ctx._updateItem(ctx);
51+
ctx.#updateItem(ctx);
5252
if (!ctx.timeLeft.isZero()) {
5353
let sleepTime = (ctx.timeLeft.compareTo(ctx.ONE_SEC) < 0) ? ctx.timeLeft : ctx.ONE_SEC;
5454
ctx.timeLeft = ctx.timeLeft.minusDuration(sleepTime);
@@ -73,12 +73,26 @@ class CountdownTimer {
7373
*/
7474
cancel() {
7575
this.timeLeft = time.Duration.ofSeconds(0);
76-
this._updateItem(this);
76+
this.#updateItem(this);
7777
this.countDownTimer?.cancel();
7878
return this.timer.cancel();
7979
}
8080
}
8181

82+
/**
83+
* A countdown timer updates an Item with the number of seconds left in the timer
84+
* once a second.
85+
* @param {*} when time.toZDT compatible time or duration
86+
* @param {function} func function to call at when
87+
* @param {string} countItem name of the Item to update with the seconds remaining
88+
* @param {string} [name] countdown name displayed in openHAB
89+
* @returns a new CountdownTimer
90+
*/
91+
function getCountdownTimer(when, func, countItem, name) {
92+
return new CountdownTimer(when, func, countItem, name);
93+
}
94+
8295
module.exports = {
83-
CountdownTimer
96+
CountdownTimer,
97+
getCountdownTimer
8498
}

deferred.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { timerMgr } = require('openhab_rules_tools');
1+
const { TimerMgr } = require('openhab_rules_tools');
22
const { time, items } = require('openhab');
33

44
/**
@@ -10,7 +10,7 @@ class Deferred {
1010
* Constructor
1111
*/
1212
constructor() {
13-
this.timers = new timerMgr.TimerMgr();
13+
this.timers = TimerMgr();
1414
}
1515

1616
/**
@@ -19,7 +19,7 @@ class Deferred {
1919
* @param {string} value command or update to send
2020
* @param {boolean} isCommand when true, value will be sent as a command, otherwise posted as an update
2121
*/
22-
_timerBodyGenerator(target, value, isCommand) {
22+
#timerBodyGenerator(target, value, isCommand) {
2323
const item = items.getItem(target);
2424
return () => (isCommand) ? item.sendCommand(value) : item.postUpdate(value);
2525
}
@@ -34,11 +34,11 @@ class Deferred {
3434
*/
3535
defer(target, value, when, isCommand) {
3636
const triggerTime = time.toZDT(when);
37-
if (triggerTime.isBefore(time.ZonedDateTime.now())) {
38-
triggerTime = time.ZonedDateTime.now();
37+
if (triggerTime.isBefore(time.toZDT())) {
38+
triggerTime = time.toZDT();
3939
}
4040
this.timers.cancel(target);
41-
this.timers.check(target, triggerTime, this._timerBodyGenerator(target, value, isCommand, when), false);
41+
this.timers.check(target, triggerTime, this.#timerBodyGenerator(target, value, isCommand, when), false);
4242
}
4343

4444
/**
@@ -57,6 +57,16 @@ class Deferred {
5757
}
5858
}
5959

60+
/**
61+
* Deferred is a way to schedule a simple command sometime in the future.
62+
*
63+
* @returns a new instance of Deferred
64+
*/
65+
function getDeferred() {
66+
return new Deferred();
67+
}
68+
6069
module.exports = {
61-
Deferred
70+
Deferred,
71+
getDeferred
6272
}

gatekeeper.js

+17-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Gatekeeper {
2626
* @parm {*} ctx pointer to the Gatekeeper OPbject.
2727
* @returns {function} function called by the timer to process the next command.
2828
*/
29-
_procCommandGenerator(ctx) {
29+
#procCommandGenerator(ctx) {
3030
return () => {
3131

3232
// no more commands
@@ -38,15 +38,15 @@ class Gatekeeper {
3838
else {
3939
const command = ctx.commands.pop();
4040
const func = command[1];
41-
const before = time.ZonedDateTime.now();
41+
const before = time.toZDT();
4242
func();
43-
const after = time.ZonedDateTime.now();
43+
const after = time.toZDT();
4444

4545
const delta = time.Duration.between(before, after);
4646
const pause = time.toZDT(command[0]);
4747
const triggerTime = pause.minus(delta);
4848

49-
ctx.timer = helpers.createTimer(triggerTime, ctx._procCommandGenerator(ctx), this.name, 'gatekeeper');
49+
ctx.timer = helpers.createTimer(triggerTime, ctx.#procCommandGenerator(ctx), this.name, 'gatekeeper');
5050
}
5151

5252
};
@@ -61,7 +61,7 @@ class Gatekeeper {
6161
addCommand(pause, command) {
6262
this.commands.add([pause, command]);
6363
if (this.timer === null || this.timer.hasTerminated()) {
64-
this._procCommandGenerator(this)();
64+
this.#procCommandGenerator(this)();
6565
}
6666
}
6767

@@ -76,6 +76,17 @@ class Gatekeeper {
7676
}
7777
}
7878

79+
/**
80+
* The Gatekeeper will ensure that a certain amount of time passes between
81+
* commands.
82+
* @param {String} name optional and used in error messages
83+
* @returns a new Gatekeeper instance
84+
*/
85+
function getGatekeeper(name) {
86+
return new Gatekeeper(name);
87+
}
88+
7989
module.exports = {
80-
Gatekeeper
90+
Gatekeeper,
91+
getGatekeeper
8192
}

helpers.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ const createTimer = (when, func, name, key) => {
4242
* @returns {boolean} true if validation passes, false if there's a problem
4343
**/
4444
const checkGrpAndMetadata = (namespace, grp, validateFunc, usage) => {
45-
let isGood = true;
46-
let badItems = [];
45+
const isGood = true;
46+
const badItems = [];
4747

48-
// Get all the Item with NAMESPACE metadata
48+
// Get all the Items with NAMESPACE metadata
4949
const allItems = items.getItems();
5050
const filtered = allItems.filter(item => item.getMetadata(namespace));
5151

index.js

+30-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
module.exports = {
22
get timeUtils() { return require('./timeUtils.js') },
3-
get timerMgr() { return require('./timerMgr.js') },
4-
get loopingTimer() { return require('./loopingTimer.js') },
5-
get rateLimit() { return require('./rateLimit.js') },
3+
get timerMgr() {
4+
console.warn('require TimerMgr instead of timerMgr and use TimerMgr() instead of new timerMgr.TimerMgr().');
5+
return require('./timerMgr.js')
6+
},
7+
get TimerMgr() { return require('./timerMgr.js').getTimerMgr; },
8+
get loopingTimer() {
9+
console.warn('require LoopingTimer instead of loopingTimer and use LoopingTimer() instead of new loopingTimer.LoopingTimer().');
10+
return require('./loopingTimer.js')
11+
},
12+
get LoopingTimer() { return require('./loopingTimer.js').getLoopingTimer; },
13+
get rateLimit() {
14+
console.warn('require RateLimit instead of rateLimit and use RateLimit() instead of new rateLimit.RateLimit().');
15+
return require('./rateLimit.js')
16+
},
17+
get RateLimit() { return require('./rateLimit.js').getRateLimit; },
618
get testUtils() { return require('./testUtils.js') },
7-
get gatekeeper() { return require('./gatekeeper.js') },
8-
get deferred() { return require('./deferred.js') },
9-
get countdownTimer() { return require('./countdownTimer.js') },
19+
get gatekeeper() {
20+
console.warn('require Gatekeeper instead of gatekeeper and use Gatekeeper() instead of new gatekeeper.Gatekeeper().');
21+
return require('./gatekeeper.js');
22+
},
23+
get Gatekeeper() { return require('./gatekeeper.js').getGatekeeper; },
24+
get deferred() {
25+
console.warn('require Deferred instead of deferred and use Deferred() instead of new deferred.Deferred().');
26+
return require('./deferred.js');
27+
},
28+
get Deferred() { return require('./deferred.js').getDeferred; },
29+
get countdownTimer() {
30+
console.warn('require CountdownTimer instead of countdownTimer and use CountdownTimer() instead of new countdownTimer.CountdownTimer().');
31+
return require('./countdownTimer.js');
32+
},
33+
get CountdownTimer() { return require('./countdownTimer.js').getCountdownTimer; },
1034
get groupUtils() { return require('./groupUtils.js') },
1135
get rulesUtils() { return require('./rulesUtils.js') },
1236
get helpers() { return require('./helpers.js') }

loopingTimer.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ class LoopingTimer {
6767
}
6868
}
6969

70+
/**
71+
* @returns a timer that resheduels itself until the passed in looping function
72+
* return null
73+
*/
74+
function getLoopingTimer() {
75+
return new LoopingTimer();
76+
}
77+
7078
module.exports = {
71-
LoopingTimer
79+
LoopingTimer,
80+
getLoopingTimer
7281
}

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openhab_rules_tools",
3-
"version": "2.0.2",
3+
"version": "2.0.3",
44
"description": "Functions and classes to make writing openHAB rules in JS Scripting easier.",
55
"private": false,
66
"license": "EPL-2.0",
@@ -21,6 +21,6 @@
2121
"url": "https://github.com/rkoshak/openhab-rules-tools/issues"
2222
},
2323
"devDependencies": {
24-
"openhab": "^4.1.0"
24+
"openhab": "^4.5.1"
2525
}
26-
}
26+
}

rateLimit.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ class RateLimit {
2626
}
2727
}
2828

29+
/**
30+
* The RateLimit class keeps track of when the last `run` was called and throws
31+
* away subsequent calls to run that occur before the passed in `when`.
32+
*/
33+
function getRateLimit() {
34+
return new RateLimit();
35+
}
36+
2937
module.exports = {
30-
RateLimit
31-
}
38+
RateLimit,
39+
getRateLimit
40+
}

rule-templates/debounce/debounce2.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ actions:
6363
configuration:
6464
type: application/javascript
6565
script: >
66-
// Version 0.2
66+
// Version 0.3
6767
68-
var {timerMgr, helpers} = require('openhab_rules_tools');
68+
var {TimerMgr, helpers} = require('openhab_rules_tools');
6969
7070
console.loggerName = 'org.openhab.automation.rules_tools.Debounce';
7171
7272
//osgi.getService('org.apache.karaf.log.core.LogService').setLevel(console.loggerName, 'DEBUG');
7373
7474
75-
helpers.validateLibraries('4.1.0', '2.0.1');
75+
helpers.validateLibraries('4.1.0', '2.0.3');
7676
7777
7878
var USAGE = "Debounce metadata should follow this format:\n"
@@ -93,7 +93,7 @@ actions:
9393
*/
9494
var getConfig = (itemName) => {
9595
96-
const md = items[itemName].getMetadata()['{{namespace}}'];
96+
const md = items[itemName].getMetadata()['{{namespace}}'];
9797
if(!md) {
9898
throw itemName + ' does not have {{namespace}} metadata!\n' + USAGE;
9999
}
@@ -159,7 +159,7 @@ actions:
159159
console.debug('Debounce:', event.type, 'item:', event.itemName);
160160
161161
// Initialize the timers, config and end debounce function
162-
const timers = cache.private.get('timerMgr', () => new timerMgr.TimerMgr());
162+
const timers = cache.private.get('timerMgr', () => TimerMgr());
163163
const cfg = getConfig(event.itemName);
164164
const endDebounce = endDebounceGenerator(event.itemName, event.itemState, cfg.proxy, cfg.command);
165165

rule-templates/ephemToD/time_state_machine.yaml

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ actions:
4545
configuration:
4646
type: application/javascript
4747
script: >
48-
// Version 0.2
48+
// Version 0.3
4949
50-
var {timerMgr, helpers} = require('openhab_rules_tools');
50+
var {TimerMgr, helpers} = require('openhab_rules_tools');
5151
5252
console.loggerName = 'org.openhab.automation.rules_tools.TimeStateMachine';
5353
5454
//osgi.getService('org.apache.karaf.log.core.LogService').setLevel(console.loggerName, 'DEBUG');
5555
5656
57-
helpers.validateLibraries('4.2.0', '2.0.1');
57+
helpers.validateLibraries('4.2.0', '2.0.3');
5858
5959
6060
console.debug('Starting state machine in ten seconds...');
@@ -316,7 +316,7 @@ actions:
316316
};
317317
318318
319-
var timers = cache.private.get('timers', () => new timerMgr.TimerMgr());
319+
var timers = cache.private.get('timers', () => TimerMgr());
320320
321321
322322
// Wait a minute after the last time the rule is triggered to make sure all Items are done changing (e.g.

0 commit comments

Comments
 (0)