node-red-contrib-boolean-logic-ultimate 1.2.15 → 1.2.17
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 +15 -0
- package/README.md +147 -185
- package/boolean-logic-ultimate/HysteresisUltimate.html +33 -10
- package/boolean-logic-ultimate/HysteresisUltimate.js +46 -4
- package/examples/HysteresisUltimate.json +74 -0
- package/img/logo-supervibe.png +0 -0
- package/img/readmemain.png +0 -0
- package/package.json +26 -11
- package/test/hysteresis.spec.js +57 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
# CHANGELOG
|
|
6
6
|
|
|
7
|
+
<p>
|
|
8
|
+
<b>Version 1.2.17</b> July 2026<br/>
|
|
9
|
+
|
|
10
|
+
- HysteresisUltimate: added permanent output control through <code>msg.permanentLockState</code>, supporting <code>lock</code>, <code>lockOn</code>, <code>lockOff</code> and <code>unlock</code>.<br/>
|
|
11
|
+
- HysteresisUltimate: control-topic configuration and diagnostics remain available while state output is locked.<br/>
|
|
12
|
+
- Updated the Hysteresis editor help, README documentation, automated tests and importable example flow.<br/>
|
|
13
|
+
- Reorganized the README with a clearer heading structure, installation instructions and a categorized node index.<br/>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p>
|
|
17
|
+
<b>Version 1.2.16</b> July 2026<br/>
|
|
18
|
+
|
|
19
|
+
- DOCS: new Max Supervibe README banner and app-icon logo.<br/>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
7
22
|
<p>
|
|
8
23
|
<b>Version 1.2.15</b> Juli 2026<br/>
|
|
9
24
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="img/logo-supervibe.png" alt="Boolean Logic Ultimate - Max Supervibe" width="380">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Boolean Logic Ultimate
|
|
6
|
+
|
|
7
|
+
A collection of enhanced logic and utility nodes for Node-RED. It supports persistent values after reboot and conversion of common Home Assistant values.
|
|
2
8
|
|
|
3
9
|
[![NPM version][npm-version-image]][npm-url]
|
|
4
10
|
[![NPM downloads per month][npm-downloads-month-image]][npm-url]
|
|
@@ -8,19 +14,39 @@
|
|
|
8
14
|
[](https://www.paypal.me/techtoday)
|
|
9
15
|
[![youtube][youtube-image]][youtube-url]
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src="img/readmemain.png" alt="Boolean Logic Ultimate for Node-RED — Max Supervibe" width="70%">
|
|
19
|
+
</p>
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
<br/>
|
|
21
|
+
## Getting started
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
Install the package from the Node-RED palette manager or run this command in your Node-RED user directory:
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
```shell
|
|
26
|
+
npm install node-red-contrib-boolean-logic-ultimate
|
|
27
|
+
```
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
<br/>
|
|
29
|
+
Importable flows are available from the Node-RED editor under **Menu (☰) → Import → Examples**, or directly in the [`examples/`](examples/) folder. See the [examples overview](examples/README.md) for the complete list.
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
## Documentation
|
|
32
|
+
|
|
33
|
+
| Logic and routing | Timing and flow | Values and simulation |
|
|
34
|
+
| ----------------- | --------------- | --------------------- |
|
|
35
|
+
| [Boolean Logic](#boolean-logic) | [Interrupt Flows Ultimate](#interrupt-flows-ultimate) | [Translator node](#translator-node) |
|
|
36
|
+
| [Invert Ultimate](#invert-ultimate) | [Blinker Ultimate](#blinker-ultimate) | [Simple Output Ultimate](#simple-output-ultimate) |
|
|
37
|
+
| [Filter Ultimate](#filter-ultimate) | [Impulse Ultimate](#impulse-ultimate) | [Inject Ultimate](#inject-ultimate) |
|
|
38
|
+
| [Hysteresis Ultimate](#hysteresis-ultimate) | [Rate Limiter Ultimate](#rate-limiter-ultimate) | [Status Ultimate](#status-ultimate) |
|
|
39
|
+
| [Railway Switch Ultimate](#railway-switch-ultimate) | [Debouncer Ultimate](#debouncer-ultimate) | [Math Ultimate](#math-ultimate) |
|
|
40
|
+
| [Toggle Ultimate](#toggle-ultimate) | [Staircase Light Ultimate](#staircase-light-ultimate) | [Kalman Filter Ultimate](#kalman-filter-ultimate) |
|
|
41
|
+
| | | [Presence Simulator Ultimate](#presence-simulator-ultimate) |
|
|
42
|
+
|
|
43
|
+
Each node section contains its configuration, accepted input messages, outputs and runtime commands where applicable.
|
|
44
|
+
|
|
45
|
+
## Changelog
|
|
46
|
+
|
|
47
|
+
- See the project [changelog](CHANGELOG.md) for release details.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
24
50
|
|
|
25
51
|
Importable Node-RED example flows are available in the [`examples/`](examples/) folder (one JSON per node). See [`examples/README.md`](examples/README.md) for a quick overview.
|
|
26
52
|
|
|
@@ -28,12 +54,9 @@ Importable Node-RED example flows are available in the [`examples/`](examples/)
|
|
|
28
54
|
|
|
29
55
|
- Node-RED editor → Menu (☰) → **Import** → **Examples** and select an example from `node-red-contrib-boolean-logic-ultimate`
|
|
30
56
|
|
|
31
|
-
|
|
32
|
-
<br/>
|
|
57
|
+
## Translator node
|
|
33
58
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Other than true/false, all nodes accepts [Homeassistant](https://www.home-assistant.io) output strings.
|
|
59
|
+
In addition to true/false, the nodes accept common [Home Assistant](https://www.home-assistant.io) state strings.
|
|
37
60
|
|
|
38
61
|
You can **even add your own input translation word list**, thanks to the translator-config node.
|
|
39
62
|
|
|
@@ -41,20 +64,17 @@ The translator node can translate an input payload, to a true/false boolean valu
|
|
|
41
64
|
|
|
42
65
|
Each row in the text box, represents a translation command. <br/>
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
Default translation rows make the _boolean-logic-ultimate_ nodes compatible with common Home Assistant states. <br/>
|
|
45
68
|
|
|
46
69
|
You can add your own translation row.<br/>
|
|
47
70
|
|
|
48
71
|
| | Description |
|
|
49
72
|
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
-
| Translate | Add, delete or edit
|
|
73
|
+
| Translate | Add, delete or edit a translation command. Each row must use the format **input string:true(or false)**, for example <code>open:true</code> or <code>closed:false</code>. Expressions such as <code>{{value>=50}}:true</code> are also supported; when the expression evaluates to true, the translator returns the selected value. |
|
|
51
74
|
|
|
52
75
|

|
|
53
76
|
|
|
54
|
-
|
|
55
|
-
<br/>
|
|
56
|
-
|
|
57
|
-
# BOOLEAN LOGIC
|
|
77
|
+
## Boolean Logic
|
|
58
78
|
|
|
59
79
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/bl1.png' width='60%'>
|
|
60
80
|
|
|
@@ -94,7 +114,7 @@ You can also set the default values of the topic inputs.<br/>
|
|
|
94
114
|
|
|
95
115
|
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/>
|
|
96
116
|
|
|
97
|
-
###
|
|
117
|
+
### Configuration
|
|
98
118
|
|
|
99
119
|
| Property | Description |
|
|
100
120
|
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
@@ -116,35 +136,29 @@ The node can convert arbitrary input values to true/false. It supports Homeassis
|
|
|
116
136
|
| msg.reset = true | Resets all saved input values to undefined |
|
|
117
137
|
| msg.inputcount | Changes the inputs count property. For example, <b>msg.inputcount = 3</b> Whenever you lower the inputcount from a higher number to a lower one, for example from 3 to 2, it's suggested to do a <b>msg.reset=true</b> to reset all stored input values. |
|
|
118
138
|
|
|
119
|
-
|
|
120
|
-
<br/>
|
|
121
|
-
<br/>
|
|
122
|
-
<br/>
|
|
123
|
-
<br/>
|
|
124
|
-
|
|
125
|
-
# INTERRUPT FLOWS ULTIMATE
|
|
139
|
+
## Interrupt Flows Ultimate
|
|
126
140
|
|
|
127
141
|
The interrupt flows is able to stop the input messages to exiting the node.
|
|
128
142
|
|
|
129
|
-
###
|
|
143
|
+
### Configuration
|
|
130
144
|
|
|
131
145
|
| Property | Description |
|
|
132
146
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
147
|
| 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. |
|
|
134
|
-
| Input
|
|
148
|
+
| Input | It's the msg property to be evaluated. _By default, it is "payload", but you can also specify other properties, for example "payload.value"_ |
|
|
135
149
|
| 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. |
|
|
136
150
|
|
|
137
151
|
<br/>
|
|
138
152
|
|
|
139
153
|
**INPUT MSG WITH "TRIGGER" TOPIC**
|
|
140
154
|
|
|
141
|
-
Pass <code>msg.payload = true</code> to allow messages to pass through
|
|
155
|
+
Pass <code>msg.payload = true</code> to allow messages to pass through<br/>
|
|
142
156
|
|
|
143
|
-
Pass <code>msg.payload = false</code> to prevent messages from passing through
|
|
157
|
+
Pass <code>msg.payload = false</code> to prevent messages from passing through<br/>
|
|
144
158
|
|
|
145
|
-
Pass <code>msg.play = true</code> from a message having the "trigger" topic, to replay the last stored message
|
|
159
|
+
Pass <code>msg.play = true</code> from a message having the "trigger" topic, to replay the last stored message<br/>
|
|
146
160
|
|
|
147
|
-
Pass <code>msg.reset = true</code> from a message having the "trigger" topic, to clear the last stored message
|
|
161
|
+
Pass <code>msg.reset = true</code> from a message having the "trigger" topic, to clear the last stored message<br/>
|
|
148
162
|
|
|
149
163
|
<code>
|
|
150
164
|
// Assume you set the "trigger by topic" field to "trigger"
|
|
@@ -160,7 +174,7 @@ msg.topic = "trigger"
|
|
|
160
174
|
msg.reset = true;
|
|
161
175
|
</code>
|
|
162
176
|
|
|
163
|
-
|
|
177
|
+
<br/>
|
|
164
178
|
|
|
165
179
|
See the example below.<br/>
|
|
166
180
|
|
|
@@ -186,19 +200,13 @@ This allow to save the state of a node and then replay it back whenever you want
|
|
|
186
200
|
</code>
|
|
187
201
|
</details>
|
|
188
202
|
|
|
189
|
-
|
|
190
|
-
<br/>
|
|
191
|
-
<br/>
|
|
192
|
-
<br/>
|
|
193
|
-
<br/>
|
|
194
|
-
|
|
195
|
-
# INVERT ULTIMATE
|
|
203
|
+
## Invert Ultimate
|
|
196
204
|
|
|
197
205
|
Outputs the inverted input. For example true -> false<br />
|
|
198
206
|
|
|
199
207
|
The input message is preserved and passed to the output, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.<br/>
|
|
200
208
|
|
|
201
|
-
###
|
|
209
|
+
### Configuration
|
|
202
210
|
|
|
203
211
|
| Property | Description |
|
|
204
212
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -206,13 +214,7 @@ The input message is preserved and passed to the output, changing only the topic
|
|
|
206
214
|
|
|
207
215
|
<br/>
|
|
208
216
|
|
|
209
|
-
|
|
210
|
-
<br/>
|
|
211
|
-
<br/>
|
|
212
|
-
<br/>
|
|
213
|
-
<br/>
|
|
214
|
-
|
|
215
|
-
# FILTER ULTIMATE
|
|
217
|
+
## Filter Ultimate
|
|
216
218
|
|
|
217
219
|
This node has 2 outputs.<br />
|
|
218
220
|
|
|
@@ -222,7 +224,7 @@ If the input payload is false, the node will send nothing on output 1 and <code>
|
|
|
222
224
|
|
|
223
225
|
The input message is preserved and passed to the output, changing only the topic and the payload. If the input message has it's own topic, it'll be preserved as well.<br/>
|
|
224
226
|
|
|
225
|
-
###
|
|
227
|
+
### Configuration
|
|
226
228
|
|
|
227
229
|
| Property | Description |
|
|
228
230
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -230,15 +232,9 @@ The input message is preserved and passed to the output, changing only the topic
|
|
|
230
232
|
|
|
231
233
|
<br/>
|
|
232
234
|
|
|
233
|
-
|
|
234
|
-
<br/>
|
|
235
|
-
<br/>
|
|
236
|
-
<br/>
|
|
237
|
-
<br/>
|
|
238
|
-
|
|
239
|
-
# BLINKER ULTIMATE
|
|
235
|
+
## Blinker Ultimate
|
|
240
236
|
|
|
241
|
-
|
|
237
|
+
This node blinks an LED or another device.<br />
|
|
242
238
|
|
|
243
239
|
output1 : outputs the value true/false<br/>
|
|
244
240
|
|
|
@@ -246,7 +242,7 @@ output2 : outputs the inverted value false/true<br/>
|
|
|
246
242
|
|
|
247
243
|
<br/>
|
|
248
244
|
|
|
249
|
-
###
|
|
245
|
+
### Configuration
|
|
250
246
|
|
|
251
247
|
| Property | Description |
|
|
252
248
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -254,11 +250,11 @@ output2 : outputs the inverted value false/true<br/>
|
|
|
254
250
|
|
|
255
251
|
<br/>
|
|
256
252
|
|
|
257
|
-
Pass <code>msg.payload = true</code> to start blinking
|
|
253
|
+
Pass <code>msg.payload = true</code> to start blinking<br/>
|
|
258
254
|
|
|
259
|
-
Pass <code>msg.payload = false</code> to stop blinking
|
|
255
|
+
Pass <code>msg.payload = false</code> to stop blinking<br/>
|
|
260
256
|
|
|
261
|
-
Pass <code>msg.interval = 2000</code> to change the blinking interval
|
|
257
|
+
Pass <code>msg.interval = 2000</code> to change the blinking interval<br/>
|
|
262
258
|
|
|
263
259
|
- output1 stop behavior : when the blinker receives the stop message, you can select the behavior of the output1<br/>
|
|
264
260
|
- output2 stop behavior : when the blinker receives the stop message, you can select the behavior of the output2<br/>
|
|
@@ -271,19 +267,13 @@ Pass <code>msg.interval = 2000</code> to change the blinking interval</br>
|
|
|
271
267
|
</code>
|
|
272
268
|
</details>
|
|
273
269
|
|
|
274
|
-
|
|
275
|
-
<br/>
|
|
276
|
-
<br/>
|
|
277
|
-
<br/>
|
|
278
|
-
<br/>
|
|
270
|
+
## Simple Output Ultimate
|
|
279
271
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
The pourpose of this node is to send a message with payload TRUE on the first output and FALSE on second output, independently from the msg input.<br />
|
|
272
|
+
This node sends a message with payload TRUE on the first output and FALSE on the second output, independently of the input message.<br />
|
|
283
273
|
|
|
284
274
|
This is useful if you need to simply send a true or false payload.
|
|
285
275
|
|
|
286
|
-
###
|
|
276
|
+
### Configuration
|
|
287
277
|
|
|
288
278
|
| Property | Description |
|
|
289
279
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -299,15 +289,9 @@ This is useful if you need to simply send a true or false payload.
|
|
|
299
289
|
</code>
|
|
300
290
|
</details>
|
|
301
291
|
|
|
302
|
-
|
|
303
|
-
<br/>
|
|
304
|
-
<br/>
|
|
305
|
-
<br/>
|
|
306
|
-
<br/>
|
|
307
|
-
|
|
308
|
-
# INJECT ULTIMATE
|
|
292
|
+
## Inject Ultimate
|
|
309
293
|
|
|
310
|
-
|
|
294
|
+
This node sends TRUE on the first output, FALSE on the second output and a toggled true/false value on the third output when its button is pressed.<br />
|
|
311
295
|
|
|
312
296
|
This is useful if you need to simply test your flow.
|
|
313
297
|
|
|
@@ -319,15 +303,9 @@ This is useful if you need to simply test your flow.
|
|
|
319
303
|
</code>
|
|
320
304
|
</details>
|
|
321
305
|
|
|
322
|
-
|
|
323
|
-
<br/>
|
|
324
|
-
<br/>
|
|
325
|
-
<br/>
|
|
326
|
-
<br/>
|
|
327
|
-
|
|
328
|
-
# STATUS ULTIMATE
|
|
306
|
+
## Status Ultimate
|
|
329
307
|
|
|
330
|
-
|
|
308
|
+
This node displays the value of a passing message as its Node-RED status.<br />
|
|
331
309
|
|
|
332
310
|
**Show msg.**
|
|
333
311
|
|
|
@@ -340,15 +318,9 @@ The pourpose of this node is to show a status of the passingthrough message.<br
|
|
|
340
318
|
[{"id":"8c1648bf.58e6","type":"StatusUltimate","z":"5c2de561.6a0de4","name":"Status","property":"testobject.color","x":90,"y":180,"wires":[["b96cd259.3f8398"]]},{"id":"3beb9c6.90d1e64","type":"function","z":"5c2de561.6a0de4","name":"Dummy msg","func":"msg.payload = \"The payload is \" + msg.payload;\nmsg.myproperty = \"This is my custom property\";\nmsg.testobject = {len : 100, color : \"blue\"};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":100,"wires":[["8c1648bf.58e6"]]},{"id":"84080b79.df3f38","type":"debug","z":"5c2de561.6a0de4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":180,"wires":[]},{"id":"b534d2ec.635398","type":"InjectUltimate","z":"5c2de561.6a0de4","name":"Inject","topic":"1","curVal":true,"x":90,"y":100,"wires":[[],[],["3beb9c6.90d1e64"]]},{"id":"9745c77a.0361b","type":"comment","z":"5c2de561.6a0de4","name":"View the status of a message passing through the StatusUltimate node","info":"","x":270,"y":40,"wires":[]},{"id":"b96cd259.3f8398","type":"StatusUltimate","z":"5c2de561.6a0de4","name":"Status","property":"payload","x":230,"y":180,"wires":[["ac2b784b.b44a48"]]},{"id":"ac2b784b.b44a48","type":"StatusUltimate","z":"5c2de561.6a0de4","name":"Status","property":"myproperty","x":450,"y":180,"wires":[["84080b79.df3f38"]]}]
|
|
341
319
|
</code>
|
|
342
320
|
</details>
|
|
343
|
-
|
|
344
|
-
<br/>
|
|
345
|
-
<br/>
|
|
346
|
-
<br/>
|
|
347
|
-
<br/>
|
|
348
|
-
|
|
349
|
-
# IMPULSE ULTIMATE
|
|
321
|
+
## Impulse Ultimate
|
|
350
322
|
|
|
351
|
-
|
|
323
|
+
This node sends a timed sequence of pulsed commands, for example to open a garage door or control an appliance.<br />
|
|
352
324
|
|
|
353
325
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/Impulse.png' width='60%'>
|
|
354
326
|
<details><summary>CLICK HERE, copy and paste it into your flow</summary>
|
|
@@ -357,7 +329,7 @@ The pourpose of this node is to send a sequence of pulsed commands to for exampl
|
|
|
357
329
|
</code>
|
|
358
330
|
</details>
|
|
359
331
|
|
|
360
|
-
###
|
|
332
|
+
### Configuration
|
|
361
333
|
|
|
362
334
|
| Property | Description |
|
|
363
335
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -379,23 +351,17 @@ Restart the sequence from the beginning. Use **_restart_** alone, without **:**
|
|
|
379
351
|
comment. For example: **_// This opens the garage_**. The comment are ignored, so you can write what you want.<br />
|
|
380
352
|
<br />
|
|
381
353
|
|
|
382
|
-
Pass <code>msg.payload = true</code> to the node to start the sequence
|
|
354
|
+
Pass <code>msg.payload = true</code> to the node to start the sequence<br/>
|
|
383
355
|
|
|
384
|
-
Pass <code>msg.payload = false</code> to the node to stop the running sequence
|
|
356
|
+
Pass <code>msg.payload = false</code> to the node to stop the running sequence<br/>
|
|
385
357
|
|
|
386
358
|
<br />
|
|
387
359
|
|
|
388
360
|
- Output: the node outputs a message you specified in the command textbox<br/>
|
|
389
361
|
|
|
390
|
-
|
|
391
|
-
<br/>
|
|
392
|
-
<br/>
|
|
393
|
-
<br/>
|
|
394
|
-
<br/>
|
|
362
|
+
## Math Ultimate
|
|
395
363
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
The pourpose of this node is to do maths on the incoming values. Each incoming message MUST HAVE OWN TOPIC.<br />
|
|
364
|
+
This node performs calculations on incoming values. Each incoming message must have its own topic.<br />
|
|
399
365
|
|
|
400
366
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/sum.png' width='60%'>
|
|
401
367
|
<details><summary>CLICK HERE, copy and paste it into your flow</summary>
|
|
@@ -404,7 +370,7 @@ The pourpose of this node is to do maths on the incoming values. Each incoming m
|
|
|
404
370
|
</code>
|
|
405
371
|
</details>
|
|
406
372
|
|
|
407
|
-
###
|
|
373
|
+
### Configuration
|
|
408
374
|
|
|
409
375
|
| Property | Description |
|
|
410
376
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -430,18 +396,11 @@ resets the values to zero.
|
|
|
430
396
|
}
|
|
431
397
|
</pre>
|
|
432
398
|
|
|
433
|
-
|
|
399
|
+
## Toggle Ultimate
|
|
434
400
|
|
|
435
|
-
|
|
436
|
-
<br/>
|
|
437
|
-
<br/>
|
|
438
|
-
<br/>
|
|
439
|
-
|
|
440
|
-
# TOGGLE ULTIMATE
|
|
401
|
+
This node toggles between true and false whenever an inbound message arrives.<br />
|
|
441
402
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
### NODE CONFIGURATION
|
|
403
|
+
### Configuration
|
|
445
404
|
|
|
446
405
|
| Property | Description |
|
|
447
406
|
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -451,27 +410,21 @@ The pourpose of this node is to toggle between true/false, everytime an inboud m
|
|
|
451
410
|
|
|
452
411
|
**INPUT**<br />
|
|
453
412
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
<br/>
|
|
457
|
-
<br/>
|
|
458
|
-
<br/>
|
|
459
|
-
<br/>
|
|
460
|
-
<br/>
|
|
413
|
+
Every input message is passed to the output with its payload toggled between true and false.
|
|
461
414
|
|
|
462
|
-
|
|
415
|
+
## Railway Switch Ultimate
|
|
463
416
|
|
|
464
|
-
The railway
|
|
417
|
+
The railway switch redirects incoming messages to one of the available outputs, like a railway junction.
|
|
465
418
|
|
|
466
419
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/railroadSwitchScambio.png' width='80%'>
|
|
467
420
|
|
|
468
|
-
###
|
|
421
|
+
### Configuration
|
|
469
422
|
|
|
470
423
|
| Property | Description |
|
|
471
424
|
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
472
425
|
| Switcher topic | Whenever the node receives a payload from this **topic**, it redirects the input messages to a choosen output PIN. |
|
|
473
426
|
| Output pins | Number of output pins (outputs) to show. Default is 5, range is 1..10. |
|
|
474
|
-
| Input
|
|
427
|
+
| Input | It's the msg property to be evaluated. _By default, it is "payload", but you can also specify other properties, for example "payload.value"_ |
|
|
475
428
|
| Translator | Translates the incoming <code>payload</code> value. This allows the compatibility with, for example, **HomeAssistant** nodes. |
|
|
476
429
|
|
|
477
430
|
### Inputs
|
|
@@ -519,7 +472,7 @@ this JSON input message redirects all input messages to the third PIN, and so on
|
|
|
519
472
|
}
|
|
520
473
|
```
|
|
521
474
|
|
|
522
|
-
|
|
475
|
+
<br/>
|
|
523
476
|
|
|
524
477
|
See the example below.<br/>
|
|
525
478
|
|
|
@@ -616,14 +569,9 @@ Copy and paste it into your flow
|
|
|
616
569
|
];
|
|
617
570
|
```
|
|
618
571
|
|
|
619
|
-
|
|
620
|
-
<br/>
|
|
621
|
-
<br/>
|
|
622
|
-
<br/>
|
|
623
|
-
|
|
624
|
-
# KALMAN FILTER ULTIMATE
|
|
572
|
+
## Kalman Filter Ultimate
|
|
625
573
|
|
|
626
|
-
|
|
574
|
+
Outputs the Kalman-filtered input.
|
|
627
575
|
|
|
628
576
|
Please refer to [this](https://github.com/wouterbulten/kalmanjs) link, on how it works.
|
|
629
577
|
|
|
@@ -644,13 +592,11 @@ Please refer to [this](https://github.com/wouterbulten/kalmanjs) link, on how it
|
|
|
644
592
|
|
|
645
593
|
: payload (number) : the payload containing the number. If you've changed the incoming evaluation property in the **_Input_** field, the number to be evaluated must be put in such message's property, instead of the _payload_ property.
|
|
646
594
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
# RATE LIMITER ULTIMATE
|
|
595
|
+
## Rate Limiter Ultimate
|
|
650
596
|
|
|
651
597
|
Gateway per sensori e dispositivi troppo “chiacchieroni”: limita burst e rimbalzi con modalità **Debounce**, **Throttle** e **Window**. Lo stato del nodo riporta sempre modalità corrente, contatori di messaggi inoltrati e bloccati.
|
|
652
598
|
|
|
653
|
-
###
|
|
599
|
+
### Configuration
|
|
654
600
|
|
|
655
601
|
| Property | Description |
|
|
656
602
|
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -663,29 +609,27 @@ Gateway per sensori e dispositivi troppo “chiacchieroni”: limita burst e rim
|
|
|
663
609
|
| Max messages | Numero di messaggi ammessi nella finestra. |
|
|
664
610
|
| On limit | _Drop_ scarta i messaggi extra, _Queue last_ accoda l’ultimo e lo riproduce appena possibile. |
|
|
665
611
|
| Control topic | Topic dei messaggi di controllo (default `rate`). |
|
|
666
|
-
| Input
|
|
612
|
+
| Input | Proprietà del messaggio da monitorare (default `msg.payload`). |
|
|
667
613
|
| Stats every (s) | Ogni quanti secondi emettere un riepilogo statistico (0 = disattivato). |
|
|
668
614
|
| Translator | Nodo translator-config opzionale per adattare le stringhe d’ingresso a true/false. |
|
|
669
615
|
|
|
670
616
|
<br/>
|
|
671
617
|
|
|
672
|
-
###
|
|
618
|
+
### Outputs
|
|
673
619
|
|
|
674
620
|
- **Output 1**: messaggi inoltrati, invariati.
|
|
675
621
|
- **Output 2**: diagnostica (`{mode, reason, passed, dropped, msg, propertyValue}`) e statistiche periodiche su `controlTopic/stats`.
|
|
676
622
|
|
|
677
623
|
<br/>
|
|
678
624
|
|
|
679
|
-
###
|
|
625
|
+
### Control messages (`msg.topic === controlTopic`)
|
|
680
626
|
|
|
681
627
|
- `msg.reset = true` → azzera contatori, accoda azzerata e timer cancellati.
|
|
682
628
|
- `msg.flush = true` → forza l’emissione immediata del messaggio in attesa.
|
|
683
629
|
- `msg.mode = 'debounce'|'throttle'|'window'` → cambia modalità runtime e resetta lo stato.
|
|
684
630
|
- `msg.interval`, `msg.wait`, `msg.windowSize`, `msg.maxInWindow` → aggiorna i parametri corrispondenti.
|
|
685
631
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
# DEBOUNCER ULTIMATE
|
|
632
|
+
## Debouncer Ultimate
|
|
689
633
|
|
|
690
634
|
Nodo dedicato al solo debounce: utile quando vuoi filtrare rimbalzi o burst rapidi senza portarti dietro le altre modalità del `RateLimiterUltimate`. Può inoltrare il **primo** messaggio, l’**ultimo** oppure **entrambi**, dopo un intervallo di quiete configurabile.
|
|
691
635
|
|
|
@@ -695,32 +639,30 @@ Nell'immagine si vede il comportamento tipico: a sinistra arrivano molti messagg
|
|
|
695
639
|
|
|
696
640
|
Example flow: [`examples/DebouncerUltimate.json`](examples/DebouncerUltimate.json)
|
|
697
641
|
|
|
698
|
-
###
|
|
642
|
+
### Configuration
|
|
699
643
|
|
|
700
|
-
| Property | Description
|
|
701
|
-
| ------------- |
|
|
702
|
-
| Wait (ms) | Tempo di quiete richiesto prima di chiudere la finestra di debounce.
|
|
703
|
-
| Emit | Scegli se inviare subito il primo messaggio, solo l’ultimo dopo la pausa, oppure entrambi.
|
|
704
|
-
| Control topic | Topic dei messaggi di controllo (default `debouncer`).
|
|
644
|
+
| Property | Description |
|
|
645
|
+
| ------------- | ------------------------------------------------------------------------------------------ |
|
|
646
|
+
| Wait (ms) | Tempo di quiete richiesto prima di chiudere la finestra di debounce. |
|
|
647
|
+
| Emit | Scegli se inviare subito il primo messaggio, solo l’ultimo dopo la pausa, oppure entrambi. |
|
|
648
|
+
| Control topic | Topic dei messaggi di controllo (default `debouncer`). |
|
|
705
649
|
|
|
706
|
-
###
|
|
650
|
+
### Outputs
|
|
707
651
|
|
|
708
652
|
- **Output 1**: messaggi inoltrati dopo il debounce.
|
|
709
653
|
|
|
710
|
-
###
|
|
654
|
+
### Control messages (`msg.topic === controlTopic`)
|
|
711
655
|
|
|
712
656
|
- `msg.reset = true` → cancella timer e messaggio pendente.
|
|
713
657
|
- `msg.flush = true` → inoltra subito l’ultimo messaggio in attesa.
|
|
714
658
|
- `msg.wait` → aggiorna il ritardo di debounce a runtime.
|
|
715
659
|
- `msg.emitOn = 'leading'|'trailing'|'both'` → cambia la modalità di emissione.
|
|
716
660
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
# PRESENCE SIMULATOR ULTIMATE
|
|
661
|
+
## Presence Simulator Ultimate
|
|
720
662
|
|
|
721
663
|
The purpose of this node is to replay a programmable sequence of messages in order to simulate occupancy when you are away.
|
|
722
664
|
|
|
723
|
-
###
|
|
665
|
+
### Configuration
|
|
724
666
|
|
|
725
667
|
| Property | Description |
|
|
726
668
|
| ------------- | ---------------------------------------------------------------------------------------------- |
|
|
@@ -729,11 +671,11 @@ The purpose of this node is to replay a programmable sequence of messages in ord
|
|
|
729
671
|
| Loop sequence | Repeats the sequence when it reaches the end. |
|
|
730
672
|
| Random delays | Enables a random variation of the programmed delays. |
|
|
731
673
|
| Jitter (%) | Maximum percentage of variation applied when random delays are enabled. |
|
|
732
|
-
| Input
|
|
674
|
+
| Input | Message property to inspect for inline events (default `payload`). |
|
|
733
675
|
| Translator | Optional translator-config to convert incoming values. |
|
|
734
676
|
| Sequence | One JSON object per line, each containing at least `delay` (ms) plus the properties to output. |
|
|
735
677
|
|
|
736
|
-
###
|
|
678
|
+
### Control messages (`msg.topic === controlTopic`)
|
|
737
679
|
|
|
738
680
|
- `msg.command = 'start'` / `msg.start = true` → begin playback.
|
|
739
681
|
- `msg.command = 'stop'` / `msg.stop = true` → halt playback.
|
|
@@ -743,13 +685,11 @@ The purpose of this node is to replay a programmable sequence of messages in ord
|
|
|
743
685
|
|
|
744
686
|
Each event in the sequence outputs a message configured in the JSON line. When random delays are enabled, the effective delay is varied within the configured jitter.
|
|
745
687
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
# STAIRCASE LIGHT ULTIMATE
|
|
688
|
+
## Staircase Light Ultimate
|
|
749
689
|
|
|
750
690
|
The purpose of this node is to control staircase lighting with a timer, pre-off warning and optional extension on every trigger.
|
|
751
691
|
|
|
752
|
-
###
|
|
692
|
+
### Configuration
|
|
753
693
|
|
|
754
694
|
| Property | Description |
|
|
755
695
|
| ------------------ | ------------------------------------------------------------------ |
|
|
@@ -759,12 +699,12 @@ The purpose of this node is to control staircase lighting with a timer, pre-off
|
|
|
759
699
|
| Warning offset (s) | Seconds before switch-off when the warning is sent. |
|
|
760
700
|
| Restart on trigger | Restarts the timer when a new trigger arrives while active. |
|
|
761
701
|
| Allow off input | Allows a `false` from the main input to switch off immediately. |
|
|
762
|
-
| Input
|
|
702
|
+
| Input | Message property evaluated as trigger (default `payload`). |
|
|
763
703
|
| Translator | Optional translator-config for true/false conversion. |
|
|
764
704
|
| On/Off payload | Values emitted on output 1 to turn the light on/off. |
|
|
765
705
|
| Warning payload | Value emitted on output 2 when the warning fires. |
|
|
766
706
|
|
|
767
|
-
###
|
|
707
|
+
### Control messages (`msg.topic === controlTopic`)
|
|
768
708
|
|
|
769
709
|
- `msg.command = 'on'` / `msg.start = true` → start the timer and turn on the light.
|
|
770
710
|
- `msg.command = 'off'` / `msg.stop = true` → switch off immediately.
|
|
@@ -773,35 +713,57 @@ The purpose of this node is to control staircase lighting with a timer, pre-off
|
|
|
773
713
|
|
|
774
714
|
Output 1 delivers the ON/OFF command. Output 2 delivers the warning and includes `msg.remaining` with the seconds left.
|
|
775
715
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
# HYSTERESIS ULTIMATE
|
|
716
|
+
## Hysteresis Ultimate
|
|
779
717
|
|
|
780
718
|
Adds hysteresis to numeric sensor values to avoid rapid ON/OFF bouncing around thresholds.
|
|
781
719
|
|
|
782
720
|
Example flow: [`examples/HysteresisUltimate.json`](examples/HysteresisUltimate.json)
|
|
783
721
|
|
|
784
|
-
###
|
|
722
|
+
### Configuration
|
|
723
|
+
|
|
724
|
+
| Property | Description |
|
|
725
|
+
| ------------------- | ----------- |
|
|
726
|
+
| Name | Optional label shown in the flow editor. |
|
|
727
|
+
| Control topic | Topic used for runtime commands (default `hysteresis`). It is not required for `permanentLockState`. |
|
|
728
|
+
| Mode | `high`: ON at or above the ON threshold and OFF at or below the OFF threshold. `low`: ON at or below the ON threshold and OFF at or above the OFF threshold. Values between the thresholds retain the current state. |
|
|
729
|
+
| ON threshold | Numeric limit that changes the internal state to ON according to the selected mode. |
|
|
730
|
+
| OFF threshold | Numeric limit that changes the internal state to OFF according to the selected mode. |
|
|
731
|
+
| Initial state ON | Initial internal state after deployment or restart. It does not emit at startup and is restored by `msg.reset = true`. |
|
|
732
|
+
| Emit only on change | When enabled, output 1 emits only on transitions. When disabled, every valid numeric input emits the current state. |
|
|
733
|
+
| Input | Message property evaluated as a numeric value (default `msg.payload`). Numbers, booleans and numeric strings are accepted. |
|
|
734
|
+
| Translator | Optional shared translator configuration associated with the input. Hysteresis evaluation uses the numeric value of the selected input property. |
|
|
735
|
+
| On payload | Typed value assigned to `msg.payload` on output 1 while the state is ON. |
|
|
736
|
+
| Off payload | Typed value assigned to `msg.payload` on output 1 while the state is OFF. |
|
|
785
737
|
|
|
786
|
-
|
|
787
|
-
| ------------------- | ------------------------------------------------------------------------------ |
|
|
788
|
-
| Control topic | Topic that receives runtime commands such as threshold updates and reset. |
|
|
789
|
-
| Mode | `high` = ON above threshold, OFF below. `low` = ON below threshold, OFF above. |
|
|
790
|
-
| ON/OFF threshold | Hysteresis limits. |
|
|
791
|
-
| Initial state | Startup output state. |
|
|
792
|
-
| Emit only on change | If enabled, output 1 emits only on state transitions. |
|
|
793
|
-
| Input | Message property evaluated as numeric value (default `payload`). |
|
|
794
|
-
| Translator | Optional translator-config. |
|
|
795
|
-
| On/Off payload | Typed payloads sent on output 1. |
|
|
738
|
+
### Input messages
|
|
796
739
|
|
|
797
|
-
|
|
740
|
+
Normal messages are evaluated using the configured **Input** property. Missing or non-numeric values generate an `invalid_input` diagnostic on output 2.
|
|
741
|
+
|
|
742
|
+
### Control messages (`msg.topic === controlTopic`)
|
|
798
743
|
|
|
799
744
|
- `msg.onThreshold`, `msg.offThreshold` → update thresholds at runtime.
|
|
800
|
-
- `msg.state = true|false` → force state.
|
|
801
|
-
- `msg.reset = true` → restore initial state.
|
|
745
|
+
- `msg.state = true|false` → force the state and emit it on output 1. While locked, it updates the internal state without emitting on output 1.
|
|
746
|
+
- `msg.reset = true` → restore the initial state and emit a `reset` diagnostic.
|
|
802
747
|
- `msg.status = true` → emit current state/thresholds on output 2.
|
|
803
748
|
|
|
804
|
-
|
|
749
|
+
### Permanent output lock
|
|
750
|
+
|
|
751
|
+
Regardless of `msg.topic`, `msg.permanentLockState` accepts:
|
|
752
|
+
|
|
753
|
+
- `lock` → suppress state output until another permanent-lock command arrives.
|
|
754
|
+
- `lockOn` → force ON, emit the configured ON payload once, then suppress state output.
|
|
755
|
+
- `lockOff` → force OFF, emit the configured OFF payload once, then suppress state output.
|
|
756
|
+
- `unlock` → resume normal processing (the unlock message itself is consumed).
|
|
757
|
+
|
|
758
|
+
While locked, normal input messages are ignored and output 1 remains suppressed. Control-topic commands remain active: thresholds can be updated, `state` and `reset` can change the internal state, and `status`/`reset` diagnostics can still be emitted on output 2.
|
|
759
|
+
|
|
760
|
+
### Outputs
|
|
761
|
+
|
|
762
|
+
1. **State output** emits a clone of the input message with:
|
|
763
|
+
- the configured `onPayload` or `offPayload` in `msg.payload`;
|
|
764
|
+
- `msg.event` set to `state_changed` or `state_confirmed`;
|
|
765
|
+
- `msg.hysteresis` containing `state`, `changed`, `mode`, input `value`, `onThreshold` and `offThreshold`.
|
|
766
|
+
2. **Diagnostics** emits state-change, invalid-input, reset and status events. It sets `msg.topic` to `<controlTopic>/event` and places the event details in `msg.payload`.
|
|
805
767
|
|
|
806
768
|
<br/>
|
|
807
769
|
|
|
@@ -121,17 +121,40 @@
|
|
|
121
121
|
|
|
122
122
|
|Property|Description|
|
|
123
123
|
|--|--|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
124
|
+
| Name | Optional label shown in the flow editor. |
|
|
125
|
+
| Control topic | Topic used for runtime commands. The default is `hysteresis`. It is not required for `permanentLockState`. |
|
|
126
|
+
| Mode | `high`: switch ON when the value is greater than or equal to the ON threshold and OFF when it is less than or equal to the OFF threshold. `low`: switch ON when the value is less than or equal to the ON threshold and OFF when it is greater than or equal to the OFF threshold. Values between the thresholds keep the current state. |
|
|
127
|
+
| ON threshold | Numeric limit that changes the internal state to ON, according to the selected mode. |
|
|
128
|
+
| OFF threshold | Numeric limit that changes the internal state to OFF, according to the selected mode. |
|
|
129
|
+
| Initial state ON | Initial internal state after deployment or restart. It does not emit a message by itself. It is also restored by `msg.reset = true`. |
|
|
130
|
+
| Emit only on change | When enabled, output 1 emits only when the state changes. When disabled, every valid numeric input emits the current ON/OFF state. |
|
|
131
|
+
| Input | Numeric message property to evaluate. The default is `msg.payload`; numbers, booleans and numeric strings are accepted. |
|
|
132
|
+
| Translator | Optional shared translator configuration associated with the input. Hysteresis evaluation uses the numeric value of the selected input property. |
|
|
133
|
+
| On payload | Typed value written to `msg.payload` on output 1 when the state is ON. |
|
|
134
|
+
| Off payload | Typed value written to `msg.payload` on output 1 when the state is OFF. |
|
|
130
135
|
|
|
131
|
-
|
|
136
|
+
### Inputs
|
|
137
|
+
|
|
138
|
+
Normal input messages are evaluated using the configured **Input** property. An absent or non-numeric value produces an `invalid_input` diagnostic on output 2.
|
|
139
|
+
|
|
140
|
+
The following commands are consumed only when `msg.topic` equals **Control topic**:
|
|
132
141
|
|
|
133
142
|
- `msg.onThreshold`, `msg.offThreshold` to update thresholds at runtime.
|
|
134
|
-
- `msg.state = true|false` to force state.
|
|
135
|
-
- `msg.reset = true` to restore initial state.
|
|
143
|
+
- `msg.state = true|false` to force the state and emit it on output 1. While locked, it updates the internal state without emitting on output 1.
|
|
144
|
+
- `msg.reset = true` to restore the configured initial state and emit a `reset` diagnostic.
|
|
136
145
|
- `msg.status = true` to emit current status on output 2.
|
|
137
|
-
|
|
146
|
+
|
|
147
|
+
`msg.permanentLockState` is handled regardless of `msg.topic`:
|
|
148
|
+
|
|
149
|
+
- `"lock"` suppresses state output until another valid permanent-lock command arrives.
|
|
150
|
+
- `"lockOn"` forces ON and emits the configured **On payload** once, then suppresses state output.
|
|
151
|
+
- `"lockOff"` forces OFF and emits the configured **Off payload** once, then suppresses state output.
|
|
152
|
+
- `"unlock"` resumes normal processing. The unlock message itself is consumed.
|
|
153
|
+
|
|
154
|
+
While locked, normal input messages are ignored and output 1 remains suppressed. Control-topic commands remain active: thresholds can be updated, `state` and `reset` can change the internal state, and `status`/`reset` diagnostics can still be emitted on output 2.
|
|
155
|
+
|
|
156
|
+
### Outputs
|
|
157
|
+
|
|
158
|
+
1. **State output**: a clone of the input message with the configured ON/OFF `msg.payload`, `msg.event` (`state_changed` or `state_confirmed`) and `msg.hysteresis`, containing `state`, `changed`, `mode`, input `value`, `onThreshold` and `offThreshold`.
|
|
159
|
+
2. **Diagnostics**: events for state changes, invalid inputs, reset and status. The topic is `<controlTopic>/event`, and `msg.payload` contains the event details.
|
|
160
|
+
</script>
|
|
@@ -18,6 +18,7 @@ module.exports = function (RED) {
|
|
|
18
18
|
let onThreshold = Number(config.onThreshold);
|
|
19
19
|
let offThreshold = Number(config.offThreshold);
|
|
20
20
|
let state = Boolean(config.initialState);
|
|
21
|
+
let permanentLockState = 'unlock';
|
|
21
22
|
|
|
22
23
|
if (!Number.isFinite(onThreshold)) onThreshold = 70;
|
|
23
24
|
if (!Number.isFinite(offThreshold)) offThreshold = 65;
|
|
@@ -47,10 +48,11 @@ module.exports = function (RED) {
|
|
|
47
48
|
function updateStatus(lastValue) {
|
|
48
49
|
const direction = mode === 'low' ? 'LOW' : 'HIGH';
|
|
49
50
|
const valueText = lastValue === undefined ? '-' : Number(lastValue).toFixed(2);
|
|
51
|
+
const lockText = permanentLockState === 'unlock' ? '' : ` ${permanentLockState}`;
|
|
50
52
|
setNodeStatus({
|
|
51
53
|
fill: state ? 'green' : 'grey',
|
|
52
54
|
shape: state ? 'dot' : 'ring',
|
|
53
|
-
text: `${direction} ${valueText} on:${onThreshold} off:${offThreshold}`,
|
|
55
|
+
text: `${direction} ${valueText} on:${onThreshold} off:${offThreshold}${lockText}`,
|
|
54
56
|
});
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -101,7 +103,7 @@ module.exports = function (RED) {
|
|
|
101
103
|
updateStatus(inputValue);
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
function handleControl(msg) {
|
|
106
|
+
function handleControl(msg, suppressStateOutput) {
|
|
105
107
|
let consumed = false;
|
|
106
108
|
|
|
107
109
|
if (msg.reset === true) {
|
|
@@ -134,7 +136,9 @@ module.exports = function (RED) {
|
|
|
134
136
|
|
|
135
137
|
if (Object.prototype.hasOwnProperty.call(msg, 'state')) {
|
|
136
138
|
state = Boolean(msg.state);
|
|
137
|
-
|
|
139
|
+
if (!suppressStateOutput) {
|
|
140
|
+
emitState(msg, true, undefined);
|
|
141
|
+
}
|
|
138
142
|
consumed = true;
|
|
139
143
|
}
|
|
140
144
|
|
|
@@ -156,8 +160,46 @@ module.exports = function (RED) {
|
|
|
156
160
|
return consumed;
|
|
157
161
|
}
|
|
158
162
|
|
|
163
|
+
function handlePermanentLock(msg) {
|
|
164
|
+
if (!Object.prototype.hasOwnProperty.call(msg, 'permanentLockState')) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const command = msg.permanentLockState;
|
|
169
|
+
if (!['unlock', 'lock', 'lockOff', 'lockOn'].includes(command)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (command === 'unlock') {
|
|
174
|
+
permanentLockState = 'unlock';
|
|
175
|
+
updateStatus();
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
permanentLockState = command;
|
|
180
|
+
if (command === 'lockOn' || command === 'lockOff') {
|
|
181
|
+
state = command === 'lockOn';
|
|
182
|
+
emitState(msg, true, undefined);
|
|
183
|
+
} else {
|
|
184
|
+
updateStatus();
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
|
|
159
189
|
node.on('input', (msg) => {
|
|
160
|
-
if (
|
|
190
|
+
if (handlePermanentLock(msg)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const isLocked = permanentLockState !== 'unlock';
|
|
195
|
+
|
|
196
|
+
if (msg.topic === controlTopic) {
|
|
197
|
+
if (handleControl(msg, isLocked) || isLocked) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (isLocked) {
|
|
161
203
|
return;
|
|
162
204
|
}
|
|
163
205
|
|
|
@@ -76,6 +76,80 @@
|
|
|
76
76
|
"y": 240,
|
|
77
77
|
"wires": [["hys-node"]]
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"id": "hys-lock-comment",
|
|
81
|
+
"type": "comment",
|
|
82
|
+
"z": "hys-flow",
|
|
83
|
+
"name": "Permanent output lock commands (independent of msg.topic)",
|
|
84
|
+
"info": "lock: suppress state output\nlockOn: emit ON once, then suppress state output\nlockOff: emit OFF once, then suppress state output\nunlock: resume normal processing\n\nControl-topic commands and diagnostics remain active while locked.",
|
|
85
|
+
"x": 310,
|
|
86
|
+
"y": 320,
|
|
87
|
+
"wires": []
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "hys-lock",
|
|
91
|
+
"type": "inject",
|
|
92
|
+
"z": "hys-flow",
|
|
93
|
+
"name": "Lock without output",
|
|
94
|
+
"props": [
|
|
95
|
+
{ "p": "permanentLockState", "v": "lock", "vt": "str" }
|
|
96
|
+
],
|
|
97
|
+
"repeat": "",
|
|
98
|
+
"crontab": "",
|
|
99
|
+
"once": false,
|
|
100
|
+
"onceDelay": 0.1,
|
|
101
|
+
"x": 230,
|
|
102
|
+
"y": 360,
|
|
103
|
+
"wires": [["hys-node"]]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "hys-lock-on",
|
|
107
|
+
"type": "inject",
|
|
108
|
+
"z": "hys-flow",
|
|
109
|
+
"name": "Force ON and lock",
|
|
110
|
+
"props": [
|
|
111
|
+
{ "p": "permanentLockState", "v": "lockOn", "vt": "str" }
|
|
112
|
+
],
|
|
113
|
+
"repeat": "",
|
|
114
|
+
"crontab": "",
|
|
115
|
+
"once": false,
|
|
116
|
+
"onceDelay": 0.1,
|
|
117
|
+
"x": 230,
|
|
118
|
+
"y": 400,
|
|
119
|
+
"wires": [["hys-node"]]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"id": "hys-lock-off",
|
|
123
|
+
"type": "inject",
|
|
124
|
+
"z": "hys-flow",
|
|
125
|
+
"name": "Force OFF and lock",
|
|
126
|
+
"props": [
|
|
127
|
+
{ "p": "permanentLockState", "v": "lockOff", "vt": "str" }
|
|
128
|
+
],
|
|
129
|
+
"repeat": "",
|
|
130
|
+
"crontab": "",
|
|
131
|
+
"once": false,
|
|
132
|
+
"onceDelay": 0.1,
|
|
133
|
+
"x": 230,
|
|
134
|
+
"y": 440,
|
|
135
|
+
"wires": [["hys-node"]]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"id": "hys-unlock",
|
|
139
|
+
"type": "inject",
|
|
140
|
+
"z": "hys-flow",
|
|
141
|
+
"name": "Unlock",
|
|
142
|
+
"props": [
|
|
143
|
+
{ "p": "permanentLockState", "v": "unlock", "vt": "str" }
|
|
144
|
+
],
|
|
145
|
+
"repeat": "",
|
|
146
|
+
"crontab": "",
|
|
147
|
+
"once": false,
|
|
148
|
+
"onceDelay": 0.1,
|
|
149
|
+
"x": 200,
|
|
150
|
+
"y": 480,
|
|
151
|
+
"wires": [["hys-node"]]
|
|
152
|
+
},
|
|
79
153
|
{
|
|
80
154
|
"id": "hys-out",
|
|
81
155
|
"type": "debug",
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-boolean-logic-ultimate",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.17",
|
|
4
4
|
"description": "A set of Node-RED enhanced boolean logic and utility nodes, flow interruption, blinker, debouncer, invert, filter, toggle etc.., with persistent values after reboot. Compatible also with Homeassistant values.",
|
|
5
|
-
"author":
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Massimo Saccani",
|
|
7
|
+
"email": "maxsupergiovane@icloud.com",
|
|
8
|
+
"url": "https://youtube.com/@maxsupervibe"
|
|
9
|
+
},
|
|
6
10
|
"dependencies": {
|
|
7
|
-
"fs": "0.0.1-security",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
11
|
+
"fs": "^0.0.1-security",
|
|
12
|
+
"kalmanjs": "^1.1.0",
|
|
13
|
+
"path": "^0.12.7"
|
|
10
14
|
},
|
|
11
15
|
"devDependencies": {
|
|
12
|
-
"chai": "^
|
|
13
|
-
"mocha": "^
|
|
14
|
-
"node-red": "^
|
|
15
|
-
"node-red-node-test-helper": "^0.3.
|
|
16
|
+
"chai": "^6.2.2",
|
|
17
|
+
"mocha": "^11.7.6",
|
|
18
|
+
"node-red": "^5.0.1",
|
|
19
|
+
"node-red-node-test-helper": "^0.3.6"
|
|
16
20
|
},
|
|
17
21
|
"keywords": [
|
|
18
22
|
"node-red",
|
|
23
|
+
"node-red-contrib",
|
|
19
24
|
"boolean",
|
|
25
|
+
"logic",
|
|
20
26
|
"gate",
|
|
21
27
|
"filter",
|
|
22
|
-
"
|
|
28
|
+
"debounce",
|
|
29
|
+
"toggle",
|
|
30
|
+
"blinker",
|
|
31
|
+
"comparator",
|
|
32
|
+
"hysteresis",
|
|
33
|
+
"rate-limiter",
|
|
34
|
+
"kalman",
|
|
35
|
+
"utility",
|
|
36
|
+
"home-assistant",
|
|
37
|
+
"home-automation"
|
|
23
38
|
],
|
|
24
39
|
"license": "MIT",
|
|
25
40
|
"repository": {
|
|
@@ -54,4 +69,4 @@
|
|
|
54
69
|
"scripts": {
|
|
55
70
|
"test": "mocha test/**/*.spec.js"
|
|
56
71
|
}
|
|
57
|
-
}
|
|
72
|
+
}
|
package/test/hysteresis.spec.js
CHANGED
|
@@ -84,4 +84,61 @@ describe('HysteresisUltimate node', function () {
|
|
|
84
84
|
hys.receive({ topic: 'sensor', payload: 58 });
|
|
85
85
|
}).catch(done);
|
|
86
86
|
});
|
|
87
|
+
|
|
88
|
+
it('supports permanent lock, lockOn, lockOff and unlock commands', function (done) {
|
|
89
|
+
const flowId = 'hys-lock';
|
|
90
|
+
const flow = [
|
|
91
|
+
{ id: flowId, type: 'tab', label: 'hys-lock' },
|
|
92
|
+
{
|
|
93
|
+
id: 'hys',
|
|
94
|
+
type: 'HysteresisUltimate',
|
|
95
|
+
z: flowId,
|
|
96
|
+
mode: 'high',
|
|
97
|
+
onThreshold: 70,
|
|
98
|
+
offThreshold: 60,
|
|
99
|
+
emitOnlyOnChange: true,
|
|
100
|
+
onPayload: 'on',
|
|
101
|
+
onPayloadType: 'str',
|
|
102
|
+
offPayload: 'off',
|
|
103
|
+
offPayloadType: 'str',
|
|
104
|
+
wires: [['out'], ['diag']],
|
|
105
|
+
},
|
|
106
|
+
{ id: 'out', type: 'helper', z: flowId },
|
|
107
|
+
{ id: 'diag', type: 'helper', z: flowId },
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
loadHysteresis(flow).then(() => {
|
|
111
|
+
const hys = helper.getNode('hys');
|
|
112
|
+
const out = helper.getNode('out');
|
|
113
|
+
const diag = helper.getNode('diag');
|
|
114
|
+
const outputPayloads = [];
|
|
115
|
+
const diagnostics = [];
|
|
116
|
+
|
|
117
|
+
out.on('input', (msg) => outputPayloads.push(msg.payload));
|
|
118
|
+
diag.on('input', (msg) => diagnostics.push(msg.payload));
|
|
119
|
+
|
|
120
|
+
hys.receive({ permanentLockState: 'lockOn' });
|
|
121
|
+
hys.receive({ payload: 55 });
|
|
122
|
+
hys.receive({ topic: 'hysteresis', onThreshold: 74, status: true });
|
|
123
|
+
hys.receive({ topic: 'hysteresis', state: false });
|
|
124
|
+
hys.receive({ permanentLockState: 'lockOff' });
|
|
125
|
+
hys.receive({ payload: 75 });
|
|
126
|
+
hys.receive({ permanentLockState: 'lock' });
|
|
127
|
+
hys.receive({ payload: 75 });
|
|
128
|
+
hys.receive({ permanentLockState: 'unlock' });
|
|
129
|
+
hys.receive({ payload: 75 });
|
|
130
|
+
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
try {
|
|
133
|
+
expect(outputPayloads).to.deep.equal(['on', 'off', 'on']);
|
|
134
|
+
expect(diagnostics).to.have.length(2);
|
|
135
|
+
expect(diagnostics[0]).to.include({ event: 'status', state: true, onThreshold: 74 });
|
|
136
|
+
expect(diagnostics[1]).to.include({ event: 'state_changed', state: true, onThreshold: 74 });
|
|
137
|
+
done();
|
|
138
|
+
} catch (error) {
|
|
139
|
+
done(error);
|
|
140
|
+
}
|
|
141
|
+
}, 50);
|
|
142
|
+
}).catch(done);
|
|
143
|
+
});
|
|
87
144
|
});
|