node-red-contrib-boolean-logic-ultimate 1.0.37 → 1.0.41

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
@@ -2,7 +2,19 @@
2
2
  [![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square)](https://www.paypal.me/techtoday)
3
3
 
4
4
  <p>
5
- <b>Version 1.0.37</b> November 2021<br/>
5
+ <b>Version 1.0.41</b> January 2022<br/>
6
+ - Boolean Logic Ultimate: UI optimization and remove warning triangle if the delay is not set.</br>
7
+ </p>
8
+ <p>
9
+ <b>Version 1.0.40</b> January 2022<br/>
10
+ - NEW: Boolean Logic Ultimate: Delay option added. See the readme on gitHub.</br>
11
+ </p>
12
+ <p>
13
+ <b>Version 1.0.39</b> November 2021<br/>
14
+ - FIX a possible issue when msg.payload is numeric.</br>
15
+ </p>
16
+ <p>
17
+ <b>Version 1.0.38</b> November 2021<br/>
6
18
  - All nodes does accept "on" and "off" as input, converting it in "true" and "false" values (Homeassistant friendly).</br>
7
19
  </p>
8
20
  <p>
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 (ms)**
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
 
@@ -75,6 +75,11 @@ module.exports = function (RED) {
75
75
  res = value;
76
76
  }
77
77
  else if (typeof value === 'number' || typeof value === 'string') {
78
+
79
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
80
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
81
+
82
+
78
83
  // Is it formated as a decimal number?
79
84
  if (decimal.test(value)) {
80
85
  var v = parseFloat(value);
@@ -33,7 +33,10 @@
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
+ }
37
40
  },
38
41
  inputs: 1,
39
42
  outputs: 3,
@@ -117,7 +120,7 @@
117
120
 
118
121
  <div class="form-row">
119
122
  <label for="node-input-inputCount"><i class="fa fa-step-forward"></i> Inputs count</label>
120
- <input type="text" id="node-input-inputCount" placeholder="Inputs count, for example: 2">
123
+ <input style="width:100px" type="text" id="node-input-inputCount" placeholder="Inputs count, for example: 2">
121
124
  </div>
122
125
  <div class="form-tips" style="margin-top: 8px;background-color:lightgrey;text-align:center">Option above: the node waits for this number of <i>different</i> msg topics before evaluating the outputs.</div>
123
126
  <br/>
@@ -165,7 +168,14 @@
165
168
  <input type="checkbox" id="node-input-restrictinputevaluation" style="display:inline-block; width:auto; vertical-align:top;">
166
169
  &nbsp<label style="width:auto" for="node-input-restrictinputevaluation"> Reject non boolean (true/false) input values</label>
167
170
  </div>
168
-
171
+ <div class="form-row">
172
+ <label style="width:160px" for="node-input-delayEvaluation"><i class="fa fa-hourglass-o"></i> Delay evaluation (ms)</label>
173
+ <input style="width:150px" type="text" id="node-input-delayEvaluation" placeholder="Set 0 for no delay">
174
+ </div>
175
+
176
+ <br/>
177
+ <br/>
178
+ <br/>
169
179
  </script>
170
180
 
171
181
  <script type="text/x-red" data-help-name="BooleanLogicUltimate">
@@ -10,6 +10,11 @@ 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
+ if (isNaN(parseInt(node.delayEvaluation)) || parseInt(node.delayEvaluation) < 0) node.delayEvaluation = 0;
15
+ if (typeof node.delayEvaluation === "string") node.delayEvaluation = parseInt(node.delayEvaluation);
16
+ node.timerDelayEvaluation = null;
17
+ node.inputMessage = {}; // 26/01/2022 input message is stored here.
13
18
 
14
19
  function setNodeStatus({ fill, shape, text }) {
15
20
  var dDate = new Date();
@@ -63,6 +68,13 @@ module.exports = function (RED) {
63
68
  setNodeStatus({ fill: "yellow", shape: "dot", text: "Waiting for input states" });
64
69
  }
65
70
 
71
+ // Starts the evaluation delay timer, if needed
72
+ node.startTimerDelayEvaluation = () => {
73
+ if (node.timerDelayEvaluation !== null) clearTimeout(node.timerDelayEvaluation);
74
+ node.timerDelayEvaluation = setTimeout(() => {
75
+ outputResult();
76
+ }, node.delayEvaluation);
77
+ }
66
78
 
67
79
  // 14/08/2019 If some inputs are to be initialized, create a dummy items in the array
68
80
  initUndefinedInputs();
@@ -128,21 +140,21 @@ module.exports = function (RED) {
128
140
  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
141
  }
130
142
  }
143
+ node.inputMessage = msg; // 26/01/2022 Store MSG to be used in the outputResult function.
131
144
 
132
145
  // Do we have as many inputs as we expect?
133
146
  var keyCount = Object.keys(node.jSonStates).length;
134
-
135
147
  if (keyCount == node.config.inputCount) {
136
148
 
137
- var resAND = CalculateResult("AND");
138
- var resOR = CalculateResult("OR");
139
- var resXOR = CalculateResult("XOR");
149
+ // var resAND = CalculateResult("AND");
150
+ // var resOR = CalculateResult("OR");
151
+ // var resXOR = CalculateResult("XOR");
140
152
 
141
- if (node.config.filtertrue == "onlytrue") {
142
- if (!resAND) { resAND = null };
143
- if (!resOR) { resOR = null };
144
- if (!resXOR) { resXOR = null };
145
- }
153
+ // if (node.config.filtertrue == "onlytrue") {
154
+ // if (!resAND) { resAND = null };
155
+ // if (!resOR) { resOR = null };
156
+ // if (!resXOR) { resXOR = null };
157
+ // }
146
158
 
147
159
  // Operation mode evaluation
148
160
  if (node.config.outputtriggeredby == "onlyonetopic") {
@@ -150,12 +162,22 @@ module.exports = function (RED) {
150
162
  && node.config.triggertopic !== ""
151
163
  && msg.hasOwnProperty("topic") && msg.topic !== ""
152
164
  && node.config.triggertopic === msg.topic) {
153
- SetResult(resAND, resOR, resXOR, node.config.topic, msg);
165
+ if (node.delayEvaluation > 0) {
166
+ node.startTimerDelayEvaluation();
167
+ setNodeStatus({ fill: "blue", shape: "ring", text: "Delay Eval " + node.delayEvaluation + "ms" });
168
+ } else {
169
+ outputResult();
170
+ }
154
171
  } else {
155
172
  setNodeStatus({ fill: "grey", shape: "ring", text: "Saved (" + (msg.hasOwnProperty("topic") ? msg.topic : "empty input topic") + ") " + value });
156
173
  }
157
174
  } else {
158
- SetResult(resAND, resOR, resXOR, node.config.topic, msg);
175
+ if (node.delayEvaluation > 0) {
176
+ node.startTimerDelayEvaluation();
177
+ setNodeStatus({ fill: "blue", shape: "ring", text: "Delay Eval " + node.delayEvaluation + "ms" });
178
+ } else {
179
+ outputResult();
180
+ }
159
181
  }
160
182
  }
161
183
  else if (keyCount > node.config.inputCount) {
@@ -264,8 +286,8 @@ module.exports = function (RED) {
264
286
  }
265
287
  else if (typeof value === 'number' || typeof value === 'string') {
266
288
 
267
- if (value.toLowerCase() === "on") return true;
268
- if (value.toLowerCase() === "off") return false;
289
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
290
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
269
291
 
270
292
  // Is it formated as a decimal number?
271
293
  if (decimal.test(value)) {
@@ -280,30 +302,41 @@ module.exports = function (RED) {
280
302
  return res;
281
303
  };
282
304
 
283
- function SetResult(_valueAND, _valueOR, _valueXOR, optionalTopic, _msg) {
284
- setNodeStatus({ fill: "green", shape: "dot", text: "(AND)" + (_valueAND !== null ? _valueAND : "---") + " (OR)" + (_valueOR !== null ? _valueOR : "---") + " (XOR)" + (_valueXOR !== null ? _valueXOR : "---") });
305
+ function outputResult() {
306
+ let optionalTopic = node.config.topic;
307
+ let calculatedValueAND = CalculateResult("AND");
308
+ let calculatedValueOR = CalculateResult("OR");
309
+ let calculatedValueXOR = CalculateResult("XOR");
310
+
311
+ if (node.config.filtertrue == "onlytrue") {
312
+ if (!calculatedValueAND) { calculatedValueAND = null };
313
+ if (!calculatedValueOR) { calculatedValueOR = null };
314
+ if (!calculatedValueXOR) { calculatedValueXOR = null };
315
+ }
316
+
317
+ setNodeStatus({ fill: "green", shape: "dot", text: "(AND)" + (calculatedValueAND !== null ? calculatedValueAND : "---") + " (OR)" + (calculatedValueOR !== null ? calculatedValueOR : "---") + " (XOR)" + (calculatedValueXOR !== null ? calculatedValueXOR : "---") });
285
318
 
286
319
  var msgAND = null;
287
- if (_valueAND != null) {
288
- msgAND = RED.util.cloneMessage(_msg);
320
+ if (calculatedValueAND != null) {
321
+ msgAND = RED.util.cloneMessage(node.inputMessage);
289
322
  msgAND.topic = optionalTopic === undefined ? "result" : optionalTopic;
290
323
  msgAND.operation = "AND";
291
- msgAND.payload = _valueAND;
324
+ msgAND.payload = calculatedValueAND;
292
325
 
293
326
  }
294
327
  var msgOR = null;
295
- if (_valueOR != null) {
296
- msgOR = RED.util.cloneMessage(_msg);
328
+ if (calculatedValueOR != null) {
329
+ msgOR = RED.util.cloneMessage(node.inputMessage);
297
330
  msgOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
298
331
  msgOR.operation = "OR";
299
- msgOR.payload = _valueOR;
332
+ msgOR.payload = calculatedValueOR;
300
333
  }
301
334
  var msgXOR = null;
302
- if (_valueXOR != null) {
303
- msgXOR = RED.util.cloneMessage(_msg);
335
+ if (calculatedValueXOR != null) {
336
+ msgXOR = RED.util.cloneMessage(node.inputMessage);
304
337
  msgXOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
305
338
  msgXOR.operation = "XOR";
306
- msgXOR.payload = _valueXOR;
339
+ msgXOR.payload = calculatedValueXOR;
307
340
  }
308
341
  node.send([msgAND, msgOR, msgXOR]);
309
342
 
@@ -40,7 +40,7 @@
40
40
  <br/>
41
41
  </div>
42
42
  <div class="form-row">
43
- <label for="node-input-name"><i class="icon-tag"></i> Name (topic)</label>
43
+ <label for="node-input-name"><i class="icon-tag"></i> Name</label>
44
44
  <input type="text" id="node-input-name" placeholder="Name">
45
45
  </div>
46
46
  </script>
@@ -55,8 +55,8 @@ module.exports = function (RED) {
55
55
  }
56
56
  else if (typeof value === 'number' || typeof value === 'string') {
57
57
 
58
- if (value.toLowerCase() === "on") return true;
59
- if (value.toLowerCase() === "off") return false;
58
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
59
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
60
60
 
61
61
  // Is it formated as a decimal number?
62
62
  if (decimal.test(value)) {
@@ -83,8 +83,8 @@ module.exports = function (RED) {
83
83
  }
84
84
  else if (typeof value === 'number' || typeof value === 'string') {
85
85
 
86
- if (value.toLowerCase() === "on") return true;
87
- if (value.toLowerCase() === "off") return false;
86
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
87
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
88
88
 
89
89
  // Is it formated as a decimal number?
90
90
  if (decimal.test(value)) {
@@ -55,8 +55,8 @@ module.exports = function (RED) {
55
55
  }
56
56
  else if (typeof value === 'number' || typeof value === 'string') {
57
57
 
58
- if (value.toLowerCase() === "on") return true;
59
- if (value.toLowerCase() === "off") return false;
58
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
59
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
60
60
 
61
61
  // Is it formated as a decimal number?
62
62
  if (decimal.test(value)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-boolean-logic-ultimate",
3
- "version": "1.0.37",
3
+ "version": "1.0.41",
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": {