-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
helpers.js
155 lines (143 loc) · 6.01 KB
/
helpers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
const { actions, time, utils } = require('openhab');
const VERSION = require('./package.json').version;
/**
* Utility function to create a named timer.
*
* The name can be set with the name parameter or is autogenerated from the ruleUID (for UI) or filename and the timer's key (if available).
*
* @param {*} when any representation of time or duration, see {@link https://openhab.github.io/openhab-js/time.html#.toZDT time.toZDT}
* @param {function} func function to call when the timer expires
* @param {string} [name] name for the timer
* @param {string} [key] key of the timer to append to the generated name
* @returns openHAB Java {@link https://www.openhab.org/javadoc/latest/org/openhab/core/model/script/actions/timer Timer}
*/
const createTimer = (when, func, name, key) => {
const timeout = time.toZDT(when);
if (name === null || name === undefined) {
if (global.ruleUID !== undefined) { // Use UI ruleUID and key if available
name = 'ui.' + global.ruleUID + ((key !== undefined) ? '.' + key : '');
} else if (global['javax.script.filename'] !== undefined) { // Use filename and key if available
name = 'file.' + global['javax.script.filename'].replace(/^.*[\\/]/, '') + ((key !== undefined) ? '.' + key : '');
}
}
return actions.ScriptExecution.createTimer(name, timeout, func);
};
/**
* Utility function mostly used by rule templates to check the metadata and Group membership
* of the Items that drive a rule like Debounce or Time Based State Machine. An Item metadata
* namespace and Group is passed along with a function and usage text.
*
* The function validates that all Items that have the given namespace are members of grp,
* no members of grp lack the namespace metadata, and the validateFunc is called to validate
* the metadata on each individual Item. validateFunc should throw an exception with the
* reason why the Item failed validation when it fails. The usage text will be logged if one
* or more Items fail validations.
*
* @param {string} namespace the Item metadata namespace to check
* @param {string} grp name of the Group Item all the Items with namespace should belong to
* @param {function} validateFunc function called to validate the metadata is valid
* @param {string} usage text to log out when an Item fails validation
* @returns {boolean} true if validation passes, false if there's a problem
**/
const checkGrpAndMetadata = (namespace, grp, validateFunc, usage) => {
let isGood = true;
const badItems = [];
// Get all the Items with NAMESPACE metadata
const allItems = items.getItems();
const filtered = allItems.filter(item => item.getMetadata(namespace));
// Check the metadata of members of the Group membership
filtered.forEach(item => {
try {
const cfg = validateFunc(item.name);
if (!item.groupNames.includes(grp)) {
console.warn(item.name + ' has ' + namespace + ' metadata but is not a member of ' + grp + '!');
isGood = false;
badItems.push(item.name);
}
}
catch (e) {
console.warn('Item ' + item.name + "'s configuration is invalid:\n" + e);
isGood = false;
badItems.push(item.name);
}
});
// Check Group membership
if (!items[grp]) {
console.warn('There is no ' + grp + ' Group!');
isGood = false;
}
else if (!items[grp].members) {
console.warn(grp + ' does not have any members!');
isGood = false;
}
else {
items[grp].members.filter(item => item.getMetadata(namespace) === null).forEach(item => {
console.warn(item.name + ' is a member of ' + grp + ' but lacks ' + namespace + ' metadata!');
isGood = false;
badItems.push(item.name);
});
}
// Report the bad Items and print usage info
if (isGood) {
console.info('All ' + namespace + ' Items are configured correctly');
}
else {
if (badItems.length) console.warn('The following Items have an invalid configuration: ' + badItems + '\n');
console.warn(usage);
}
return isGood;
};
/**
* Validates that the passed in version number is of the format X.Y.Z where
* X, Y, and Z are numbers.
*
* @param {string} version a version string to validate
* @returns {boolean} true if valid, false otherwise
*/
const _validateVersionNum = (version) => {
const re = /\d+\.\d+\.\d+/;
if (version === null || version === undefined || !(typeof version === 'string')) return false;
return re.test(version);
};
/**
* Compare version numbers of the format X.Y.Z.
*
* @param {string} v1 the first version number
* @param {string} v2 the second version number
* @throws error if v1 or v2 are not parsable
* @returns {-1|0|1} 0 if the versions are equal, -1 if v1 is lower and 1 if v1 is higher
*/
const compareVersions = (v1, v2) => {
if (!_validateVersionNum(v1)) throw v1 + ' is not a valid version number in the format X.Y.Z where X, Y, and Z are numbers!';
if (!_validateVersionNum(v2)) throw v2 + ' is not a valid version number in the format X.Y.Z where X, Y, and Z are numbers!';
const v1Version = Number.parseFloat(v1);
const v1Point = Number.parseInt(v1.split('.')[2]);
const v2Version = Number.parseFloat(v2);
const v2Point = Number.parseFloat(v2.split('.')[2]);
if (v1 == v2) return 0;
else if (v1Version > v2Version) return 1;
else if (v1Version == v2Version && v1Point > v2Point) return 1;
else return -1;
};
/**
* Checks to see if the minimum versions of openhab-js and openhab_rules_tools
* are met.
*
* @throws error if one or more of the version numbers are malformed
* @throws error if one or more of the versions are too old
*/
const validateLibraries = (minOHJS, minOHRT) => {
if (compareVersions(utils.OPENHAB_JS_VERSION, minOHJS) < 0)
throw 'Minimum library version not met: openhab-js '
+ utils.OPENHAB_JS_VERSION + ' installed, ' + minOHJS + ' required';
if (compareVersions(VERSION, minOHRT) < 0)
throw 'Minimum library version not met: openhab_rules_tools '
+ VERSION + ' installed, ' + minOHRT + ' required';
};
module.exports = {
createTimer,
checkGrpAndMetadata,
compareVersions,
validateLibraries,
OHRT_VERSION: VERSION
};