node-red-contrib-boolean-logic-ultimate 1.0.39 → 1.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Usare IntelliSense per informazioni sui possibili attributi.
|
|
3
|
+
// Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
|
|
4
|
+
// Per altre informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "pwa-node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Launch Program",
|
|
11
|
+
"skipFiles": [
|
|
12
|
+
"<node_internals>/**"
|
|
13
|
+
],
|
|
14
|
+
"program": "${workspaceFolder}/boolean-logic-ultimate/BooleanLogicUltimate.js"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# node-red-contrib-boolean-logic-ultimate
|
|
2
2
|
[](https://www.paypal.me/techtoday)
|
|
3
3
|
|
|
4
|
+
<p>
|
|
5
|
+
<b>Version 1.0.40</b> Januart 2022<br/>
|
|
6
|
+
- NEW: Boolean Logic Ultimate: Delay option added. See the readme on gitHub.</br>
|
|
7
|
+
</p>
|
|
4
8
|
<p>
|
|
5
9
|
<b>Version 1.0.39</b> November 2021<br/>
|
|
6
10
|
- FIX a possible issue when msg.payload is numeric.</br>
|
package/README.md
CHANGED
|
@@ -15,9 +15,15 @@ A set of Node-RED enhanced boolean logic, with persisten values after reboot and
|
|
|
15
15
|
> Wellcome! First of all thank you for your interest in my nodes. This is a set of logic nodes, to overcome the simplicity of the default node-red boolean logic nodes.
|
|
16
16
|
Hope you enjoy that and if you're in trouble, please ask!
|
|
17
17
|
|
|
18
|
+
<br/>
|
|
19
|
+
<br/>
|
|
20
|
+
|
|
18
21
|
## CHANGELOG
|
|
19
22
|
* See <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/blob/master/CHANGELOG.md">here the changelog</a>
|
|
20
23
|
|
|
24
|
+
<br/>
|
|
25
|
+
<br/>
|
|
26
|
+
|
|
21
27
|
# BOOLEAN LOGIC
|
|
22
28
|
|
|
23
29
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/bl1.png' width='60%'>
|
|
@@ -88,6 +94,12 @@ Every time you modify the node's config, <b>the retained values are cleared</b>.
|
|
|
88
94
|
|
|
89
95
|
If checked, the node will accept only boolean true/false values. Otherwise, it will try to convert the payload to a logic value true/false (including "on" and "off" values, sent, for example, from HomeAssistant).<br/>
|
|
90
96
|
|
|
97
|
+
**Delay evaluation (msec)**
|
|
98
|
+
|
|
99
|
+
Delays the evaluation until this time (in milliseconds) is elapsed. Each time a message or "topic trigger message" (see **Trigger mode**) arrives, the delay is restarted.<br/>
|
|
100
|
+
This option is useful for debouncing pourposes or simply for adding some delay.<br/>
|
|
101
|
+
For example, you can turn on a light if the room is occupied for a long time, allowing people to fast transit repeatedly, without the need of turning the light on.<br/>
|
|
102
|
+
Another example, if you have many sensors changing state rapidly, you can wait until these sensor reach a quiet state, then evaluate the inputs.<br/>
|
|
91
103
|
|
|
92
104
|
**INPUT MSG TO THE NODE**
|
|
93
105
|
|
|
@@ -33,7 +33,14 @@
|
|
|
33
33
|
return v !== undefined && v.length > 0;
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
restrictinputevaluation:{ value: true }
|
|
36
|
+
restrictinputevaluation: { value: true },
|
|
37
|
+
delayEvaluation: {
|
|
38
|
+
value: 0,
|
|
39
|
+
validate:
|
|
40
|
+
function (v) {
|
|
41
|
+
return !isNaN(parseInt(v)) && parseInt(v) >= 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
37
44
|
},
|
|
38
45
|
inputs: 1,
|
|
39
46
|
outputs: 3,
|
|
@@ -165,7 +172,14 @@
|
|
|
165
172
|
<input type="checkbox" id="node-input-restrictinputevaluation" style="display:inline-block; width:auto; vertical-align:top;">
|
|
166
173
|
 <label style="width:auto" for="node-input-restrictinputevaluation"> Reject non boolean (true/false) input values</label>
|
|
167
174
|
</div>
|
|
168
|
-
|
|
175
|
+
<div class="form-row">
|
|
176
|
+
<label for="node-input-delayEvaluation"><i class="fa fa-hourglass-o"></i> Delay evaluation (msec)</label>
|
|
177
|
+
<input style="width:100px" type="text" id="node-input-delayEvaluation" placeholder="0">
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<br/>
|
|
181
|
+
<br/>
|
|
182
|
+
<br/>
|
|
169
183
|
</script>
|
|
170
184
|
|
|
171
185
|
<script type="text/x-red" data-help-name="BooleanLogicUltimate">
|
|
@@ -10,6 +10,9 @@ module.exports = function (RED) {
|
|
|
10
10
|
node.sInitializeWith = typeof node.config.sInitializeWith === "undefined" ? "WaitForPayload" : node.config.sInitializeWith;
|
|
11
11
|
node.persistPath = path.join(RED.settings.userDir, "booleanlogicultimatepersist"); // 26/10/2020 Contains the path for the states dir.
|
|
12
12
|
node.restrictinputevaluation = config.restrictinputevaluation === undefined ? false : config.restrictinputevaluation;
|
|
13
|
+
node.delayEvaluation = config.delayEvaluation === undefined ? 0 : config.delayEvaluation; // 26/01/2022 Starts evaluating the inputs only after this amount of time is elapsed, after the last msg input or trigger
|
|
14
|
+
node.timerDelayEvaluation = null;
|
|
15
|
+
node.inputMessage = {}; // 26/01/2022 input message is stored here.
|
|
13
16
|
|
|
14
17
|
function setNodeStatus({ fill, shape, text }) {
|
|
15
18
|
var dDate = new Date();
|
|
@@ -63,6 +66,13 @@ module.exports = function (RED) {
|
|
|
63
66
|
setNodeStatus({ fill: "yellow", shape: "dot", text: "Waiting for input states" });
|
|
64
67
|
}
|
|
65
68
|
|
|
69
|
+
// Starts the evaluation delay timer, if needed
|
|
70
|
+
node.startTimerDelayEvaluation = () => {
|
|
71
|
+
if (node.timerDelayEvaluation !== null) clearTimeout(node.timerDelayEvaluation);
|
|
72
|
+
node.timerDelayEvaluation = setTimeout(() => {
|
|
73
|
+
outputResult();
|
|
74
|
+
}, node.delayEvaluation);
|
|
75
|
+
}
|
|
66
76
|
|
|
67
77
|
// 14/08/2019 If some inputs are to be initialized, create a dummy items in the array
|
|
68
78
|
initUndefinedInputs();
|
|
@@ -128,21 +138,21 @@ module.exports = function (RED) {
|
|
|
128
138
|
RED.log.error("BooleanLogicUltimate: unable to write to the filesystem. Check wether the user running node-red, has write permission to the filesysten. " + error.message);
|
|
129
139
|
}
|
|
130
140
|
}
|
|
141
|
+
node.inputMessage = msg; // 26/01/2022 Store MSG to be used in the outputResult function.
|
|
131
142
|
|
|
132
143
|
// Do we have as many inputs as we expect?
|
|
133
144
|
var keyCount = Object.keys(node.jSonStates).length;
|
|
134
|
-
|
|
135
145
|
if (keyCount == node.config.inputCount) {
|
|
136
146
|
|
|
137
|
-
var resAND = CalculateResult("AND");
|
|
138
|
-
var resOR = CalculateResult("OR");
|
|
139
|
-
var resXOR = CalculateResult("XOR");
|
|
147
|
+
// var resAND = CalculateResult("AND");
|
|
148
|
+
// var resOR = CalculateResult("OR");
|
|
149
|
+
// var resXOR = CalculateResult("XOR");
|
|
140
150
|
|
|
141
|
-
if (node.config.filtertrue == "onlytrue") {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
151
|
+
// if (node.config.filtertrue == "onlytrue") {
|
|
152
|
+
// if (!resAND) { resAND = null };
|
|
153
|
+
// if (!resOR) { resOR = null };
|
|
154
|
+
// if (!resXOR) { resXOR = null };
|
|
155
|
+
// }
|
|
146
156
|
|
|
147
157
|
// Operation mode evaluation
|
|
148
158
|
if (node.config.outputtriggeredby == "onlyonetopic") {
|
|
@@ -150,12 +160,22 @@ module.exports = function (RED) {
|
|
|
150
160
|
&& node.config.triggertopic !== ""
|
|
151
161
|
&& msg.hasOwnProperty("topic") && msg.topic !== ""
|
|
152
162
|
&& node.config.triggertopic === msg.topic) {
|
|
153
|
-
|
|
163
|
+
if (node.delayEvaluation > 0) {
|
|
164
|
+
node.startTimerDelayEvaluation();
|
|
165
|
+
setNodeStatus({ fill: "blue", shape: "ring", text: "Delay Eval " + node.delayEvaluation + "ms" });
|
|
166
|
+
} else {
|
|
167
|
+
outputResult();
|
|
168
|
+
}
|
|
154
169
|
} else {
|
|
155
170
|
setNodeStatus({ fill: "grey", shape: "ring", text: "Saved (" + (msg.hasOwnProperty("topic") ? msg.topic : "empty input topic") + ") " + value });
|
|
156
171
|
}
|
|
157
172
|
} else {
|
|
158
|
-
|
|
173
|
+
if (node.delayEvaluation > 0) {
|
|
174
|
+
node.startTimerDelayEvaluation();
|
|
175
|
+
setNodeStatus({ fill: "blue", shape: "ring", text: "Delay Eval " + node.delayEvaluation + "ms" });
|
|
176
|
+
} else {
|
|
177
|
+
outputResult();
|
|
178
|
+
}
|
|
159
179
|
}
|
|
160
180
|
}
|
|
161
181
|
else if (keyCount > node.config.inputCount) {
|
|
@@ -280,30 +300,41 @@ module.exports = function (RED) {
|
|
|
280
300
|
return res;
|
|
281
301
|
};
|
|
282
302
|
|
|
283
|
-
function
|
|
284
|
-
|
|
303
|
+
function outputResult() {
|
|
304
|
+
let optionalTopic = node.config.topic;
|
|
305
|
+
let calculatedValueAND = CalculateResult("AND");
|
|
306
|
+
let calculatedValueOR = CalculateResult("OR");
|
|
307
|
+
let calculatedValueXOR = CalculateResult("XOR");
|
|
308
|
+
|
|
309
|
+
if (node.config.filtertrue == "onlytrue") {
|
|
310
|
+
if (!calculatedValueAND) { calculatedValueAND = null };
|
|
311
|
+
if (!calculatedValueOR) { calculatedValueOR = null };
|
|
312
|
+
if (!calculatedValueXOR) { calculatedValueXOR = null };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
setNodeStatus({ fill: "green", shape: "dot", text: "(AND)" + (calculatedValueAND !== null ? calculatedValueAND : "---") + " (OR)" + (calculatedValueOR !== null ? calculatedValueOR : "---") + " (XOR)" + (calculatedValueXOR !== null ? calculatedValueXOR : "---") });
|
|
285
316
|
|
|
286
317
|
var msgAND = null;
|
|
287
|
-
if (
|
|
288
|
-
msgAND = RED.util.cloneMessage(
|
|
318
|
+
if (calculatedValueAND != null) {
|
|
319
|
+
msgAND = RED.util.cloneMessage(node.inputMessage);
|
|
289
320
|
msgAND.topic = optionalTopic === undefined ? "result" : optionalTopic;
|
|
290
321
|
msgAND.operation = "AND";
|
|
291
|
-
msgAND.payload =
|
|
322
|
+
msgAND.payload = calculatedValueAND;
|
|
292
323
|
|
|
293
324
|
}
|
|
294
325
|
var msgOR = null;
|
|
295
|
-
if (
|
|
296
|
-
msgOR = RED.util.cloneMessage(
|
|
326
|
+
if (calculatedValueOR != null) {
|
|
327
|
+
msgOR = RED.util.cloneMessage(node.inputMessage);
|
|
297
328
|
msgOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
|
|
298
329
|
msgOR.operation = "OR";
|
|
299
|
-
msgOR.payload =
|
|
330
|
+
msgOR.payload = calculatedValueOR;
|
|
300
331
|
}
|
|
301
332
|
var msgXOR = null;
|
|
302
|
-
if (
|
|
303
|
-
msgXOR = RED.util.cloneMessage(
|
|
333
|
+
if (calculatedValueXOR != null) {
|
|
334
|
+
msgXOR = RED.util.cloneMessage(node.inputMessage);
|
|
304
335
|
msgXOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
|
|
305
336
|
msgXOR.operation = "XOR";
|
|
306
|
-
msgXOR.payload =
|
|
337
|
+
msgXOR.payload = calculatedValueXOR;
|
|
307
338
|
}
|
|
308
339
|
node.send([msgAND, msgOR, msgXOR]);
|
|
309
340
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-boolean-logic-ultimate",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"description": "A set of Node-RED enhanced boolean logic node, flow interruption node, blinker node, invert node, filter node, with persisten values after reboot and more.",
|
|
5
5
|
"author": "Supergiovane (https://github.com/Supergiovane)",
|
|
6
6
|
"dependencies": {
|