node-red-contrib-boolean-logic-ultimate 1.0.36 → 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,18 @@
1
1
  # node-red-contrib-boolean-logic-ultimate
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
+ <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>
8
+ <p>
9
+ <b>Version 1.0.39</b> November 2021<br/>
10
+ - FIX a possible issue when msg.payload is numeric.</br>
11
+ </p>
12
+ <p>
13
+ <b>Version 1.0.38</b> November 2021<br/>
14
+ - All nodes does accept "on" and "off" as input, converting it in "true" and "false" values (Homeassistant friendly).</br>
15
+ </p>
4
16
  <p>
5
17
  <b>Version 1.0.36</b> November 2021<br/>
6
18
  - ImpulseUltimate: NEW: added <b>restart</b> command, to restart the sequence from scratch.</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%'>
@@ -49,7 +55,9 @@ The node performs some checks on the incoming boolean payloads and outputs all r
49
55
  If you need ***"NAND"*** or ***"NOR"*** gate, just put an **InvertUltimate** node respectively after the "AND" or "OR" pin.
50
56
 
51
57
  The node can have a persistent input: the input values are retained after a node-red reboot. That means, that if you reboot your node-red, you don't need to wait all inputs to arrive and initialize the node, before the node can output a payload.<br/>
52
- You can also set the default values of the topic inputs.
58
+ You can also set the default values of the topic inputs.<br/>
59
+ The node can convert arbitrary input values to true/false. It supports Homeassistant ***"on"*** and ***"off"*** as well. For enabling auto conversion, please be sure to disable **Reject non boolean (true/false) input values** <br/>
60
+
53
61
 
54
62
 
55
63
  ### CONFIGURATION
@@ -82,6 +90,17 @@ Every time you create a node or modify the node, all inputs are set to undefined
82
90
  If checked, the input values are retained after a node-red reboot. That means, that if you reboot your node-red, you don't need to wait all inputs to arrive and initialize the node, before the node can output a payload.<br/>
83
91
  Every time you modify the node's config, <b>the retained values are cleared</b>.<br/>
84
92
 
93
+ **Reject non boolean (true/false) input values**
94
+
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/>
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/>
103
+
85
104
  **INPUT MSG TO THE NODE**
86
105
 
87
106
  <code>
@@ -97,7 +116,8 @@ Resets all inputs to undefined.
97
116
 
98
117
  # INTERRUPT FLOWS ULTIMATE
99
118
 
100
- Whenever this node receives a payload = false from a specific topic, it stops output messages to the flow. As soon it receives payload = true from this topic, the output messages start to flow out again.
119
+ Whenever this node receives a payload = false from a specific topic, it stops output messages to the flow. As soon it receives payload = true from this topic, the output messages start to flow out again.<br/>
120
+ The node tries to convert any arbitrary input value to a valid boolean value. It converts Homeassistant ***"on"*** and ***"off"*** to true/false values as well.<br/>
101
121
 
102
122
  <img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/if0.png' width='60%'>
103
123
 
@@ -129,7 +149,8 @@ This allow to save the state of a node and then replay it back whenever you want
129
149
  # INVERT ULTIMATE
130
150
 
131
151
  Outputs the inverted input. For example true -> false<br />
132
- The input message is preserved and passed to the output pin, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.
152
+ The input message is preserved and passed to the output pin, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.<br/>
153
+ The node tries to convert any arbitrary input value to a valid boolean value. It converts Homeassistant ***"on"*** and ***"off"*** to true/false values as well.<br/>
133
154
 
134
155
  <br/>
135
156
  <br/>
@@ -142,7 +163,8 @@ The input message is preserved and passed to the output pin, changing only the t
142
163
  This node has 2 outputs.<br />
143
164
  If the input payload is true, the node will send <code>true</code> on output 1 and nothing on oputput 2<br />
144
165
  If the input payload is false, the node will send nothing on output 1, and <code>false</code> on oputput 2<br />
