forked from rkoshak/openhab-rules-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rulesUtils.js
executable file
·166 lines (150 loc) · 6.51 KB
/
rulesUtils.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
156
157
158
159
160
161
162
163
164
165
166
const RuleManager = osgi.getService('org.openhab.core.automation.RuleManager');
const ruleRegistry = osgi.getService('org.openhab.core.automation.RuleRegistry');
const { itemRegistry } = require('@runtime');
/**
* Generates an Array of Item triggers for each Item in the list.
* @param {Array<Item>} list list of Items to generate triggers for
* @param {triggers.ItemChangedTrigger|triggers.ItemStateUpdateTrigger|triggers.ItemStateUpdateTrigger} trigger type of trigger to generate for each Item in the list
* @param {int} systemStarted optional, when provided adds a system runlevel trigger. Valid values are 40, 50, 60, 70, 80, 90, or 100.
* @returns {Array<triggers>} the generated rule triggers
*/
const generateTriggers = (list, trigger, systemStarted) => {
let triggers = [];
list.forEach(i => {
triggers.push(trigger(i.name));
});
if(systemStarted && systemStarted >= 40) triggers.push(triggers.SystemStartLevelTrigger(systemStarted));
return triggers;
}
/**
* Checks to see if the rule exists
* @param {String} uid UID for the rule to look for
* @returns {Boolean} true when the rule exists
*/
const ruleExists = (uid) => {
return !(RuleManager.getStatusInfo(uid) == null);
}
/**
* Deletes the rule if it exists. Does not work in UI rules.
* @param {String} uid UID for the rule to remove
*/
const removeRule = (uid) => {
if(ruleExists(uid)) {
ruleRegistry.remove(uid);
return !ruleExists(uid);
}
else {
return false;
}
}
/**
* If a rule with the given UID exists, it's deleted. Then a new rule is created
* with the given properties. A DYNAMIC_RULE_TAG will be applied to the rule.
* @param {string} uid unique identifier for the given rule
* @param {string} ruleName name for the rule as it will appear in MainUI
* @param {string} ruleDescription explanation of the purpose of the rule
* @param {Array<triggers.*>} trigs triggers which willcause the rule to run
* @param {function(event)} func called when the rule triggers
* @param {Array<string>} [ts=[]] optional list of tags to apply to the rule
*/
const recreateRule = (uid, ruleName, ruleDescription, trigs, func, ts = []) => {
console.log('Removing the rule if necessary');
// Remove the existing rule if it exists, only works for rules created in the same file
if(ruleExists(uid)) if(removeRule(uid)) return null;
console.log('Old rule removed if it existed');
ts.push['DYNAMIC_RULE_TAG'];
let args = {
name: ruleName,
description: ruleDescription,
id: uid,
triggers: trigs,
tags: ts,
execute: func
};
console.log('Rule args:', args);
return rules.JSRule( {
name: ruleName,
description: ruleDescription,
id: uid,
triggers: trigs,
tags: ts,
execute: func
});
}
/**
* Creates a rule that is triggered when any Item with valid metadata in the passed in
* namespace using the passed in trigger type. In addition to the passed in tags,
* a DYNAMIC_RULE_TAG will also be applied.
* @param {string} namespace Item metadata namespace used to identify those Items to trigger
* @param {function(itemName)} checkConfig function that returns true if the metadata on the Item is valid
* @param {triggers.ItemStateChangeTrigger|triggers.ItemStateUpdateTrigger|triggers.ItemChangeTrigger} event the Item trigger type to create for each Item
* @param {string} ruleName name of the rule generated
* @param {function(event)} func function to call when the rule is triggered
* @param {string} description optional description for the rule
* @param {Array<string>} tags optional tags to apply to the rule
* @param {string} uid optional UID to identify the rule
* @param {int} systemStarted optional when true a runlevel 40 trigger will be added to the rule.
* @returns {HostRule} the created rule, or null if there was a problem
*/
const createRuleWithMetadata = (namespace, checkConfig, trigger, ruleName, func,
description, uid, systemStarted, tags) => {
// Get the Items
let triggeringItems = utils.javaSetToJsArray(itemRegistry.getAll())
.filter(i => items.getItem(i.name).getMetadataValue(namespace) && checkConfig(i.name));
triggers = generateTriggers(triggeringItems, trigger, systemStarted);
if(!triggers) return null;
return recreateRule(uid, ruleName, description, triggers, func, tags);
}
/**
* Creates a rule that is triggered when any Item with a given tag trigger type.
* In addition to the passed in tags, a DYNAMIC_RULE_TAG will also be applied.
* @param {string} tag Item tag used to identify those Items to trigger
* @param {triggers.ItemStateChangeTrigger|triggers.ItemStateUpdateTrigger|triggers.ItemChangeTrigger} event the Item trigger type to create for each Item
* @param {string} ruleName name of the rule generated
* @param {function(event)} func function to call when the rule is triggered
* @param {string} description optional description for the rule
* @param {Array<string>} tags optional tags to apply to the rule
* @param {string} uid optional UID to identify the rule
* @param {int} systemStarted optional when true a runlevel 40 trigger will be added to the rule.
* @returns {HostRule} the created rule, or null if there was a problem
*/
const createRuleWithTags = (tag, trigger, ruleName, func, description,
uid, systemStarted, tags) => {
let triggeringItems = items.getItemsByTag(tag);
triggers = generateTriggers(triggeringItems, trigger, systemStarted);
if(!triggers) return null;
return recreateRule(uid, ruleName, description, triggers, func, tags);
}
/**
* Calls another rule based on UID or rule name. TODO remove when added to openhab-js
* @param {string} nameOrUid Rule UID or name to run
* @param {dict} argsDict optional dict of data to pass to the called rule
* @param {boolean} cond optional flag, when true the called rule's conditions will be evaluated
* @returns {boolean} true when the rule is found and successfully called
*/
const runRule = (nameOrUid, argsDict, cond = false) => {
// If it's not a UID, try to find it by name
if(!RuleManager.getStatusInfo(nameOrUid)) {
const { ruleRegistry } = require('@runtime/RuleSupport');
const rule = utils.javaSetToJsArray(ruleRegistry.getAll())
.find(rule => rule.getName() == nameOrUid);
nameOrUid = (rule) ? rule.getUID() : null;
}
// run the rule
if(nameOrUid) {
RuleManager.runNow(nameOrUid, cond, argsDict);
return true;
}
else {
return false;
}
}
module.exports = {
generateTriggers,
recreateRule,
createRuleWithMetadata,
createRuleWithTags,
runRule,
ruleExists,
removeRule
}