node-red-contrib-boolean-logic-ultimate 1.0.51 → 1.0.54
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.
- package/CHANGELOG.md +16 -0
- package/README.md +158 -59
- package/boolean-logic-ultimate/BlinkerUltimate.html +9 -1
- package/boolean-logic-ultimate/BlinkerUltimate.js +6 -28
- package/boolean-logic-ultimate/BooleanLogicUltimate.html +10 -1
- package/boolean-logic-ultimate/BooleanLogicUltimate.js +13 -31
- package/boolean-logic-ultimate/FilterUltimate.html +10 -1
- package/boolean-logic-ultimate/FilterUltimate.js +7 -28
- package/boolean-logic-ultimate/ImpulseUltimate.html +7 -0
- package/boolean-logic-ultimate/ImpulseUltimate.js +5 -2
- package/boolean-logic-ultimate/InterruptFlowUltimate.html +13 -5
- package/boolean-logic-ultimate/InterruptFlowUltimate.js +4 -28
- package/boolean-logic-ultimate/InvertUltimate.js +2 -29
- package/boolean-logic-ultimate/RailwaySwitchUltimate.html +101 -0
- package/boolean-logic-ultimate/RailwaySwitchUltimate.js +81 -0
- package/boolean-logic-ultimate/SumUltimate.html +22 -8
- package/boolean-logic-ultimate/SumUltimate.js +24 -8
- package/boolean-logic-ultimate/toggleUltimate.html +10 -1
- package/boolean-logic-ultimate/toggleUltimate.js +5 -29
- package/boolean-logic-ultimate/utils.js +38 -0
- package/img/railroadSwitchScambio.png +0 -0
- package/img/railwaySwitch.png +0 -0
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
|
|
4
4
|
# CHANGELOG
|
|
5
5
|
|
|
6
|
+
<p>
|
|
7
|
+
<b>Version 1.0.54</b> July 2022<br/>
|
|
8
|
+
- NEW: you can now specify the input property name from witch the node picks up the payload.</br>
|
|
9
|
+
- NEW: added more Homeassistant string compatibility values.</br>
|
|
10
|
+
- Updated the README</br>
|
|
11
|
+
</p>
|
|
12
|
+
<p>
|
|
13
|
+
<b>Version 1.0.53</b> June 2022<br/>
|
|
14
|
+
- NEW: Math Ultimate. The old "Sum" node, now has become a math node, you can peform multipication other than sum.</br>
|
|
15
|
+
- Updated README with samples of Math node.
|
|
16
|
+
</p>
|
|
17
|
+
<p>
|
|
18
|
+
<b>Version 1.0.52</b> Mai 2022<br/>
|
|
19
|
+
- NEW: Railway Switcher Ultimate: new node to switch the input message to an output pin (https://youtu.be/1SjYE7d04u4).</br>
|
|
20
|
+
- Updated README with samples of Railway Switch node.
|
|
21
|
+
</p>
|
|
6
22
|
<p>
|
|
7
23
|
<b>Version 1.0.51</b> February 2022<br/>
|
|
8
24
|
- Blinker Ultimate: fixed minor problem with an orphan timer.</br>
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://www.paypal.me/techtoday)
|
|
11
11
|
[![youtube][youtube-image]][youtube-url]
|
|
12
12
|
|
|
13
|
-
A set of Node-RED enhanced boolean logic and utility nodes, with persistent values after reboot. Compatible also with Homeassistant
|
|
13
|
+
A set of Node-RED enhanced boolean logic and utility nodes, with persistent values after reboot. Compatible also with Homeassistant values.
|
|
14
14
|
|
|
15
15
|
<br/>
|
|
16
16
|
<br/>
|
|
@@ -21,6 +21,22 @@ A set of Node-RED enhanced boolean logic and utility nodes, with persistent valu
|
|
|
21
21
|
<br/>
|
|
22
22
|
<br/>
|
|
23
23
|
|
|
24
|
+
### COMPATIBLES INPUT VALUES
|
|
25
|
+
Other than true/false, all nodes accepts these strings and convert it to true/false. All nodes are compatible with Homeassistant output strings.
|
|
26
|
+
|Input|Translated into|
|
|
27
|
+
|--|--|
|
|
28
|
+
| "on" | true |
|
|
29
|
+
| "off" | false |
|
|
30
|
+
| "active" | true |
|
|
31
|
+
| "inactive" | false |
|
|
32
|
+
| "open" | true |
|
|
33
|
+
| "closed" | false |
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
<br/>
|
|
37
|
+
<br/>
|
|
38
|
+
|
|
39
|
+
|
|
24
40
|
# BOOLEAN LOGIC
|
|
25
41
|
|
|
26
42
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/bl1.png' width='60%'>
|
|
@@ -53,50 +69,24 @@ If you need ***"NAND"*** or ***"NOR"*** gate, just put an **InvertUltimate** nod
|
|
|
53
69
|
|
|
54
70
|
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/>
|
|
55
71
|
You can also set the default values of the topic inputs.<br/>
|
|
56
|
-
The node can convert arbitrary input values to true/false. It supports Homeassistant
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
### CONFIGURATION
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
**Inputs count**
|
|
64
|
-
|
|
65
|
-
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/>
|
|
66
|
-
*Remember: each input topic must be different. For example, if you set this field to 3, the node expects 3 different topics.*
|
|
72
|
+
The node can convert arbitrary input values to true/false. It supports Homeassistant string to boolean conversion as well. For enabling auto conversion, please be sure to disable **Reject non boolean (true/false) input values** <br/>
|
|
67
73
|
|
|
68
74
|
|
|
69
|
-
**Filter output**
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
- 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.
|
|
76
|
+
### NODE CONFIGURATION
|
|
73
77
|
|
|
74
|
-
|
|
78
|
+
|Property|Description|
|
|
79
|
+
|--|--|
|
|
80
|
+
| Inputs count | 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. *Remember: each input topic must be different. For example, if you set this field to 3, the node expects 3 different topics.* |
|
|
81
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
82
|
+
| Filter output | **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. **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. |
|
|
83
|
+
| Trigger mode | **All topics**: standard behaviour, the node will evaluate each input topic and ouputs the values. At each input change, it will output a msg on the flow. **Single topic + eval other inputs**: the node evaluates all the input topics, but only whenever it receives a msg input with the **specified topic**, it outputs a msg to the flow.|
|
|
84
|
+
| If input states are undefined | 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. **Leave undefined**: Standard behaviour, the node will wait all the "undefined" topics to arrive, then starts a flow with the result. **True or False**: The node is immediately operative, by force the initialization of the "undefined" inputs with "true" or "false".|
|
|
85
|
+
| Remember latest input values after reboot | 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. Every time you modify the node's config, <b>the retained values are cleared</b>.|
|
|
86
|
+
| Reject non boolean (true/false) input values | If checked, the node will accept only boolean true/false values. Otherwise, it will try to convert the payload value to a logic true/false boolean. |
|
|
87
|
+
| Delay evaluation (ms) | 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. This option is useful for debouncing pourposes or simply for adding some delay. 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. Another example, if you have many sensors changing state rapidly, you can wait until these sensor reach a quiet state, then evaluate the inputs.|
|
|
75
88
|
|
|
76
|
-
|
|
77
|
-
- Single topic + eval other inputs: the node evaluates all the input topics, but only whenever it receives a msg input with the **specified topic**, it outputs a msg to the flow.
|
|
78
|
-
|
|
79
|
-
**If input states are undefined**
|
|
80
|
-
|
|
81
|
-
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.
|
|
82
|
-
- Leave undefined: Standard behaviour, the node will wait all the "undefined" topics to arrive, then starts a flow with the result.
|
|
83
|
-
- True or False: The node is immediately operative, by force the initialization of the "undefined" inputs with "true" or "false".
|
|
84
|
-
|
|
85
|
-
**Remember latest input values after reboot**
|
|
86
|
-
|
|
87
|
-
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/>
|
|
88
|
-
Every time you modify the node's config, <b>the retained values are cleared</b>.<br/>
|
|
89
|
-
|
|
90
|
-
**Reject non boolean (true/false) input values**
|
|
91
|
-
|
|
92
|
-
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/>
|
|
93
|
-
|
|
94
|
-
**Delay evaluation (ms)**
|
|
95
|
-
|
|
96
|
-
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/>
|
|
97
|
-
This option is useful for debouncing pourposes or simply for adding some delay.<br/>
|
|
98
|
-
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/>
|
|
99
|
-
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/>
|
|
89
|
+
<br/>
|
|
100
90
|
|
|
101
91
|
**INPUT MSG TO THE NODE**
|
|
102
92
|
|
|
@@ -113,19 +103,25 @@ Resets all inputs to undefined.
|
|
|
113
103
|
|
|
114
104
|
# INTERRUPT FLOWS ULTIMATE
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
The interrupt flows is able to stop the input messages to exiting the node.
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
As soon it receives payload = true from this topic, the output messages start to flow out again. <br/>
|
|
120
|
-
The node will output the current stored message plus an added property "isReplay = true", as soon as it receives a ***msg.play = true*** from this topic.<br/>
|
|
121
|
-
The node will clear the current stored message, as soon as it receives a ***msg.reset = true*** from this topic.<br/>
|
|
122
|
-
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/>
|
|
108
|
+
### NODE CONFIGURATION
|
|
123
109
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
110
|
+
|Property|Description|
|
|
111
|
+
|--|--|
|
|
112
|
+
| Trigger by topic | Whenever the node receives a payload = false from this 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. The node will output the current stored message plus an added property "isReplay = true", as soon as it receives a ***msg.play = true*** from this topic. The node will clear the current stored message, as soon as it receives a ***msg.reset = true*** from this topic. |
|
|
113
|
+
| With Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
114
|
+
| Then | This property, allow you to auto toggle the selected start state (pass or block) after a timer has elapsed. You can choose from some pre-defined delays. If you have, for example, an Homekit-Bridged nodeset with a thermostat node or security system node in your flow, once node-red restarts, these homekit nodes output a default message to the flow. Just put an InterruptFlow node with a "block at start" behaviour and a toggle delay enabled behind homekit nodes, to temporary stop the chained nodes to receive the unwanted startup message.|
|
|
127
115
|
|
|
128
|
-
|
|
116
|
+
|
|
117
|
+
<br/>
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
**INPUT MSG WITH "TRIGGER" TOPIC**
|
|
129
125
|
|
|
130
126
|
Pass <code>msg.payload = true</code> to allow messages to pass through</br>
|
|
131
127
|
Pass <code>msg.payload = false</code> to prevent messages from passing through</br>
|
|
@@ -181,7 +177,15 @@ This allow to save the state of a node and then replay it back whenever you want
|
|
|
181
177
|
|
|
182
178
|
Outputs the inverted input. For example true -> false<br />
|
|
183
179
|
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/>
|
|
184
|
-
|
|
180
|
+
|
|
181
|
+
### NODE CONFIGURATION
|
|
182
|
+
|
|
183
|
+
|Property|Description|
|
|
184
|
+
|--|--|
|
|
185
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
186
|
+
|
|
187
|
+
<br/>
|
|
188
|
+
|
|
185
189
|
|
|
186
190
|
<br/>
|
|
187
191
|
<br/>
|
|
@@ -195,7 +199,15 @@ This node has 2 outputs.<br />
|
|
|
195
199
|
If the input payload is true, the node will send <code>true</code> on output 1 and nothing on oputput 2<br />
|
|
196
200
|
If the input payload is false, the node will send nothing on output 1, and <code>false</code> on oputput 2<br />
|
|
197
201
|
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/>
|
|
198
|
-
|
|
202
|
+
|
|
203
|
+
### NODE CONFIGURATION
|
|
204
|
+
|
|
205
|
+
|Property|Description|
|
|
206
|
+
|--|--|
|
|
207
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
208
|
+
|
|
209
|
+
<br/>
|
|
210
|
+
|
|
199
211
|
|
|
200
212
|
<br/>
|
|
201
213
|
<br/>
|
|
@@ -210,6 +222,15 @@ Output PIN1 : outputs the value true/false<br/>
|
|
|
210
222
|
Output PIN2 : outputs the inverted value false/true<br/>
|
|
211
223
|
<br/>
|
|
212
224
|
|
|
225
|
+
### NODE CONFIGURATION
|
|
226
|
+
|
|
227
|
+
|Property|Description|
|
|
228
|
+
|--|--|
|
|
229
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
230
|
+
|
|
231
|
+
<br/>
|
|
232
|
+
|
|
233
|
+
|
|
213
234
|
Pass <code>msg.payload = true</code> to start blinking</br>
|
|
214
235
|
Pass <code>msg.payload = false</code> to stop blinking</br>
|
|
215
236
|
Pass <code>msg.interval = 2000</code> to change the blinking interval</br>
|
|
@@ -237,6 +258,15 @@ Pass <code>msg.interval = 2000</code> to change the blinking interval</br>
|
|
|
237
258
|
The pourpose of this node is to send a message with payload TRUE on the first pin and FALSE on second pin, independently from the msg input.<br />
|
|
238
259
|
This is useful if you need to simply send a true or false payload.
|
|
239
260
|
|
|
261
|
+
### NODE CONFIGURATION
|
|
262
|
+
|
|
263
|
+
|Property|Description|
|
|
264
|
+
|--|--|
|
|
265
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
266
|
+
|
|
267
|
+
<br/>
|
|
268
|
+
|
|
269
|
+
|
|
240
270
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/SimpleOutput.png' width='60%'>
|
|
241
271
|
|
|
242
272
|
<details><summary>CLICK HERE, copy and paste it into your flow</summary>
|
|
@@ -302,6 +332,15 @@ The pourpose of this node is to send a sequence of pulsed commands to for exampl
|
|
|
302
332
|
</code>
|
|
303
333
|
</details>
|
|
304
334
|
|
|
335
|
+
### NODE CONFIGURATION
|
|
336
|
+
|
|
337
|
+
|Property|Description|
|
|
338
|
+
|--|--|
|
|
339
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
340
|
+
|
|
341
|
+
<br/>
|
|
342
|
+
|
|
343
|
+
|
|
305
344
|
**Avaiable Commands**<br />
|
|
306
345
|
Commands are to be wrote in the format: command:value. For example ***send:200***, ***wait:2000***. Each row represents a command.<br />
|
|
307
346
|
<br /><b>send</b><br />
|
|
@@ -326,17 +365,27 @@ Pass <code>msg.payload = false</code> to the node to stop the running sequence</
|
|
|
326
365
|
<br/>
|
|
327
366
|
<br/>
|
|
328
367
|
|
|
329
|
-
#
|
|
368
|
+
# MATH ULTIMATE
|
|
369
|
+
|
|
370
|
+
The pourpose of this node is to do maths on the incoming values. Each incoming message MUST HAVE OWN TOPIC.<br />
|
|
330
371
|
|
|
331
|
-
The pourpose of this node is to sum the incoming values. Each incoming message MUST HAVE OWN TOPIC.<br />
|
|
332
372
|
|
|
333
373
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/sum.png' width='60%'>
|
|
334
374
|
<details><summary>CLICK HERE, copy and paste it into your flow</summary>
|
|
335
375
|
<code>
|
|
336
|
-
[{"id":"05b6ce0cb476abd5","type":"SumUltimate","z":"
|
|
376
|
+
[{"id":"05b6ce0cb476abd5","type":"SumUltimate","z":"2bf641f4b8742755","name":"Multiply","property":"payload","math":"multiply","x":400,"y":180,"wires":[["567aa6a9719e463e"]]},{"id":"6744e01b88d820b9","type":"inject","z":"2bf641f4b8742755","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Wh Washing machine","payload":"10","payloadType":"num","x":190,"y":180,"wires":[["05b6ce0cb476abd5"]]},{"id":"75823dbc7db78c3c","type":"inject","z":"2bf641f4b8742755","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Cost per KWh","payload":"20","payloadType":"num","x":160,"y":220,"wires":[["05b6ce0cb476abd5"]]},{"id":"567aa6a9719e463e","type":"debug","z":"2bf641f4b8742755","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":530,"y":180,"wires":[]},{"id":"1793931ba218bc1d","type":"inject","z":"2bf641f4b8742755","name":"Reset","props":[{"p":"reset","v":"","vt":"date"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":260,"wires":[["05b6ce0cb476abd5"]]},{"id":"0b3277af03f546d4","type":"comment","z":"2bf641f4b8742755","name":"Getting results, (Sum, Multiply etc...) from the MATH node.","info":"","x":270,"y":140,"wires":[]}]
|
|
337
377
|
</code>
|
|
338
378
|
</details>
|
|
339
379
|
|
|
380
|
+
### NODE CONFIGURATION
|
|
381
|
+
|
|
382
|
+
|Property|Description|
|
|
383
|
+
|--|--|
|
|
384
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
385
|
+
|
|
386
|
+
<br/>
|
|
387
|
+
|
|
388
|
+
|
|
340
389
|
**INPUT**<br />
|
|
341
390
|
|
|
342
391
|
<br /><b>msg.reset</b><br />
|
|
@@ -348,9 +397,9 @@ resets the values to zero.
|
|
|
348
397
|
|
|
349
398
|
<pre>
|
|
350
399
|
{
|
|
351
|
-
"payload": 30, // This is the
|
|
352
|
-
"topic": "
|
|
353
|
-
"average": 15, // This is the
|
|
400
|
+
"payload": 30, // This is the math result
|
|
401
|
+
"topic": "MyMath", // Node Topic
|
|
402
|
+
"average": 15, // This is the AVERAGE, in case of SUM
|
|
354
403
|
"measurements": 2 // This is the number of topics that have been evaluated
|
|
355
404
|
}
|
|
356
405
|
</pre>
|
|
@@ -363,13 +412,63 @@ br/>
|
|
|
363
412
|
|
|
364
413
|
# TOGGLE ULTIMATE
|
|
365
414
|
|
|
366
|
-
The pourpose of this node is to toggle between true/false
|
|
415
|
+
The pourpose of this node is to toggle between true/false, everytime an inboud message arrives.<br />
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
### NODE CONFIGURATION
|
|
367
419
|
|
|
420
|
+
|Property|Description|
|
|
421
|
+
|--|--|
|
|
422
|
+
| Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
423
|
+
|
|
424
|
+
<br/>
|
|
368
425
|
|
|
369
426
|
**INPUT**<br />
|
|
370
427
|
|
|
371
428
|
Any message that arrives on input, will be passwd through to the output with the payload toggled between true and false.
|
|
372
429
|
|
|
430
|
+
<br/>
|
|
431
|
+
<br/>
|
|
432
|
+
<br/>
|
|
433
|
+
<br/>
|
|
434
|
+
<br/>
|
|
435
|
+
|
|
436
|
+
# RAILWAY SWITCH ULTIMATE
|
|
437
|
+
|
|
438
|
+
The railway switcher, switches the input msg flow to one ot the two output pins (upper or lower).
|
|
439
|
+
|
|
440
|
+
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/railroadSwitchScambio.png' width='80%'>
|
|
441
|
+
|
|
442
|
+
### NODE CONFIGURATION
|
|
443
|
+
|
|
444
|
+
|Property|Description|
|
|
445
|
+
|--|--|
|
|
446
|
+
| Switcher topic | Whenever the node receives a payload from this **topic**, it switches the input messages to an output PIN. |
|
|
447
|
+
| With Input | Set the property where the input payload is. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
448
|
+
| Then | This property, allow you to auto toggle the selected start state after some time. |
|
|
449
|
+
|
|
450
|
+
<br/>
|
|
451
|
+
|
|
452
|
+
</br>
|
|
453
|
+
</br>
|
|
454
|
+
|
|
455
|
+
**INPUT MSG WITH "TRIGGER" TOPIC**
|
|
456
|
+
|
|
457
|
+
Pass <code>msg.payload = false</code> switches the msg input to the UPPER PIN</br>
|
|
458
|
+
Pass <code>msg.payload = true</code> switches the msg input to the LOWER PIN</br>
|
|
459
|
+
|
|
460
|
+
</br>
|
|
461
|
+
|
|
462
|
+
See the example below.<br/>
|
|
463
|
+
|
|
464
|
+
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/railwaySwitch.png' width='60%'>
|
|
465
|
+
|
|
466
|
+
Copy and paste it into your flow
|
|
467
|
+
```javascript
|
|
468
|
+
[{"id":"a6993d5187f05c0a","type":"RailwaySwitchUltimate","z":"e5b506b72b42922e","name":"Railway Switch","triggertopic":"trigger","initializewith":"0","autoToggle":"0","x":490,"y":180,"wires":[["51e7df8da0bd8d67"],["7f33b14e12c91744"]]},{"id":"2e3014226290f678","type":"InjectUltimate","z":"e5b506b72b42922e","name":"Sample message","topic":"Train","curVal":true,"x":180,"y":140,"wires":[["a6993d5187f05c0a"],[],[]]},{"id":"f6f80cd77a65073e","type":"InjectUltimate","z":"e5b506b72b42922e","name":"Railway switcher","topic":"trigger","curVal":true,"x":180,"y":220,"wires":[[],[],["a6993d5187f05c0a"]]},{"id":"51e7df8da0bd8d67","type":"debug","z":"e5b506b72b42922e","name":"Upper railway","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"topic","statusType":"msg","x":720,"y":140,"wires":[]},{"id":"7f33b14e12c91744","type":"debug","z":"e5b506b72b42922e","name":"Lower railway","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"topic","statusType":"msg","x":720,"y":220,"wires":[]},{"id":"8716120e94a7b6ee","type":"comment","z":"e5b506b72b42922e","name":"Switch between railways","info":"","x":190,"y":80,"wires":[]}]
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
|
|
373
472
|
|
|
374
473
|
|
|
375
474
|
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
stopbehaviorPIN2: { value: "0" },
|
|
9
9
|
blinkfrequency: { value: "500" },
|
|
10
10
|
initializewith: { value: "0" },
|
|
11
|
+
payloadPropName: { value: "payload", required: false }
|
|
11
12
|
},
|
|
12
13
|
inputs: 1,
|
|
13
14
|
outputs: 2,
|
|
@@ -30,6 +31,10 @@
|
|
|
30
31
|
},
|
|
31
32
|
paletteLabel: function () {
|
|
32
33
|
return "BlinkerUltimate";
|
|
34
|
+
},
|
|
35
|
+
oneditprepare: function () {
|
|
36
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
37
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
33
38
|
}
|
|
34
39
|
});
|
|
35
40
|
</script>
|
|
@@ -45,7 +50,10 @@
|
|
|
45
50
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
46
51
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
47
52
|
</div>
|
|
48
|
-
|
|
53
|
+
<div class="form-row">
|
|
54
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
55
|
+
<input type="text" id="node-input-payloadPropName">
|
|
56
|
+
</div>
|
|
49
57
|
<div class="form-row">
|
|
50
58
|
<label for="node-input-blinkfrequency"><i class="fa fa-clock-o"></i> Blink every (in milliseconds)</label>
|
|
51
59
|
<input type="text" id="node-input-blinkfrequency" placeholder="Example: 500">
|
|
@@ -41,9 +41,13 @@ module.exports = function (RED) {
|
|
|
41
41
|
setNodeStatus({ fill: "red", shape: "dot", text: "Invalid interval received" });
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
|
|
45
|
+
const utils = require("./utils.js");
|
|
46
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
47
|
+
|
|
48
|
+
if (sPayload !== undefined) {
|
|
45
49
|
// 06/11/2019
|
|
46
|
-
if (ToBoolean(
|
|
50
|
+
if (utils.ToBoolean(sPayload) === true) {
|
|
47
51
|
if (node.tBlinker !== null) clearInterval(node.tBlinker);
|
|
48
52
|
node.tBlinker = setInterval(handleTimer, node.blinkfrequency); // Start the timer that handles the queue of telegrams
|
|
49
53
|
node.isBlinking = true;
|
|
@@ -68,32 +72,6 @@ module.exports = function (RED) {
|
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
|
|
71
|
-
function ToBoolean(value) {
|
|
72
|
-
let res = false;
|
|
73
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
74
|
-
|
|
75
|
-
if (typeof value === 'boolean') {
|
|
76
|
-
res = value;
|
|
77
|
-
}
|
|
78
|
-
else if (typeof value === 'number' || typeof value === 'string') {
|
|
79
|
-
|
|
80
|
-
if (typeof value === "string" && value.toLowerCase() === "on") return true;
|
|
81
|
-
if (typeof value === "string" && value.toLowerCase() === "off") return false;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// Is it formated as a decimal number?
|
|
85
|
-
if (decimal.test(value)) {
|
|
86
|
-
res = parseFloat(value) != 0;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
res = value.toLowerCase() === "true";
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return res;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
|
|
97
75
|
function handleTimer() {
|
|
98
76
|
node.curPayload = !node.curPayload;
|
|
99
77
|
node.send([{ payload: node.curPayload }, { payload: !node.curPayload }]);
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
name: {
|
|
7
7
|
value: ""
|
|
8
8
|
},
|
|
9
|
+
payloadPropName: { value: "payload", required: false },
|
|
9
10
|
filtertrue: { value: "both" },
|
|
10
11
|
persist: { value: true },
|
|
11
12
|
sInitializeWith: { value: "WaitForPayload" },
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
return v !== undefined && v.length > 0;
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
|
-
restrictinputevaluation: { value:
|
|
37
|
+
restrictinputevaluation: { value: false },
|
|
37
38
|
delayEvaluation: { value: 0 }
|
|
38
39
|
},
|
|
39
40
|
inputs: 1,
|
|
@@ -77,6 +78,10 @@
|
|
|
77
78
|
return "BooleanLogicUltimate";
|
|
78
79
|
},
|
|
79
80
|
oneditprepare: function () {
|
|
81
|
+
|
|
82
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
83
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
84
|
+
|
|
80
85
|
// Add write and response as default for existing nodes like was default before
|
|
81
86
|
if (this.outputtriggeredby === 'all') {
|
|
82
87
|
$("#triggertopic").hide()
|
|
@@ -131,6 +136,10 @@
|
|
|
131
136
|
<div class="form-row">
|
|
132
137
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
133
138
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
139
|
+
</div>
|
|
140
|
+
<div class="form-row">
|
|
141
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
142
|
+
<input type="text" id="node-input-payloadPropName">
|
|
134
143
|
</div>
|
|
135
144
|
<div class="form-row">
|
|
136
145
|
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
|
@@ -94,23 +94,27 @@ module.exports = function (RED) {
|
|
|
94
94
|
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid topic!" });
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
var topic = msg.topic;
|
|
100
|
+
const utils = require("./utils.js");
|
|
101
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
102
102
|
|
|
103
103
|
// 12/08/2021 Restrict only to true/false
|
|
104
104
|
if (node.restrictinputevaluation) {
|
|
105
|
-
if (
|
|
105
|
+
if (sPayload !== true && sPayload !== false) {
|
|
106
106
|
setNodeStatus({ fill: "red", shape: "dot", text: "Received non boolean value from " + msg.topic });
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
var
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
var value = utils.ToBoolean(sPayload);
|
|
112
|
+
|
|
113
|
+
// 15/11/2021 inform user about undefined topic or payload
|
|
114
|
+
if (sPayload === undefined) {
|
|
115
|
+
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
114
118
|
|
|
115
119
|
// 14/08/2019 if inputs are initialized, remove a "dummy" item from the state's array, as soon as new topic arrives
|
|
116
120
|
if (node.sInitializeWith !== "WaitForPayload") {
|
|
@@ -277,29 +281,7 @@ module.exports = function (RED) {
|
|
|
277
281
|
return res;
|
|
278
282
|
}
|
|
279
283
|
|
|
280
|
-
function ToBoolean(value) {
|
|
281
|
-
let res = false;
|
|
282
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
283
|
-
|
|
284
|
-
if (typeof value === 'boolean') {
|
|
285
|
-
res = value;
|
|
286
|
-
}
|
|
287
|
-
else if (typeof value === 'number' || typeof value === 'string') {
|
|
288
|
-
|
|
289
|
-
if (typeof value === "string" && value.toLowerCase() === "on") return true;
|
|
290
|
-
if (typeof value === "string" && value.toLowerCase() === "off") return false;
|
|
291
284
|
|
|
292
|
-
// Is it formated as a decimal number?
|
|
293
|
-
if (decimal.test(value)) {
|
|
294
|
-
res = parseFloat(value) != 0;
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
res = value.toLowerCase() === "true";
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return res;
|
|
302
|
-
};
|
|
303
285
|
|
|
304
286
|
function outputResult() {
|
|
305
287
|
let optionalTopic = node.config.topic;
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {
|
|
7
7
|
value: "Filter"
|
|
8
|
-
}
|
|
8
|
+
},
|
|
9
|
+
payloadPropName: { value: "payload", required: false }
|
|
9
10
|
},
|
|
10
11
|
inputs: 1,
|
|
11
12
|
outputs: 2,
|
|
@@ -29,6 +30,10 @@
|
|
|
29
30
|
},
|
|
30
31
|
paletteLabel: function () {
|
|
31
32
|
return "FilterUltimate";
|
|
33
|
+
},
|
|
34
|
+
oneditprepare: function () {
|
|
35
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
36
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
32
37
|
}
|
|
33
38
|
});
|
|
34
39
|
</script>
|
|
@@ -44,6 +49,10 @@
|
|
|
44
49
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
45
50
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
46
51
|
</div>
|
|
52
|
+
<div class="form-row">
|
|
53
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
54
|
+
<input type="text" id="node-input-payloadPropName">
|
|
55
|
+
</div>
|
|
47
56
|
</script>
|
|
48
57
|
|
|
49
58
|
<script type="text/x-red" data-help-name="FilterUltimate">
|
|
@@ -13,20 +13,24 @@ module.exports = function (RED) {
|
|
|
13
13
|
setNodeStatus({ fill: "grey", shape: "dot", text: "Waiting" });
|
|
14
14
|
this.on('input', function (msg) {
|
|
15
15
|
|
|
16
|
+
const utils = require("./utils.js");
|
|
17
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
18
|
+
|
|
16
19
|
// 15/11/2021 inform user about undefined topic or payload
|
|
17
|
-
if (
|
|
20
|
+
if (sPayload=== undefined ) {
|
|
18
21
|
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
19
22
|
return;
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
|
|
22
26
|
var bRes = null;
|
|
23
27
|
try {
|
|
24
|
-
bRes = ToBoolean(
|
|
28
|
+
bRes = utils.ToBoolean(sPayload);
|
|
25
29
|
} catch (error) {
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
if (bRes === undefined || bRes === null) {
|
|
29
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " +
|
|
33
|
+
setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " + sPayload + " from " + msg.topic });
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
36
|
|
|
@@ -44,31 +48,6 @@ module.exports = function (RED) {
|
|
|
44
48
|
|
|
45
49
|
});
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
function ToBoolean(value) {
|
|
50
|
-
let res = false;
|
|
51
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
52
|
-
|
|
53
|
-
if (typeof value === 'boolean') {
|
|
54
|
-
res = value;
|
|
55
|
-
}
|
|
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
|
-
|
|
61
|
-
// Is it formated as a decimal number?
|
|
62
|
-
if (decimal.test(value)) {
|
|
63
|
-
res = parseFloat(value) != 0;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
res = value.toLowerCase() === "true";
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return res;
|
|
71
|
-
};
|
|
72
51
|
}
|
|
73
52
|
|
|
74
53
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name: { value: "" },
|
|
7
7
|
commandText: { value: "// Open garage door\nsend:true\nwait:1000\nsend:false" },
|
|
8
|
+
payloadPropName: { value: "payload", required: false }
|
|
8
9
|
},
|
|
9
10
|
inputs: 1,
|
|
10
11
|
outputs: 1,
|
|
@@ -30,6 +31,8 @@
|
|
|
30
31
|
mode: 'ace/mode/text',
|
|
31
32
|
value: node.commandText
|
|
32
33
|
});
|
|
34
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
35
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
33
36
|
},
|
|
34
37
|
oneditsave: function () {
|
|
35
38
|
var node = this;
|
|
@@ -57,6 +60,10 @@
|
|
|
57
60
|
<div class="form-row">
|
|
58
61
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
59
62
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
63
|
+
</div>
|
|
64
|
+
<div class="form-row">
|
|
65
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
66
|
+
<input type="text" id="node-input-payloadPropName">
|
|
60
67
|
</div>
|
|
61
68
|
<div class="form-row" >
|
|
62
69
|
<label style="width:300px;" for="node-input-commandText"><i class="fa fa-tasks"></i> Commands (one command per row)</label>
|
|
@@ -90,15 +90,18 @@ module.exports = function (RED) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
this.on('input', function (msg) {
|
|
93
|
+
|
|
94
|
+
const utils = require("./utils.js");
|
|
95
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
93
96
|
|
|
94
|
-
if (
|
|
97
|
+
if (sPayload === true) {
|
|
95
98
|
if (node.isPlaying) {
|
|
96
99
|
node.setNodeStatus({ fill: "yellow", shape: "ring", text: "Already running. Stop me first." });
|
|
97
100
|
return;
|
|
98
101
|
}
|
|
99
102
|
avvio();
|
|
100
103
|
|
|
101
|
-
} else if (
|
|
104
|
+
} else if (sPayload === false) {
|
|
102
105
|
if (node.timerWait !== null) clearTimeout(node.timerWait);
|
|
103
106
|
node.isPlaying = false;
|
|
104
107
|
node.setNodeStatus({ fill: "red", shape: "dot", text: "Forced stop" });
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
name: { value: "Interrupt Flow" },
|
|
7
7
|
triggertopic: { value: "trigger" },
|
|
8
8
|
initializewith: { value: "1" },
|
|
9
|
-
autoToggle: { value: "0" }
|
|
9
|
+
autoToggle: { value: "0" },
|
|
10
|
+
payloadPropName: { value: "payload", required: false }
|
|
10
11
|
},
|
|
11
12
|
inputs: 1,
|
|
12
13
|
outputs: 1,
|
|
@@ -30,6 +31,10 @@
|
|
|
30
31
|
},
|
|
31
32
|
paletteLabel: function () {
|
|
32
33
|
return "InterruptFlowUltimate";
|
|
34
|
+
},
|
|
35
|
+
oneditprepare: function () {
|
|
36
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
37
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
33
38
|
}
|
|
34
39
|
});
|
|
35
40
|
</script>
|
|
@@ -45,16 +50,19 @@
|
|
|
45
50
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
46
51
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
47
52
|
</div>
|
|
48
|
-
|
|
49
53
|
<div class="form-row">
|
|
50
54
|
<label for="node-input-triggertopic"><i class="icon-tag"></i> Trigger by topic</label>
|
|
51
55
|
<input type="text" id="node-input-triggertopic" placeholder="Name">
|
|
52
|
-
|
|
56
|
+
</div>
|
|
57
|
+
<div class="form-row">
|
|
58
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> With Input</label>
|
|
59
|
+
<input type="text" id="node-input-payloadPropName">
|
|
60
|
+
</div>
|
|
61
|
+
<div><i>Whenever the node receives a msg with false from this topic,<br/> it stops output messages to the flow.<br/>As soon it receives a message with true from this topic,<br/>the output messages start to flow out again.
|
|
53
62
|
<br/>The node will output the current stored message<br/>plus an added property "isReplay = true",<br/>as soon as it receives a "play" = true from this topic.</br>
|
|
54
63
|
The node will clear the current stored message, as soon as it receives a "msg.reset = true" from this topic.
|
|
55
64
|
</i></div>
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
<br/>
|
|
58
66
|
<div class="form-row">
|
|
59
67
|
<label style="width:160px" for="node-input-initializewith"><i class="fa fa-home"></i> At node-red start</label>
|
|
60
68
|
<select type="text" id="node-input-initializewith" placeholder="">
|
|
@@ -43,13 +43,14 @@ module.exports = function (RED) {
|
|
|
43
43
|
sIncomingTopic = msg.topic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); // Cut unwanted Characters
|
|
44
44
|
if (sIncomingTopic === node.sTriggerTopic) {
|
|
45
45
|
|
|
46
|
+
const utils = require("./utils.js");
|
|
47
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
46
48
|
// 15/11/2021 inform user about undefined topic or payload
|
|
47
|
-
if (
|
|
49
|
+
if (sPayload === undefined ) {
|
|
48
50
|
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
49
51
|
return;
|
|
50
52
|
}
|
|
51
|
-
|
|
52
|
-
msg.payload = ToBoolean(msg.payload); // 15/11/2021 Convert input to boolean.
|
|
53
|
+
msg.payload = utils.ToBoolean(sPayload); // 15/11/2021 Convert input to boolean.
|
|
53
54
|
|
|
54
55
|
// 28/01/2022 Stop autotoggle
|
|
55
56
|
if (node.timerAutoToggle !== null) clearInterval(node.timerAutoToggle);
|
|
@@ -93,31 +94,6 @@ module.exports = function (RED) {
|
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
function ToBoolean(value) {
|
|
99
|
-
let res = false;
|
|
100
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
101
|
-
|
|
102
|
-
if (typeof value === 'boolean') {
|
|
103
|
-
res = value;
|
|
104
|
-
}
|
|
105
|
-
else if (typeof value === 'number' || typeof value === 'string') {
|
|
106
|
-
|
|
107
|
-
if (typeof value === "string" && value.toLowerCase() === "on") return true;
|
|
108
|
-
if (typeof value === "string" && value.toLowerCase() === "off") return false;
|
|
109
|
-
|
|
110
|
-
// Is it formated as a decimal number?
|
|
111
|
-
if (decimal.test(value)) {
|
|
112
|
-
res = parseFloat(value) != 0;
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
res = value.toLowerCase() === "true";
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return res;
|
|
120
|
-
};
|
|
121
97
|
}
|
|
122
98
|
|
|
123
99
|
|
|
@@ -23,9 +23,10 @@ module.exports = function (RED) {
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
// 11/11/2021 Clone input message and replace only relevant topics
|
|
26
|
+
const utils = require("./utils.js");
|
|
26
27
|
var bRes = null;
|
|
27
28
|
try {
|
|
28
|
-
bRes = ToBoolean(msg.payload);
|
|
29
|
+
bRes = utils.ToBoolean(msg.payload);
|
|
29
30
|
} catch (error) {
|
|
30
31
|
}
|
|
31
32
|
if (bRes === undefined || bRes === null) {
|
|
@@ -44,34 +45,6 @@ module.exports = function (RED) {
|
|
|
44
45
|
|
|
45
46
|
});
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
function ToBoolean(value) {
|
|
50
|
-
let res = false;
|
|
51
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
52
|
-
|
|
53
|
-
if (typeof value === 'boolean') {
|
|
54
|
-
res = value;
|
|
55
|
-
}
|
|
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
|
-
|
|
61
|
-
// Is it formated as a decimal number?
|
|
62
|
-
if (decimal.test(value)) {
|
|
63
|
-
res = parseFloat(value) != 0;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
res = value.toLowerCase() === "true";
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return res;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
48
|
}
|
|
76
49
|
|
|
77
50
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('RailwaySwitchUltimate', {
|
|
3
|
+
category: 'boolean logic ultimate',
|
|
4
|
+
color: '#ff8080',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: { value: "Railway Switch" },
|
|
7
|
+
triggertopic: { value: "trigger" },
|
|
8
|
+
initializewith: { value: "0" },
|
|
9
|
+
autoToggle: { value: "0" },
|
|
10
|
+
payloadPropName: { value: "payload", required: false }
|
|
11
|
+
},
|
|
12
|
+
inputs: 1,
|
|
13
|
+
outputs: 2,
|
|
14
|
+
outputLabels: function (i) {
|
|
15
|
+
var ret = "";
|
|
16
|
+
switch (i) {
|
|
17
|
+
case 0:
|
|
18
|
+
return "Upper PIN";
|
|
19
|
+
break;
|
|
20
|
+
case 1:
|
|
21
|
+
return "Lower PIN";
|
|
22
|
+
break;
|
|
23
|
+
default:
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
icon: "font-awesome/fa-train",
|
|
28
|
+
label:
|
|
29
|
+
function () {
|
|
30
|
+
return (this.name || "Switch") + " (" + this.triggertopic + ")";
|
|
31
|
+
},
|
|
32
|
+
paletteLabel: function () {
|
|
33
|
+
return "RailwaySwitchUltimate";
|
|
34
|
+
},
|
|
35
|
+
oneditprepare: function () {
|
|
36
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
37
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<script type="text/x-red" data-template-name="RailwaySwitchUltimate">
|
|
43
|
+
<div class="form-row">
|
|
44
|
+
<b>Railway Switch Ultimate</b>    <span style="color:red"><i class="fa fa-question-circle"></i> <a target="_blank" href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate"><u>Help online</u></a></span>
|
|
45
|
+
   <span style="color:red"><i class="fa fa-youtube-play"></i> <a target="_blank" href="https://youtu.be/1SjYE7d04u4"><u>Youtube Sample</u></a></span>
|
|
46
|
+
<br/>
|
|
47
|
+
<br/>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
51
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="form-row">
|
|
55
|
+
<label for="node-input-triggertopic"><i class="icon-tag"></i> Switcher topic</label>
|
|
56
|
+
<input type="text" id="node-input-triggertopic" placeholder="Name">
|
|
57
|
+
</div>
|
|
58
|
+
<div class="form-row">
|
|
59
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> With Input</label>
|
|
60
|
+
<input type="text" id="node-input-payloadPropName">
|
|
61
|
+
</div>
|
|
62
|
+
<div><i>An input msg having this topic and msg true or false<br/>will trigger the railway switch between the two output PINs<br/>
|
|
63
|
+
false switches to the upper PIN<br/>
|
|
64
|
+
true switches to the lower PIN<br/>
|
|
65
|
+
</i></div>
|
|
66
|
+
<br/>
|
|
67
|
+
<div class="form-row">
|
|
68
|
+
<label style="width:160px" for="node-input-initializewith"><i class="fa fa-home"></i> At node-red start</label>
|
|
69
|
+
<select type="text" id="node-input-initializewith" placeholder="" style="width:250px">
|
|
70
|
+
<option value="0">Flow messages to the upper PIN</option>
|
|
71
|
+
<option value="1">Flow messages to the lower PIN</option>
|
|
72
|
+
</select>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="form-row">
|
|
75
|
+
<label style="width:160px" for="node-input-autoToggle"><i class="fa fa-hourglass-o"></i> Then</label>
|
|
76
|
+
<select type="text" id="node-input-autoToggle" placeholder="" style="width:250px">
|
|
77
|
+
<option value="0">Nothing</option>
|
|
78
|
+
<option value="10">Toggle above option after 10 seconds</option>
|
|
79
|
+
<option value="20">Toggle above option after 20 seconds</option>
|
|
80
|
+
<option value="30">Toggle above option after 30 seconds</option>
|
|
81
|
+
<option value="40">Toggle above option after 40 seconds</option>
|
|
82
|
+
<option value="50">Toggle above option after 50 seconds</option>
|
|
83
|
+
<option value="60">Toggle above option after 60 seconds</option>
|
|
84
|
+
<option value="90">Toggle above option after 90 seconds</option>
|
|
85
|
+
<option value="120">Toggle above option after 120 seconds</option>
|
|
86
|
+
</select>
|
|
87
|
+
</div>
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<script type="text/x-red" data-help-name="RailwaySwitchUltimate">
|
|
91
|
+
<p>
|
|
92
|
+
SEE THE README FOR HELP CONFIGURING THE NODE
|
|
93
|
+
</p>
|
|
94
|
+
|
|
95
|
+
<p>
|
|
96
|
+
<a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">Click here to learn how to configure the node.</a>
|
|
97
|
+
</p>
|
|
98
|
+
|
|
99
|
+
<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>
|
|
100
|
+
|
|
101
|
+
</script>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function RailwaySwitchUltimate(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
this.config = config;
|
|
5
|
+
var node = this;
|
|
6
|
+
node.currentMsg = {}; // Stores current payload
|
|
7
|
+
node.sTriggerTopic = node.config.triggertopic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') || "trigger"; // Topic controlling the iRailway
|
|
8
|
+
node.iRailway = Number(node.config.initializewith); // Railway selector
|
|
9
|
+
node.autoToggle = config.autoToggle === undefined ? 0 : parseInt(config.autoToggle); // Auto toggle the selected "initializewith" after a while (useful for homekit bridged, that sends junk after start)
|
|
10
|
+
node.timerAutoToggle = null;
|
|
11
|
+
|
|
12
|
+
function setNodeStatus({ fill, shape, text }) {
|
|
13
|
+
let dDate = new Date();
|
|
14
|
+
node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
node.alignStatus = () => {
|
|
18
|
+
let sAutoToggle = node.autoToggle > 0 ? " (Autotoggle in " + node.autoToggle + "s)" : "";
|
|
19
|
+
if (node.iRailway === 0) {
|
|
20
|
+
setNodeStatus({ fill: "green", shape: "dot", text: "-> UPPER PIN" + sAutoToggle });
|
|
21
|
+
} else {
|
|
22
|
+
setNodeStatus({ fill: "blue", shape: "dot", text: "-> LOWER PIN" + sAutoToggle });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (node.autoToggle > 0) {
|
|
27
|
+
node.timerAutoToggle = setTimeout(() => {
|
|
28
|
+
node.autoToggle = 0;
|
|
29
|
+
node.iRailway === 0 ? node.iRailway = 1 : node.iRailway = 0;
|
|
30
|
+
node.alignStatus();
|
|
31
|
+
}, node.autoToggle * 1000);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
node.alignStatus();
|
|
35
|
+
|
|
36
|
+
this.on('input', function (msg) {
|
|
37
|
+
var sIncomingTopic = "";
|
|
38
|
+
if (msg.hasOwnProperty("topic")) {
|
|
39
|
+
// 06/11/2019
|
|
40
|
+
if (!msg.hasOwnProperty("topic") || msg.topic === undefined) msg.topic = "NoTopicReceived";
|
|
41
|
+
sIncomingTopic = msg.topic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); // Cut unwanted Characters
|
|
42
|
+
if (sIncomingTopic === node.sTriggerTopic) {
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const utils = require("./utils.js");
|
|
46
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
47
|
+
|
|
48
|
+
// 15/11/2021 inform user about undefined topic or payload
|
|
49
|
+
if (sPayload === undefined ) {
|
|
50
|
+
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
msg.payload = utils.ToBoolean(sPayload); // 15/11/2021 Convert input to boolean.
|
|
55
|
+
|
|
56
|
+
// 28/01/2022 Stop autotoggle
|
|
57
|
+
if (node.timerAutoToggle !== null) clearInterval(node.timerAutoToggle);
|
|
58
|
+
|
|
59
|
+
if (msg.payload === false) node.iRailway = 0;
|
|
60
|
+
if (msg.payload === true) node.iRailway = 1;
|
|
61
|
+
if (node.iRailway === 0) {
|
|
62
|
+
setNodeStatus({ fill: "green", shape: "dot", text: "-> UPPER PIN" });
|
|
63
|
+
} else {
|
|
64
|
+
setNodeStatus({ fill: "blue", shape: "dot", text: "-> LOWER PIN" });
|
|
65
|
+
}
|
|
66
|
+
return; // DONT'S SEND THIS MESSAGE
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
node.currentMsg = RED.util.cloneMessage(msg);
|
|
70
|
+
if (node.iRailway === 0) {
|
|
71
|
+
node.send([msg, null]);
|
|
72
|
+
} else {
|
|
73
|
+
node.send([null, msg]);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
RED.nodes.registerType("RailwaySwitchUltimate", RailwaySwitchUltimate);
|
|
81
|
+
}
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
color: '#ff8080',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {
|
|
7
|
-
value: "
|
|
7
|
+
value: "Math"
|
|
8
8
|
},
|
|
9
9
|
property: {
|
|
10
10
|
value: "payload"
|
|
11
|
+
},
|
|
12
|
+
math: {
|
|
13
|
+
value: "sum"
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
},
|
|
@@ -16,29 +19,40 @@
|
|
|
16
19
|
icon: "font-awesome/fa-plus",
|
|
17
20
|
label:
|
|
18
21
|
function () {
|
|
19
|
-
return this.name || "
|
|
22
|
+
return this.name || "Math";
|
|
20
23
|
},
|
|
21
24
|
paletteLabel: function () {
|
|
22
|
-
return "
|
|
23
|
-
}
|
|
25
|
+
return "MathUltimate";
|
|
26
|
+
},
|
|
27
|
+
oneditprepare: function () {
|
|
28
|
+
if ($("#node-input-property").val() === "") $("#node-input-property").val("payload");
|
|
29
|
+
$("#node-input-property").typedInput({ default: 'msg', types: ['msg'] });
|
|
30
|
+
}
|
|
24
31
|
});
|
|
25
32
|
</script>
|
|
26
33
|
|
|
27
34
|
<script type="text/x-red" data-template-name="SumUltimate">
|
|
28
35
|
<div class="form-row">
|
|
29
|
-
<b>
|
|
36
|
+
<b>Math Ultimate</b>    <span style="color:red"><i class="fa fa-question-circle"></i> <a target="_blank" href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate"><u>Help online</u></a></span>
|
|
30
37
|
   <span style="color:red"><i class="fa fa-youtube-play"></i> <a target="_blank" href="https://youtu.be/jLIbQgmRzuc"><u>Youtube Sample</u></a></span>
|
|
31
38
|
<br/>
|
|
32
39
|
<br/>
|
|
33
40
|
</div>
|
|
34
41
|
<div class="form-row">
|
|
35
|
-
<label for="node-input-name"><i class="icon-tag"></i>
|
|
36
|
-
<input type="text" id="node-input-name" placeholder="
|
|
42
|
+
<label for="node-input-name"><i class="icon-tag"></i> Topic</label>
|
|
43
|
+
<input type="text" id="node-input-name" placeholder="Topic">
|
|
37
44
|
</div>
|
|
38
45
|
<div class="form-row">
|
|
39
|
-
<label for="node-input-property"><i class="icon-tag"></i>
|
|
46
|
+
<label for="node-input-property"><i class="icon-tag"></i> Input</label>
|
|
40
47
|
<input type="text" id="node-input-property" placeholder="payload">
|
|
41
48
|
</div>
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<label for="node-input-math"><i class="icon-tag"></i> Operation</label>
|
|
51
|
+
<select type="text" id="node-input-math" placeholder="">
|
|
52
|
+
<option value="sum">Sum</option>
|
|
53
|
+
<option value="multiply">Multiply</option>
|
|
54
|
+
</select>
|
|
55
|
+
</div>
|
|
42
56
|
</script>
|
|
43
57
|
|
|
44
58
|
<script type="text/x-red" data-help-name="SumUltimate">
|
|
@@ -3,6 +3,7 @@ module.exports = function (RED) {
|
|
|
3
3
|
RED.nodes.createNode(this, config);
|
|
4
4
|
this.config = config;
|
|
5
5
|
var node = this;
|
|
6
|
+
node.math = config.math === undefined ? "sum" : config.math;
|
|
6
7
|
this.topics = {};
|
|
7
8
|
|
|
8
9
|
function setNodeStatus({ fill, shape, text }) {
|
|
@@ -52,14 +53,29 @@ module.exports = function (RED) {
|
|
|
52
53
|
node.topics[msg.topic.toString()] = ret;
|
|
53
54
|
|
|
54
55
|
var quantita = 0;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
|
|
57
|
+
if (node.math === "sum") {
|
|
58
|
+
let somma = Object.keys(node.topics).reduce(function (a, b) {
|
|
59
|
+
++quantita;
|
|
60
|
+
return a + node.topics[b];
|
|
61
|
+
}, 0);
|
|
62
|
+
msg.payload = somma; // Sum
|
|
63
|
+
msg.average = somma / quantita; // Average
|
|
64
|
+
msg.measurements = quantita; // Topics
|
|
65
|
+
} else if (node.math === "multiply") {
|
|
66
|
+
let moltiplicazione = Object.keys(node.topics).reduce(function (a, b) {
|
|
67
|
+
try {
|
|
68
|
+
++quantita;
|
|
69
|
+
return (a > 0 ? a : 1) * node.topics[b]; // Avoid returning zero everytime
|
|
70
|
+
} catch (error) {
|
|
71
|
+
setNodeStatus({ fill: "red", shape: "ring", text: "Error " + error.message });
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
}, 0);
|
|
75
|
+
msg.payload = moltiplicazione; // Sum
|
|
76
|
+
msg.average = undefined; // Average
|
|
77
|
+
msg.measurements = quantita; // Topics
|
|
78
|
+
}
|
|
63
79
|
|
|
64
80
|
// overwrite topic if configured
|
|
65
81
|
if (config.name) {
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
name: {
|
|
7
7
|
value: "Toggle"
|
|
8
8
|
},
|
|
9
|
-
valueToToggle: { value: "true" }
|
|
9
|
+
valueToToggle: { value: "true" },
|
|
10
|
+
payloadPropName: { value: "payload", required: false }
|
|
10
11
|
},
|
|
11
12
|
inputs: 1,
|
|
12
13
|
outputs: 1,
|
|
@@ -17,6 +18,10 @@
|
|
|
17
18
|
},
|
|
18
19
|
paletteLabel: function () {
|
|
19
20
|
return "toggleUltimate";
|
|
21
|
+
},
|
|
22
|
+
oneditprepare: function () {
|
|
23
|
+
if ($("#node-input-payloadPropName").val() === "") $("#node-input-payloadPropName").val("payload");
|
|
24
|
+
$("#node-input-payloadPropName").typedInput({ default: 'msg', types: ['msg'] });
|
|
20
25
|
}
|
|
21
26
|
});
|
|
22
27
|
</script>
|
|
@@ -31,6 +36,10 @@
|
|
|
31
36
|
<div class="form-row">
|
|
32
37
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
33
38
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
42
|
+
<input type="text" id="node-input-payloadPropName">
|
|
34
43
|
</div>
|
|
35
44
|
<div class="form-row">
|
|
36
45
|
<label style="width:160px" for="node-input-valueToToggle"><i class="fa fa-toggle-on"></i> Initial value</label>
|
|
@@ -3,7 +3,8 @@ module.exports = function (RED) {
|
|
|
3
3
|
RED.nodes.createNode(this, config);
|
|
4
4
|
this.config = config;
|
|
5
5
|
var node = this;
|
|
6
|
-
|
|
6
|
+
const utils = require("./utils.js");
|
|
7
|
+
node.valueToToggle = config.valueToToggle === undefined ? true : utils.ToBoolean(config.valueToToggle);
|
|
7
8
|
|
|
8
9
|
function setNodeStatus({ fill, shape, text }) {
|
|
9
10
|
let dDate = new Date();
|
|
@@ -14,9 +15,11 @@ module.exports = function (RED) {
|
|
|
14
15
|
|
|
15
16
|
this.on('input', function (msg) {
|
|
16
17
|
|
|
18
|
+
const utils = require("./utils.js");
|
|
19
|
+
let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload");
|
|
17
20
|
|
|
18
21
|
// 15/11/2021 inform user about undefined topic or payload
|
|
19
|
-
if (
|
|
22
|
+
if (sPayload === undefined ) {
|
|
20
23
|
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
21
24
|
return;
|
|
22
25
|
}
|
|
@@ -35,33 +38,6 @@ module.exports = function (RED) {
|
|
|
35
38
|
});
|
|
36
39
|
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
function ToBoolean(value) {
|
|
40
|
-
let res = false;
|
|
41
|
-
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
42
|
-
|
|
43
|
-
if (typeof value === 'boolean') {
|
|
44
|
-
res = value;
|
|
45
|
-
}
|
|
46
|
-
else if (typeof value === 'number' || typeof value === 'string') {
|
|
47
|
-
|
|
48
|
-
if (typeof value === "string" && value.toLowerCase() === "on") return true;
|
|
49
|
-
if (typeof value === "string" && value.toLowerCase() === "off") return false;
|
|
50
|
-
|
|
51
|
-
// Is it formated as a decimal number?
|
|
52
|
-
if (decimal.test(value)) {
|
|
53
|
-
res = parseFloat(value) != 0;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
res = value.toLowerCase() === "true";
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return res;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
41
|
}
|
|
66
42
|
|
|
67
43
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module.exports.ToBoolean = function ToBoolean(value) {
|
|
2
|
+
let res = false;
|
|
3
|
+
let decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/
|
|
4
|
+
|
|
5
|
+
if (typeof value === 'boolean') {
|
|
6
|
+
return value;
|
|
7
|
+
} else if (typeof value === 'string') {
|
|
8
|
+
|
|
9
|
+
if (value.toLowerCase() === "on") return true;
|
|
10
|
+
if (value.toLowerCase() === "off") return false;
|
|
11
|
+
|
|
12
|
+
if (value.toLowerCase() === "active") return true;
|
|
13
|
+
if (value.toLowerCase() === "inactive") return false;
|
|
14
|
+
|
|
15
|
+
if (value.toLowerCase() === "open") return true;
|
|
16
|
+
if (value.toLowerCase() === "closed") return false;
|
|
17
|
+
|
|
18
|
+
} else if (typeof value === 'number') {
|
|
19
|
+
// Is it formated as a decimal number?
|
|
20
|
+
if (decimal.test(value)) {
|
|
21
|
+
res = parseFloat(value) != 0;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
res = value.toLowerCase() === "true";
|
|
25
|
+
}
|
|
26
|
+
return res;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports.fetchFromObject = function fetchFromObject(_msg, _payloadPropName) {
|
|
31
|
+
// The output cannot be an oblect. In case, return undefined.
|
|
32
|
+
var _index = _payloadPropName.indexOf('.')
|
|
33
|
+
if (_index > -1) {
|
|
34
|
+
return fetchFromObject(_msg[_payloadPropName.substring(0, _index)], _payloadPropName.substr(_index + 1));
|
|
35
|
+
}
|
|
36
|
+
if (typeof _msg[_payloadPropName] === "object") return undefined;
|
|
37
|
+
return _msg[_payloadPropName];
|
|
38
|
+
};
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-boolean-logic-ultimate",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A set of Node-RED enhanced boolean logic and utility nodes, flow interruption, blinker, invert, filter, toggle etc.., with persistent values after reboot. Compatible also with Homeassistant
|
|
3
|
+
"version": "1.0.54",
|
|
4
|
+
"description": "A set of Node-RED enhanced boolean logic and utility nodes, flow interruption, blinker, invert, filter, toggle etc.., with persistent values after reboot. Compatible also with Homeassistant values.",
|
|
5
5
|
"author": "Supergiovane (https://github.com/Supergiovane)",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"fs": "0.0.1-security",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"StatusUltimate": "boolean-logic-ultimate/StatusUltimate.js",
|
|
32
32
|
"ImpulseUltimate": "boolean-logic-ultimate/ImpulseUltimate.js",
|
|
33
33
|
"SumUltimate": "boolean-logic-ultimate/SumUltimate.js",
|
|
34
|
-
"toggleUltimate": "boolean-logic-ultimate/toggleUltimate.js"
|
|
34
|
+
"toggleUltimate": "boolean-logic-ultimate/toggleUltimate.js",
|
|
35
|
+
"RailwaySwitchUltimate": "boolean-logic-ultimate/RailwaySwitchUltimate.js"
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
}
|
|
38
|
+
}
|