145
- The input message is preserved and passed to the output pin, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.
166
+ The input message is preserved and passed to the output pin, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.<br/>
167
+ The node tries to convert any arbitrary input value to a valid boolean value. It converts Homeassistant ***"on"*** and ***"off"*** to true/false values as well.<br/>
146
168
 
147
169
  <br/>
148
170
  <br/>
@@ -251,13 +273,13 @@ The pourpose of this node is to send a sequence of pulsed commands to for exampl
251
273
 
252
274
  **Avaiable Commands**<br />
253
275
  Commands are to be wrote in the format: command:value. For example ***send:200***, ***wait:2000***. Each row represents a command.<br />
254
- <b>send</b><br />
276
+ <br /><b>send</b><br />
255
277
  sends a value. For example: ***send:true*** or ***send:100*** or ***send:Hello***<br />
256
- <b>wait</b><br />
278
+ <br /><b>wait</b><br />
257
279
  wait for specified time (in milliseconds). For example ***wait:500*** waits for 500 milliseconds<br />
258
- <b>restart</b><br />
280
+ <br /><b>restart</b><br />
259
281
  Restart the sequence from the beginning. Use ***restart*** alone, without **:** and extra value. For example ***restart*** <br />
260
- <b>//</b><br />
282
+ <br /><b>//</b><br />
261
283
  comment. For example: ***// This opens the garage***. The comment are ignored, so you can write what you want.<br />
262
284
  <br />
263
285
 
@@ -74,26 +74,12 @@
74
74
 
75
75
  <script type="text/x-red" data-help-name="BlinkerUltimate">
76
76
  <p>
77
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
77
+ SEE THE README FOR HELP CONFIGURING THE NODE
78
78
  </p>
79
79
 
80
- </p>
81
- Output PIN1 : outputs the value true/false<br/>
82
- Output PIN2 : outputs the inverted value false/true<br/>
83
80
  <p>
84
-
85
- <p>The meaning of this node is to blink a light or something else.<br/>
86
- <p>Pass msg.payload = true to start blinking</br>
87
- Pass msg.payload = false to stop blinking</br>
88
- Pass msg.interval = 2000 to change the blinking interval</br>
89
- </p>
90
- PIN1 stop behavior : when the blinker receives the stop message, you can select the behavior of the pin1<br/>
91
- PIN2 stop behavior : when the blinker receives the stop message, you can select the behavior of the pin2<br/>
92
- Autostart : whenever node-red starts, the node can either start blinking or not<br/>
93
- <p>
94
-
81
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
95
82
  </p>
96
-
97
83
 
98
84
  <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
99
85
 
@@ -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,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,88 +172,24 @@
165
172
  <input type="checkbox" id="node-input-restrictinputevaluation" style="display:inline-block; width:auto; vertical-align:top;">
166
173
  &nbsp<label style="width:auto" for="node-input-restrictinputevaluation"> Reject non boolean (true/false) input values</label>
167
174
  </div>
168
-
169
- </script>
170
-
171
- <script type="text/x-red" data-help-name="BooleanLogicUltimate">
172
- <p>
173
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
174
-
175
- </p>
176
-
177
- <p>The node performs Boolean logic on the incoming payloads.<br/>
178
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
179
- <br/><br/>
180
- The node performs some checks on the incoming boolean payloads and outputs results at the same time, as follow:<br/>
181
- - Output "AND": true or false<br/>
182
- - Output "OR": true or false<br/>
183
- - Output "XOR": true or false<br/>
184
-
185
- If you need ***"NAND"*** or ***"NOR"*** gate, just put an **InvertUltimate** node respectively after the "AND" or "OR" pin.
186
-
187
- <b>Inputs count</b><br />
188
- Set the number of different topics to be evaluated. The node will output a message to the flow, after this number of different topics arrives.<br/>
189
- <b> Remember: each input topic must be different. For example, if you set this field to 3, the node expects 3 different topics.</b><br/>
190
-
191
- <br/>
192
- Changing the topic is usually only needed when chaining multiple boolean nodes after each other becuse the topics will then all be the same when delivered to the nodes further down the chain.<br/>
193
- <br/>
194
- The node expects a fixed number of topics (configured in the settings) on which it will operate. It will only output a value
195
- when it has seen the expected number of topics. If it ever sees more than the configured number of topics it will log a message then reset its state and start over.<br/>
196
- <b> Remember: each input topic must be different. For example, if you set "Inputs count" to 3, the node expects 3 different topics.</b><br/>
197
- <br/><br/>
198
- <b>Filter output result</b><br />
199
- <ol>
200
- <li>Output both 'true' and 'false' results: Standard behaviour, the node will output <b>true</b> and <b>false</b> whenever it receives an input and calculate the boolean logics as output.</li>
201
- <li>Output only 'true' results: whenever the node receives an input, it outputs a payload <b>true</b> only if the result of the logic is true. <b>False</b> results are filtered out.</li>
202
- </ol>
203
- <b>filtered</b>: shown on label, means that the node will pass out only <code>true</code> values (Output only 'true' results). <br/>
204
- <br/><br/>
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>
205
179
 
206
- <b>Trigger mode</b><br />
207
- The node can acts ad a standard boolean logic or as single topic triggered boolean logic.<br/>
208
- As single topic triggered boolean logic, the node will evaluate the inputs (and thus will output a payload) only if a specified topic input arrives.<br/>
209
- In a coding perspectives, it acts as follows:<br/>
210
- <code>
211
- if (msg.topic == specified topic)<br/>
212
- {<br/>
213
- If (all other inputs are true) -> outputs true otherwise false<br/>
214
- }<br/>
215
- </code>
216
- <ol>
217
- <li>All topics: standard behaviour, the node will output <b>true</b> and <b>false</b> by evaluating all inputs. Each input change will trigger the node output.</li>
218
- <li>Single topic + only eval others: <u>only whenever the node receives a msg input with the <b>specified topic</b> (having payload = true)</u>, it starts the evaluation of all other inputs as well and outputs the evaluated payload. If the node receives a msg input other than the <b>specified topic</b>), it only retains it's value for the boolean evaluation.</li>
219
- </ol>
220
- Example of trigger mode = Single topic + eval other inputs: <b>SEE THE README FOR AN EXAMPLE</b>
221
- <br/><br/>
222
-
223
- <b> If input states are undefined</b><br />
224
- Every time you create a node or modify the node, all inputs are set to undefined. This means that the node will wait the arrive of all topics (for example 3 topics, if you've selected 3 topics in the option), before it can output a payload. This can be a problem if your logic must be operative as soon as you deploy the flow. To overcome this problem, you can "initialize" all the undefined inputs with True or False.
225
- <ol>
226
- <li>Leave undefined: Standard behaviour, the node will wait all the "undefined" topics to arrive, then starts a flow with the result.</li>
227
- <li>True or False: The node is immediately operative, by force the initialization of the "undefined" inputs with "true" or "false".</li>
228
- </ol>
229
180
  <br/>
230
-
231
- <b>Remember latest input values after reboot</b><br />
232
- If checked, the input values are retained after a node-red reboot. That means, that if you reboot your node-red, you don't need to wait all inputs to arrive and initialize the node, before the node can output a payload.<br/>
233
- Every time you modify the node's config, <b>the retained values are cleared</b>.<br/>
234
181
  <br/>
235
-
236
- <b>Reject non boolean (true/false) input values</b><br />
237
- 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.<br/>
238
182
  <br/>
239
-
183
+ </script>
240
184
 
241
- <i> How inputs are handled:</i><br />
242
- All incoming msg.payloads are converted into a boolean value according to the following rules (this applies to all boolean logic nodes):
243
- <ol>
244
- <li>Boolean values are taken as-is.</li>
245
- <li>For numbers, 0 evaluates to false, all other numbers evaluates to true.</li>
246
- <li>Strings are converted to numbers if they match the format of a decimal value, then the same rule as for numbers are applied. If it does not match, it evaluates to false. Also, the string "true" evaluates to true.</li>
247
- </ol>
248
- <br>
249
- The XOR operation operates in a one, and only one mode, i.e. (A ^ B) ^ C ... ^ n
185
+ <script type="text/x-red" data-help-name="BooleanLogicUltimate">
186
+ <p>
187
+ SEE THE README FOR HELP CONFIGURING THE NODE
188
+ </p>
250
189
 
190
+ <p>
191
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
251
192
  </p>
193
+
194
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
252
195
  </script>
@@ -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();
@@ -77,18 +87,18 @@ module.exports = function (RED) {
77
87
  return;
78
88
  }
79
89
 
80
- // 28/08/2020 inform user about undefined topic or payload
81
- if (!msg.hasOwnProperty("topic") || typeof (msg.topic) == "undefined") {
90
+ // 15/11/2021 inform user about undefined topic or payload
91
+ if (!msg.hasOwnProperty("topic") || msg.topic === undefined || msg.topic === null) {
82
92
  setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid topic!" });
83
93
  return;
84
94
  }
85
- // 28/08/2020 inform user about undefined topic or payload
86
- if (!msg.hasOwnProperty("payload") || typeof (msg.payload) == "undefined") {
87
- setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic });
95
+ // 15/11/2021 inform user about undefined topic or payload
96
+ if (!msg.hasOwnProperty("payload") || msg.payload === undefined || msg.payload === null) {
97
+ setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
88
98
  return;
89
99
  }
90
100
 
91
- // 12/08/2021 Restrict only to true/false and 0/1
101
+ // 12/08/2021 Restrict only to true/false
92
102
  if (node.restrictinputevaluation) {
93
103
  if (msg.payload !== true && msg.payload !== false) {
94
104
  setNodeStatus({ fill: "red", shape: "dot", text: "Received non boolean value from " + msg.topic });
@@ -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
- if (!resAND) { resAND = null };
143
- if (!resOR) { resOR = null };
144
- if (!resXOR) { resXOR = null };
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
- SetResult(resAND, resOR, resXOR, node.config.topic, msg);
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
- SetResult(resAND, resOR, resXOR, node.config.topic, msg);
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) {
@@ -263,6 +283,10 @@ module.exports = function (RED) {
263
283
  res = value;
264
284
  }
265
285
  else if (typeof value === 'number' || typeof value === 'string') {
286
+
287
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
288
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
289
+
266
290
  // Is it formated as a decimal number?
267
291
  if (decimal.test(value)) {
268
292
  var v = parseFloat(value);
@@ -276,30 +300,41 @@ module.exports = function (RED) {
276
300
  return res;
277
301
  };
278
302
 
279
- function SetResult(_valueAND, _valueOR, _valueXOR, optionalTopic, _msg) {
280
- setNodeStatus({ fill: "green", shape: "dot", text: "(AND)" + (_valueAND !== null ? _valueAND : "---") + " (OR)" + (_valueOR !== null ? _valueOR : "---") + " (XOR)" + (_valueXOR !== null ? _valueXOR : "---") });
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 : "---") });
281
316
 
282
317
  var msgAND = null;
283
- if (_valueAND != null) {
284
- msgAND = RED.util.cloneMessage(_msg);
318
+ if (calculatedValueAND != null) {
319
+ msgAND = RED.util.cloneMessage(node.inputMessage);
285
320
  msgAND.topic = optionalTopic === undefined ? "result" : optionalTopic;
286
321
  msgAND.operation = "AND";
287
- msgAND.payload = _valueAND;
322
+ msgAND.payload = calculatedValueAND;
288
323
 
289
324
  }
290
325
  var msgOR = null;
291
- if (_valueOR != null) {
292
- msgOR = RED.util.cloneMessage(_msg);
326
+ if (calculatedValueOR != null) {
327
+ msgOR = RED.util.cloneMessage(node.inputMessage);
293
328
  msgOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
294
329
  msgOR.operation = "OR";
295
- msgOR.payload = _valueOR;
330
+ msgOR.payload = calculatedValueOR;
296
331
  }
297
332
  var msgXOR = null;
298
- if (_valueXOR != null) {
299
- msgXOR = RED.util.cloneMessage(_msg);
333
+ if (calculatedValueXOR != null) {
334
+ msgXOR = RED.util.cloneMessage(node.inputMessage);
300
335
  msgXOR.topic = optionalTopic === undefined ? "result" : optionalTopic;
301
336
  msgXOR.operation = "XOR";
302
- msgXOR.payload = _valueXOR;
337
+ msgXOR.payload = calculatedValueXOR;
303
338
  }
304
339
  node.send([msgAND, msgOR, msgXOR]);
305
340
 
@@ -40,20 +40,20 @@
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>
47
47
 
48
48
  <script type="text/x-red" data-help-name="FilterUltimate">
49
49
  <p>
50
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
51
-
52
- </p>
53
-
54
- <p>The node emits on output "true", only input payloads that are true<br/>
55
- and on the output "false", only input payload that are false.
50
+ SEE THE README FOR HELP CONFIGURING THE NODE
51
+ </p>
52
+
53
+ <p>
54
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
56
55
  </p>
56
+
57
57
  <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
58
58
 
59
59
  </script>
@@ -13,11 +13,9 @@ module.exports = function (RED) {
13
13
  setNodeStatus({ fill: "grey", shape: "dot", text: "Waiting" });
14
14
  this.on('input', function (msg) {
15
15
 
16
- if (!msg.hasOwnProperty("topic")) {
17
- msg.topic = node.config.name || "";
18
- }
19
- if (!msg.hasOwnProperty("payload" || msg.payload === undefined)) {
20
- setNodeStatus({ fill: "red", shape: "dot", text: "No payload property from " + msg.topic });
16
+ // 15/11/2021 inform user about undefined topic or payload
17
+ if (!msg.hasOwnProperty("payload") || msg.payload === undefined || msg.payload === null) {
18
+ setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
21
19
  return;
22
20
  }
23
21
 
@@ -26,7 +24,7 @@ module.exports = function (RED) {
26
24
  bRes = ToBoolean(msg.payload);
27
25
  } catch (error) {
28
26
  }
29
-
27
+
30
28
  if (bRes === undefined || bRes === null) {
31
29
  setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " + msg.payload + " from " + msg.topic });
32
30
  return;
@@ -43,7 +41,7 @@ module.exports = function (RED) {
43
41
  setNodeStatus({ fill: "green", shape: "dot", text: "(Send) false" });
44
42
  node.send([null, msgOut]);
45
43
  }
46
-
44
+
47
45
  });
48
46
 
49
47
 
@@ -56,6 +54,10 @@ module.exports = function (RED) {
56
54
  res = value;
57
55
  }
58
56
  else if (typeof value === 'number' || typeof value === 'string') {
57
+
58
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
59
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
60
+
59
61
  // Is it formated as a decimal number?
60
62
  if (decimal.test(value)) {
61
63
  var v = parseFloat(value);
@@ -75,26 +75,13 @@
75
75
 
76
76
  <script type="text/x-red" data-help-name="ImpulseUltimate">
77
77
  <p>
78
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
79
-
80
- </p>
81
- <p>
82
- The node executes the commands you write in the JSON.<br/>
83
- Avaiable commands are: send, wait (in milliseconds), restart (restarts the sequence) and // (for comment).<br/>
84
- For example<br/><br/>
85
- // Blink a light
86
- send:true<br/>
87
- wait:2000<br/>
88
- send:false<br/>
89
- wait:2000<br/>
90
- restart<br/>
91
- For a complete list of avaiable commands, see the gitHub Homepage.
92
- </div>
93
- </p>
78
+ SEE THE README FOR HELP CONFIGURING THE NODE
79
+ </p>
80
+
94
81
  <p>
95
- <b>Input Message</b><br/>
96
- Send true to start executing the program<br/>
97
- Send false to stop execution<br/>
82
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
98
83
  </p>
84
+
85
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
99
86
 
100
87
  </script>
@@ -77,13 +77,13 @@
77
77
 
78
78
  <script type="text/x-red" data-help-name="InjectUltimate">
79
79
  <p>
80
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
81
-
80
+ SEE THE README FOR HELP CONFIGURING THE NODE
82
81
  </p>
83
-
84
- <p>This node sends TRUE on output 1, FALSE on putput 2 and a TOGGLED value (true/false) on output 3, on every click of the button.<br/>
85
- The status indicator represents the output value.
86
- </p>
87
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
82
+
83
+ <p>
84
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
85
+ </p>
86
+
87
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
88
88
 
89
89
  </script>
@@ -63,20 +63,13 @@
63
63
 
64
64
  <script type="text/x-red" data-help-name="InterruptFlowUltimate">
65
65
  <p>
66
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
67
-
66
+ SEE THE README FOR HELP CONFIGURING THE NODE
68
67
  </p>
69
- <p>The meaning of this node is to interrupt/reactivate flow messages.<br/>
70
- Normally, passes the input messages to the output. If you send a payload with a specific topic (you can set it on the node properties), the node stops sending output messages.<br/>
71
- It can also save the last message received and play later. This is useful if you wish to restore previous state to, for example, a light actuator.<br/>
72
- Please see the <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">README</a> on github for examples.
73
- </p>
68
+
74
69
  <p>
75
- The node will stop output messages, if it receives a payload = false <b>from the specified topic</b>.<br/>
76
- The node will resume output messages, if it receives a payload = true <b>from the specified topic</b>.<br/>
77
- Other that that, as soon as you send payload = false <b>from the specified topic</b>, the node stores the last received payload internally
78
- The node will output the current stored message plus an added property <b>isReplay</b> = true, if it receives a <b>play</b> = true from the specified topic.<br/>
70
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
79
71
  </p>
72
+
80
73
  <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
81
74
 
82
75
  </script>
@@ -26,11 +26,21 @@ module.exports = function (RED) {
26
26
  // 06/11/2019
27
27
  if (!msg.hasOwnProperty("topic") || msg.topic === undefined) msg.topic = "NoTopicReceived";
28
28
  sIncomingTopic = msg.topic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); // Cut unwanted Characters
29
- if (sIncomingTopic == node.sTriggerTopic) {
30
- if (msg.payload !== true && msg.payload !== false) {
31
- setNodeStatus({ fill: "red", shape: "dot", text: "Received non boolean value from " + sIncomingTopic });
29
+ if (sIncomingTopic === node.sTriggerTopic) {
30
+
31
+ // 15/11/2021 inform user about undefined topic or payload
32
+ if (!msg.hasOwnProperty("payload") || msg.payload === undefined || msg.payload === null) {
33
+ setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
32
34
  return;
33
35
  }
36
+
37
+ msg.payload = ToBoolean(msg.payload); // 15/11/2021 Convert input to boolean.
38
+
39
+ // if (msg.payload !== true && msg.payload !== false) {
40
+ // setNodeStatus({ fill: "red", shape: "dot", text: "Received non boolean value from " + sIncomingTopic });
41
+ // return;
42
+ // }
43
+
34
44
  if (msg.hasOwnProperty("play")) {
35
45
  node.currentMsg.isReplay = true;
36
46
  setNodeStatus({ fill: "yellow", shape: "dot", text: "-> replay" });
@@ -72,8 +82,11 @@ module.exports = function (RED) {
72
82
  res = value;
73
83
  }
74
84
  else if (typeof value === 'number' || typeof value === 'string') {
75
- // Is it formated as a decimal number?
76
85
 
86
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
87
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
88
+
89
+ // Is it formated as a decimal number?
77
90
  if (decimal.test(value)) {
78
91
  var v = parseFloat(value);
79
92
  res = v != 0;
@@ -34,13 +34,13 @@
34
34
 
35
35
  <script type="text/x-red" data-help-name="InvertUltimate">
36
36
  <p>
37
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
38
-
39
- </p>
40
-
41
- <p>A node that emits the inverted input value.<br/>
42
- The status indicator represents the output value.
37
+ SEE THE README FOR HELP CONFIGURING THE NODE
43
38
  </p>
44
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
39
+
40
+ <p>
41
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
42
+ </p>
43
+
44
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
45
45
 
46
46
  </script>
@@ -14,32 +14,34 @@ module.exports = function (RED) {
14
14
 
15
15
  this.on('input', function (msg) {
16
16
 
17
- if (msg.hasOwnProperty("payload") && msg.payload !== undefined && msg.payload !== null) {
18
17
 
19
- // 11/11/2021 Clone input message and replace only relevant topics
18
+ // 15/11/2021 inform user about undefined topic or payload
19
+ if (!msg.hasOwnProperty("payload") || msg.payload === undefined || msg.payload === null) {
20
+ setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
21
+ return;
22
+ }
20
23
 
21
- var bRes = null;
22
- try {
23
- bRes = ToBoolean(msg.payload);
24
- } catch (error) {
25
- }
26
- if (bRes === undefined || bRes === null) {
27
- setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " + msg.payload + " from " + msg.topic });
28
- return;
29
- }
30
24
 
31
- var msgOUt = RED.util.cloneMessage(msg);
32
- try {
33
- msgOUt.payload = !bRes;
34
- setNodeStatus({ fill: "green", shape: "dot", text: "(Send) " + msgOUt.payload });
35
- node.send(msgOUt);
36
- } catch (error) {
37
- setNodeStatus({ fill: "red", shape: "dot", text: "Unable to invert the input payload " + bRes });
38
- }
25
+ // 11/11/2021 Clone input message and replace only relevant topics
26
+ var bRes = null;
27
+ try {
28
+ bRes = ToBoolean(msg.payload);
29
+ } catch (error) {
30
+ }
31
+ if (bRes === undefined || bRes === null) {
32
+ setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " + msg.payload + " from " + msg.topic });
33
+ return;
34
+ }
39
35
 
40
- } else {
41
- setNodeStatus({ fill: "red", shape: "dot", text: "No payload from " + msg.topic });
36
+ var msgOUt = RED.util.cloneMessage(msg);
37
+ try {
38
+ msgOUt.payload = !bRes;
39
+ setNodeStatus({ fill: "green", shape: "dot", text: "(Send) " + msgOUt.payload });
40
+ node.send(msgOUt);
41
+ } catch (error) {
42
+ setNodeStatus({ fill: "red", shape: "dot", text: "Unable to invert the input payload " + bRes });
42
43
  }
44
+
43
45
  });
44
46
 
45
47
 
@@ -52,6 +54,10 @@ module.exports = function (RED) {
52
54
  res = value;
53
55
  }
54
56
  else if (typeof value === 'number' || typeof value === 'string') {
57
+
58
+ if (typeof value === "string" && value.toLowerCase() === "on") return true;
59
+ if (typeof value === "string" && value.toLowerCase() === "off") return false;
60
+
55
61
  // Is it formated as a decimal number?
56
62
  if (decimal.test(value)) {
57
63
  var v = parseFloat(value);
@@ -46,14 +46,14 @@
46
46
  </script>
47
47
 
48
48
  <script type="text/x-red" data-help-name="SimpleOutputUltimate">
49
- <p>
50
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
51
-
49
+ <p>
50
+ SEE THE README FOR HELP CONFIGURING THE NODE
52
51
  </p>
53
-
54
- <p>This node replaces the input payload by sendind a message with payload TRUE on output 1 and FALSE on output 2.<br/>
55
-
56
- </p>
57
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
52
+
53
+ <p>
54
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
55
+ </p>
56
+
57
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
58
58
 
59
59
  </script>
@@ -41,13 +41,14 @@
41
41
  </script>
42
42
 
43
43
  <script type="text/x-red" data-help-name="StatusUltimate">
44
- <p>
45
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
46
-
47
- </p>
48
-
49
- <p>This node simply shows the status of the selected msg property<br/>
50
-
44
+ <p>
45
+ SEE THE README FOR HELP CONFIGURING THE NODE
51
46
  </p>
47
+
48
+ <p>
49
+ <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
50
+ </p>
51
+
52
+ <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
52
53
 
53
54
  </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-boolean-logic-ultimate",
3
- "version": "1.0.36",
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": {