@mschaeffler/node-red-logic 0.2.1 → 0.4.3
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/README.md +98 -3
- package/counter.js +3 -0
- package/examples/edge.json +323 -0
- package/examples/edge.png +0 -0
- package/icons/falling-edge.png +0 -0
- package/icons/hysteresis.png +0 -0
- package/icons/raising-edge.png +0 -0
- package/logic_and.js +30 -22
- package/logic_bool.html +8 -1
- package/logic_bool.js +9 -2
- package/logic_or.js +30 -22
- package/math_falling.html +81 -0
- package/math_falling.js +52 -0
- package/math_hysteresis.html +103 -0
- package/math_hysteresis.js +81 -0
- package/math_number.html +8 -1
- package/math_number.js +10 -3
- package/math_raising.html +81 -0
- package/math_raising.js +52 -0
- package/math_reduce.html +9 -2
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Nodes to perform boolean and arithmetic operations on input signals.
|
|
|
10
10
|
$ npm install @mschaeffler/node-red-logic
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Nodes
|
|
14
14
|
|
|
15
15
|
### counter
|
|
16
16
|
|
|
@@ -58,6 +58,7 @@ The message property to be used as payload can be defined with the `Property` pr
|
|
|
58
58
|
|config| type | description |
|
|
59
59
|
|:-----|:-------|:----------------------------------|
|
|
60
60
|
|Property| string | defines the message property to be used as payload.|
|
|
61
|
+
|Status|boolean|shows the actual value as a node status.|
|
|
61
62
|
|
|
62
63
|
### or
|
|
63
64
|
|
|
@@ -146,6 +147,7 @@ The message property to be used as payload can be defined with the `Property` pr
|
|
|
146
147
|
|config| type | description |
|
|
147
148
|
|:-----|:-------|:----------------------------------|
|
|
148
149
|
|Property| string | defines the message property to be used as payload.|
|
|
150
|
+
|Status|boolean|shows the actual value as a node status.|
|
|
149
151
|
|
|
150
152
|
### reduce
|
|
151
153
|
|
|
@@ -184,14 +186,107 @@ The message property to be used as payload can be defined with the `Property` pr
|
|
|
184
186
|
|
|
185
187
|
#### Algorithms
|
|
186
188
|
|
|
187
|
-
## Example Flow
|
|
188
189
|
|
|
189
|
-
|
|
190
|
+
## Edge Nodes
|
|
191
|
+
|
|
192
|
+

|
|
193
|
+
|
|
194
|
+
### fallingEdge
|
|
195
|
+
|
|
196
|
+
Message is only forwarded, if the payload falls below a threshold value.
|
|
197
|
+
|
|
198
|
+
Each `topic` is treated seperatly.
|
|
199
|
+
|
|
200
|
+
#### Input
|
|
201
|
+
|
|
202
|
+
The message property to be used as payload can be defined with the `Property` property.
|
|
203
|
+
|
|
204
|
+
|msg. | type | description |
|
|
205
|
+
|:-------|:-------|:----------------------------------|
|
|
206
|
+
|topic | string | name of the input channel. |
|
|
207
|
+
|payload | number | input value for `topic`. |
|
|
208
|
+
|
|
209
|
+
#### Output
|
|
210
|
+
|
|
211
|
+
Trigger message, in case a falling edge is detected.
|
|
212
|
+
|
|
213
|
+
#### Parameters
|
|
214
|
+
|
|
215
|
+
|config| type | description |
|
|
216
|
+
|:-----|:-------|:----------------------------------|
|
|
217
|
+
|Property| string | defines the message property to be used as payload.|
|
|
218
|
+
|Threshold|number|threshold value for the edge detection.|
|
|
219
|
+
|Status|boolean|shows the actual value as a node status.|
|
|
220
|
+
|
|
221
|
+
### raisingEdge
|
|
222
|
+
|
|
223
|
+
Message is only forwarded, if the payload raises above a threshold value.
|
|
224
|
+
|
|
225
|
+
Each `topic` is treated seperatly.
|
|
226
|
+
|
|
227
|
+
#### Input
|
|
228
|
+
|
|
229
|
+
The message property to be used as payload can be defined with the `Property` property.
|
|
230
|
+
|
|
231
|
+
|msg. | type | description |
|
|
232
|
+
|:-------|:-------|:----------------------------------|
|
|
233
|
+
|topic | string | name of the input channel. |
|
|
234
|
+
|payload | number | input value for `topic`. |
|
|
235
|
+
|
|
236
|
+
#### Output
|
|
237
|
+
|
|
238
|
+
Trigger message, in case a raising edge is detected.
|
|
239
|
+
|
|
240
|
+
#### Parameters
|
|
241
|
+
|
|
242
|
+
|config| type | description |
|
|
243
|
+
|:-----|:-------|:----------------------------------|
|
|
244
|
+
|Property| string | defines the message property to be used as payload.|
|
|
245
|
+
|Threshold|number|threshold value for the edge detection.|
|
|
246
|
+
|Status|boolean|shows the actual value as a node status.|
|
|
247
|
+
|
|
248
|
+
### hysteresis
|
|
249
|
+
|
|
250
|
+
Message is only forwarded, if the payload raises above an upper limit or falls below a lower limit.
|
|
251
|
+
|
|
252
|
+
Each `topic` is treated seperatly.
|
|
253
|
+
|
|
254
|
+
#### Input
|
|
255
|
+
|
|
256
|
+
The message property to be used as payload can be defined with the `Property` property.
|
|
257
|
+
|
|
258
|
+
|msg. | type | description |
|
|
259
|
+
|:-------|:-------|:----------------------------------|
|
|
260
|
+
|topic | string | name of the input channel. |
|
|
261
|
+
|payload | number | input value for `topic`. |
|
|
262
|
+
|
|
263
|
+
#### Output
|
|
264
|
+
|
|
265
|
+
Trigger message, in case an edge is detected.
|
|
266
|
+
|
|
267
|
+
#### Parameters
|
|
268
|
+
|
|
269
|
+
|config| type | description |
|
|
270
|
+
|:-----|:-------|:----------------------------------|
|
|
271
|
+
|Property| string | defines the message property to be used as payload.|
|
|
272
|
+
|up Threshold|number|threshold value for the raising edge detection.|
|
|
273
|
+
|d(ow)n Threshold|number|threshold value for the falling edge detection.|
|
|
274
|
+
|1st message|string|initial behaviour (None, Rising, Falling, Any).|
|
|
275
|
+
|Status|boolean|shows the actual value as a node status.|
|
|
276
|
+
|
|
277
|
+
## Example Flows
|
|
278
|
+
|
|
279
|
+
[edge nodes](https://github.com/m-schaeffler/node-red-my-nodes/raw/main/node-red-logic/examples/edge.json)
|
|
190
280
|
|
|
191
281
|
## Author
|
|
192
282
|
|
|
193
283
|
[Mathias Schäffler](https://github.com/m-schaeffler)
|
|
194
284
|
|
|
285
|
+
## Contributors
|
|
286
|
+
|
|
287
|
+
for `falling edge`, `raising edge` and `hysteresis`:
|
|
288
|
+
* [Eugene Schava](https://github.com/eschava/node-red-contrib-edge-trigger)
|
|
289
|
+
|
|
195
290
|
## License
|
|
196
291
|
|
|
197
292
|
LGPL-2.1
|
package/counter.js
CHANGED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "4970749d37068d6b",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Flow 1",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "",
|
|
8
|
+
"env": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "52d9bc78e16a9148",
|
|
12
|
+
"type": "fallingEdge",
|
|
13
|
+
"z": "4970749d37068d6b",
|
|
14
|
+
"name": "",
|
|
15
|
+
"property": "payload",
|
|
16
|
+
"threshold": "0.5",
|
|
17
|
+
"showState": true,
|
|
18
|
+
"x": 350,
|
|
19
|
+
"y": 180,
|
|
20
|
+
"wires": [
|
|
21
|
+
[
|
|
22
|
+
"77726eaa088e280b"
|
|
23
|
+
]
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "77726eaa088e280b",
|
|
28
|
+
"type": "debug",
|
|
29
|
+
"z": "4970749d37068d6b",
|
|
30
|
+
"name": "",
|
|
31
|
+
"active": false,
|
|
32
|
+
"tosidebar": true,
|
|
33
|
+
"console": false,
|
|
34
|
+
"tostatus": true,
|
|
35
|
+
"complete": "edge",
|
|
36
|
+
"targetType": "msg",
|
|
37
|
+
"statusVal": "payload",
|
|
38
|
+
"statusType": "auto",
|
|
39
|
+
"x": 520,
|
|
40
|
+
"y": 180,
|
|
41
|
+
"wires": []
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "ac8e06cc38b44b25",
|
|
45
|
+
"type": "inject",
|
|
46
|
+
"z": "4970749d37068d6b",
|
|
47
|
+
"name": "",
|
|
48
|
+
"props": [
|
|
49
|
+
{
|
|
50
|
+
"p": "topic",
|
|
51
|
+
"vt": "str"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"p": "payload"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"repeat": "",
|
|
58
|
+
"crontab": "",
|
|
59
|
+
"once": false,
|
|
60
|
+
"onceDelay": 0.1,
|
|
61
|
+
"topic": "A",
|
|
62
|
+
"payload": "invalid",
|
|
63
|
+
"payloadType": "str",
|
|
64
|
+
"x": 140,
|
|
65
|
+
"y": 140,
|
|
66
|
+
"wires": [
|
|
67
|
+
[
|
|
68
|
+
"a24056951606f51c",
|
|
69
|
+
"52d9bc78e16a9148"
|
|
70
|
+
]
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "c3c3954adcb27b9f",
|
|
75
|
+
"type": "inject",
|
|
76
|
+
"z": "4970749d37068d6b",
|
|
77
|
+
"name": "",
|
|
78
|
+
"props": [
|
|
79
|
+
{
|
|
80
|
+
"p": "topic",
|
|
81
|
+
"vt": "str"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"p": "payload"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"repeat": "",
|
|
88
|
+
"crontab": "",
|
|
89
|
+
"once": false,
|
|
90
|
+
"onceDelay": 0.1,
|
|
91
|
+
"topic": "B",
|
|
92
|
+
"payload": "5",
|
|
93
|
+
"payloadType": "num",
|
|
94
|
+
"x": 150,
|
|
95
|
+
"y": 280,
|
|
96
|
+
"wires": [
|
|
97
|
+
[
|
|
98
|
+
"a24056951606f51c",
|
|
99
|
+
"52d9bc78e16a9148",
|
|
100
|
+
"6c0fc0087d21517c"
|
|
101
|
+
]
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "f968bad2f0afca41",
|
|
106
|
+
"type": "inject",
|
|
107
|
+
"z": "4970749d37068d6b",
|
|
108
|
+
"name": "",
|
|
109
|
+
"props": [
|
|
110
|
+
{
|
|
111
|
+
"p": "topic",
|
|
112
|
+
"vt": "str"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"p": "payload"
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"repeat": "",
|
|
119
|
+
"crontab": "",
|
|
120
|
+
"once": false,
|
|
121
|
+
"onceDelay": 0.1,
|
|
122
|
+
"topic": "A",
|
|
123
|
+
"payload": "true",
|
|
124
|
+
"payloadType": "bool",
|
|
125
|
+
"x": 150,
|
|
126
|
+
"y": 180,
|
|
127
|
+
"wires": [
|
|
128
|
+
[
|
|
129
|
+
"a24056951606f51c",
|
|
130
|
+
"52d9bc78e16a9148"
|
|
131
|
+
]
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "ad9fbb99931a81c4",
|
|
136
|
+
"type": "inject",
|
|
137
|
+
"z": "4970749d37068d6b",
|
|
138
|
+
"name": "",
|
|
139
|
+
"props": [
|
|
140
|
+
{
|
|
141
|
+
"p": "topic",
|
|
142
|
+
"vt": "str"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"p": "payload"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"repeat": "",
|
|
149
|
+
"crontab": "",
|
|
150
|
+
"once": false,
|
|
151
|
+
"onceDelay": 0.1,
|
|
152
|
+
"topic": "A",
|
|
153
|
+
"payload": "false",
|
|
154
|
+
"payloadType": "bool",
|
|
155
|
+
"x": 150,
|
|
156
|
+
"y": 220,
|
|
157
|
+
"wires": [
|
|
158
|
+
[
|
|
159
|
+
"a24056951606f51c",
|
|
160
|
+
"52d9bc78e16a9148"
|
|
161
|
+
]
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "f1ab2e7739f49adf",
|
|
166
|
+
"type": "inject",
|
|
167
|
+
"z": "4970749d37068d6b",
|
|
168
|
+
"name": "",
|
|
169
|
+
"props": [
|
|
170
|
+
{
|
|
171
|
+
"p": "topic",
|
|
172
|
+
"vt": "str"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"p": "payload"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"repeat": "",
|
|
179
|
+
"crontab": "",
|
|
180
|
+
"once": false,
|
|
181
|
+
"onceDelay": 0.1,
|
|
182
|
+
"topic": "B",
|
|
183
|
+
"payload": "-5",
|
|
184
|
+
"payloadType": "num",
|
|
185
|
+
"x": 150,
|
|
186
|
+
"y": 320,
|
|
187
|
+
"wires": [
|
|
188
|
+
[
|
|
189
|
+
"a24056951606f51c",
|
|
190
|
+
"52d9bc78e16a9148",
|
|
191
|
+
"6c0fc0087d21517c"
|
|
192
|
+
]
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "a24056951606f51c",
|
|
197
|
+
"type": "raisingEdge",
|
|
198
|
+
"z": "4970749d37068d6b",
|
|
199
|
+
"name": "",
|
|
200
|
+
"property": "payload",
|
|
201
|
+
"threshold": "0.5",
|
|
202
|
+
"showState": true,
|
|
203
|
+
"x": 350,
|
|
204
|
+
"y": 240,
|
|
205
|
+
"wires": [
|
|
206
|
+
[
|
|
207
|
+
"fe404d9f9c32f265"
|
|
208
|
+
]
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "fe655bd06e553598",
|
|
213
|
+
"type": "inject",
|
|
214
|
+
"z": "4970749d37068d6b",
|
|
215
|
+
"name": "reset",
|
|
216
|
+
"props": [
|
|
217
|
+
{
|
|
218
|
+
"p": "reset",
|
|
219
|
+
"v": "true",
|
|
220
|
+
"vt": "bool"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"p": "topic",
|
|
224
|
+
"vt": "str"
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
"repeat": "",
|
|
228
|
+
"crontab": "",
|
|
229
|
+
"once": false,
|
|
230
|
+
"onceDelay": 0.1,
|
|
231
|
+
"topic": "",
|
|
232
|
+
"x": 150,
|
|
233
|
+
"y": 80,
|
|
234
|
+
"wires": [
|
|
235
|
+
[
|
|
236
|
+
"a24056951606f51c",
|
|
237
|
+
"52d9bc78e16a9148",
|
|
238
|
+
"6c0fc0087d21517c"
|
|
239
|
+
]
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"id": "fe404d9f9c32f265",
|
|
244
|
+
"type": "debug",
|
|
245
|
+
"z": "4970749d37068d6b",
|
|
246
|
+
"name": "",
|
|
247
|
+
"active": false,
|
|
248
|
+
"tosidebar": true,
|
|
249
|
+
"console": false,
|
|
250
|
+
"tostatus": true,
|
|
251
|
+
"complete": "edge",
|
|
252
|
+
"targetType": "msg",
|
|
253
|
+
"statusVal": "",
|
|
254
|
+
"statusType": "auto",
|
|
255
|
+
"x": 520,
|
|
256
|
+
"y": 240,
|
|
257
|
+
"wires": []
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"id": "50bd9f615e8929df",
|
|
261
|
+
"type": "debug",
|
|
262
|
+
"z": "4970749d37068d6b",
|
|
263
|
+
"name": "",
|
|
264
|
+
"active": true,
|
|
265
|
+
"tosidebar": true,
|
|
266
|
+
"console": false,
|
|
267
|
+
"tostatus": true,
|
|
268
|
+
"complete": "edge",
|
|
269
|
+
"targetType": "msg",
|
|
270
|
+
"statusVal": "payload",
|
|
271
|
+
"statusType": "auto",
|
|
272
|
+
"x": 520,
|
|
273
|
+
"y": 320,
|
|
274
|
+
"wires": []
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"id": "6c0fc0087d21517c",
|
|
278
|
+
"type": "hysteresisEdge",
|
|
279
|
+
"z": "4970749d37068d6b",
|
|
280
|
+
"name": "",
|
|
281
|
+
"property": "payload",
|
|
282
|
+
"threshold_raise": "1",
|
|
283
|
+
"threshold_fall": "-1",
|
|
284
|
+
"initial": "falling",
|
|
285
|
+
"showState": true,
|
|
286
|
+
"x": 360,
|
|
287
|
+
"y": 320,
|
|
288
|
+
"wires": [
|
|
289
|
+
[
|
|
290
|
+
"50bd9f615e8929df"
|
|
291
|
+
]
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"id": "23a7bae9cad0dd16",
|
|
296
|
+
"type": "inject",
|
|
297
|
+
"z": "4970749d37068d6b",
|
|
298
|
+
"name": "",
|
|
299
|
+
"props": [
|
|
300
|
+
{
|
|
301
|
+
"p": "topic",
|
|
302
|
+
"vt": "str"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"p": "payload"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"repeat": "",
|
|
309
|
+
"crontab": "",
|
|
310
|
+
"once": false,
|
|
311
|
+
"onceDelay": 0.1,
|
|
312
|
+
"topic": "B",
|
|
313
|
+
"payload": "0",
|
|
314
|
+
"payloadType": "num",
|
|
315
|
+
"x": 150,
|
|
316
|
+
"y": 360,
|
|
317
|
+
"wires": [
|
|
318
|
+
[
|
|
319
|
+
"6c0fc0087d21517c"
|
|
320
|
+
]
|
|
321
|
+
]
|
|
322
|
+
}
|
|
323
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/logic_and.js
CHANGED
|
@@ -11,34 +11,42 @@ module.exports = function(RED) {
|
|
|
11
11
|
this.minData = Number( config.minData );
|
|
12
12
|
|
|
13
13
|
node.on('input', function(msg,send,done) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if( msg.reset || msg.topic==="init" )
|
|
15
|
+
{
|
|
16
|
+
context.set( "data", {} );
|
|
17
|
+
node.status( "" );
|
|
18
|
+
}
|
|
19
|
+
else
|
|
17
20
|
{
|
|
18
|
-
|
|
19
|
-
data[msg.topic] = payload;
|
|
20
|
-
context.set( "data", data );
|
|
21
|
+
const payload = tools.property2boolean( RED.util.getMessageProperty( msg, node.property ) );
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
msg.payload = true;
|
|
24
|
-
msg.count = 0;
|
|
25
|
-
for( const item in data )
|
|
23
|
+
if( payload !== null )
|
|
26
24
|
{
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
let data = context.get( "data" ) ?? {};
|
|
26
|
+
data[msg.topic] = payload;
|
|
27
|
+
context.set( "data", data );
|
|
28
|
+
|
|
29
|
+
msg.topic = node.topic;
|
|
30
|
+
msg.payload = true;
|
|
31
|
+
msg.count = 0;
|
|
32
|
+
for( const item in data )
|
|
29
33
|
{
|
|
30
|
-
|
|
34
|
+
msg.count++;
|
|
35
|
+
if( ! data[item] )
|
|
36
|
+
{
|
|
37
|
+
msg.payload = false;
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
|
-
}
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
if( msg.count >= node.minData )
|
|
42
|
+
{
|
|
43
|
+
node.status( msg.payload );
|
|
44
|
+
send( msg );
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
{
|
|
48
|
+
node.status( "waiting for data" );
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
52
|
|
package/logic_bool.html
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
color: "#C0DEED",
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
|
-
property:{value:"payload",required:true}
|
|
7
|
+
property:{value:"payload",required:true},
|
|
8
|
+
showState:{value:false}
|
|
8
9
|
},
|
|
9
10
|
inputs:1,
|
|
10
11
|
outputs:1,
|
|
@@ -35,6 +36,10 @@
|
|
|
35
36
|
<input type="text" id="node-input-property">
|
|
36
37
|
<input type="hidden" id="node-input-property-type">
|
|
37
38
|
</div>
|
|
39
|
+
<div class="form-row">
|
|
40
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
41
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
42
|
+
</div>
|
|
38
43
|
</script>
|
|
39
44
|
|
|
40
45
|
<script type="text/html" data-help-name="tobool">
|
|
@@ -76,6 +81,8 @@
|
|
|
76
81
|
<dl class="message-properties">
|
|
77
82
|
<dt>Property <span class="property-type">string</span></dt>
|
|
78
83
|
<dd> defines the message property to be used as payload.</dd>
|
|
84
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
85
|
+
<dd> shows the actual value as a node status.</dd>
|
|
79
86
|
</dl>
|
|
80
87
|
|
|
81
88
|
</script>
|
package/logic_bool.js
CHANGED
|
@@ -6,18 +6,25 @@ module.exports = function(RED) {
|
|
|
6
6
|
//this.config = config;
|
|
7
7
|
var node = this;
|
|
8
8
|
this.property = config.property || "payload";
|
|
9
|
+
this.showState = config.showState;
|
|
9
10
|
|
|
10
11
|
node.on('input', function(msg,send,done) {
|
|
11
12
|
msg.payload = tools.property2boolean( RED.util.getMessageProperty( msg, node.property ) );
|
|
12
13
|
|
|
13
14
|
if( msg.payload !== null )
|
|
14
15
|
{
|
|
15
|
-
|
|
16
|
+
if( node.showState )
|
|
17
|
+
{
|
|
18
|
+
node.status( msg.payload );
|
|
19
|
+
}
|
|
16
20
|
send( msg );
|
|
17
21
|
}
|
|
18
22
|
else
|
|
19
23
|
{
|
|
20
|
-
node.
|
|
24
|
+
if( node.showState )
|
|
25
|
+
{
|
|
26
|
+
node.status( "error" );
|
|
27
|
+
}
|
|
21
28
|
}
|
|
22
29
|
done();
|
|
23
30
|
});
|
package/logic_or.js
CHANGED
|
@@ -11,34 +11,42 @@ module.exports = function(RED) {
|
|
|
11
11
|
this.minData = Number( config.minData );
|
|
12
12
|
|
|
13
13
|
node.on('input', function(msg,send,done) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if( msg.reset || msg.topic==="init" )
|
|
15
|
+
{
|
|
16
|
+
context.set( "data", {} );
|
|
17
|
+
node.status( "" );
|
|
18
|
+
}
|
|
19
|
+
else
|
|
17
20
|
{
|
|
18
|
-
|
|
19
|
-
data[msg.topic] = payload;
|
|
20
|
-
context.set( "data", data );
|
|
21
|
+
const payload = tools.property2boolean( RED.util.getMessageProperty( msg, node.property ) );
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
msg.payload = false;
|
|
24
|
-
msg.count = 0;
|
|
25
|
-
for( const item in data )
|
|
23
|
+
if( payload !== null )
|
|
26
24
|
{
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
let data = context.get( "data" ) ?? {};
|
|
26
|
+
data[msg.topic] = payload;
|
|
27
|
+
context.set( "data", data );
|
|
28
|
+
|
|
29
|
+
msg.topic = node.topic;
|
|
30
|
+
msg.payload = false;
|
|
31
|
+
msg.count = 0;
|
|
32
|
+
for( const item in data )
|
|
29
33
|
{
|
|
30
|
-
msg.
|
|
34
|
+
msg.count++;
|
|
35
|
+
if( data[item] )
|
|
36
|
+
{
|
|
37
|
+
msg.payload = true;
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
|
-
}
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
if( msg.count >= node.minData )
|
|
42
|
+
{
|
|
43
|
+
node.status( msg.payload );
|
|
44
|
+
send( msg );
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
{
|
|
48
|
+
node.status( "waiting for data" );
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
52
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('fallingEdge',{
|
|
3
|
+
category: 'function',
|
|
4
|
+
color: "#C0DEED",
|
|
5
|
+
defaults: {
|
|
6
|
+
name:{value:""},
|
|
7
|
+
property:{value:"payload",required:true},
|
|
8
|
+
threshold:{value:"",required:true,validate:RED.validators.number()},
|
|
9
|
+
showState:{value:false}
|
|
10
|
+
},
|
|
11
|
+
inputs:1,
|
|
12
|
+
outputs:1,
|
|
13
|
+
icon: "falling-edge.png",
|
|
14
|
+
label: function() {
|
|
15
|
+
return this.name||"falling";
|
|
16
|
+
},
|
|
17
|
+
paletteLabel: "falling edge",
|
|
18
|
+
inputLabels: 'input',
|
|
19
|
+
outputLabels: 'edge trigger',
|
|
20
|
+
oneditprepare: function() {
|
|
21
|
+
$("#node-input-property").typedInput({
|
|
22
|
+
type:"msg",
|
|
23
|
+
types:["msg"],
|
|
24
|
+
typeField: "#node-input-property-type"
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<script type="text/html" data-template-name="fallingEdge">
|
|
31
|
+
<div class="form-row">
|
|
32
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
33
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
34
|
+
</div>
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
37
|
+
<input type="text" id="node-input-property">
|
|
38
|
+
<input type="hidden" id="node-input-property-type">
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-threshold"><i class="fa fa-chevron-down"></i> Threshold</label>
|
|
42
|
+
<input type="text" id="node-input-threshold">
|
|
43
|
+
</div>
|
|
44
|
+
<div class="form-row">
|
|
45
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
46
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
47
|
+
</div>
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<script type="text/html" data-help-name="fallingEdge">
|
|
51
|
+
|
|
52
|
+
<p>Message is only forwarded, if the payload falls below a threshold value.</p>
|
|
53
|
+
<p>Each <code>topic</code> is treated seperatly.</p>
|
|
54
|
+
|
|
55
|
+
<h3>Input</h3>
|
|
56
|
+
|
|
57
|
+
<p>The message property to be used as payload can be defined with the <code>Property</code> property.</p>
|
|
58
|
+
|
|
59
|
+
<dl class="message-properties">
|
|
60
|
+
<dt>topic <span class="property-type">string</span></dt>
|
|
61
|
+
<dd> name of the input channel.</dd>
|
|
62
|
+
<dt>payload <span class="property-type"></span></dt>
|
|
63
|
+
<dd> input value for <code>topic</code>.</dd>
|
|
64
|
+
</dl>
|
|
65
|
+
|
|
66
|
+
<h3>Output</h3>
|
|
67
|
+
|
|
68
|
+
<p>Trigger message, in case a falling edge is detected.</p>
|
|
69
|
+
|
|
70
|
+
<h3>Parameter</h3>
|
|
71
|
+
|
|
72
|
+
<dl class="message-properties">
|
|
73
|
+
<dt>Property <span class="property-type">string</span></dt>
|
|
74
|
+
<dd> defines the message property to be used as payload.</dd>
|
|
75
|
+
<dt>Threshold <span class="property-type">number</span></dt>
|
|
76
|
+
<dd> threshold value for the edge detection.</dd>
|
|
77
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
78
|
+
<dd> shows the actual value as a node status.</dd>
|
|
79
|
+
</dl>
|
|
80
|
+
|
|
81
|
+
</script>
|
package/math_falling.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
|
|
3
|
+
function FallingEdgeNode(config) {
|
|
4
|
+
RED.nodes.createNode(this,config);
|
|
5
|
+
//this.config = config;
|
|
6
|
+
var node = this;
|
|
7
|
+
var context = this.context();
|
|
8
|
+
this.property = config.property ?? "payload";
|
|
9
|
+
this.threshold = config.threshold;
|
|
10
|
+
this.showState = config.showState;
|
|
11
|
+
|
|
12
|
+
node.on('input', function(msg,send,done) {
|
|
13
|
+
if( msg.reset || msg.topic==="init" )
|
|
14
|
+
{
|
|
15
|
+
context.set( "data", {} );
|
|
16
|
+
node.status( "" );
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
{
|
|
20
|
+
msg.payload = Number( RED.util.getMessageProperty( msg, node.property ) );
|
|
21
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
22
|
+
|
|
23
|
+
if( ! isNaN( msg.payload ) )
|
|
24
|
+
{
|
|
25
|
+
let data = context.get( "data" ) ?? {};
|
|
26
|
+
const last = data[msg.topic] ?? Number.MIN_SAFE_INTEGER;
|
|
27
|
+
if( msg.payload < this.threshold && this.threshold <= last )
|
|
28
|
+
{
|
|
29
|
+
status.fill = "green";
|
|
30
|
+
msg.edge = "falling";
|
|
31
|
+
send( msg );
|
|
32
|
+
}
|
|
33
|
+
data[msg.topic] = msg.payload;
|
|
34
|
+
context.set( "data", data );
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
{
|
|
38
|
+
status.fill = "red";
|
|
39
|
+
status.text = "not a Number";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if( node.showState )
|
|
43
|
+
{
|
|
44
|
+
node.status( status );
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
done();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
RED.nodes.registerType("fallingEdge",FallingEdgeNode);
|
|
52
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('hysteresisEdge',{
|
|
3
|
+
category: 'function',
|
|
4
|
+
color: "#C0DEED",
|
|
5
|
+
defaults: {
|
|
6
|
+
name:{value:""},
|
|
7
|
+
property:{value:"payload",required:true},
|
|
8
|
+
threshold_raise:{value:"",required:true,validate:RED.validators.number()},
|
|
9
|
+
threshold_fall:{value:"",required:true,validate:function(v){
|
|
10
|
+
const raise = $("#node-input-threshold_raise").length ? $("#node-input-threshold_raise").val() : this.threshold_raise;
|
|
11
|
+
return v!=='' && !isNaN(v) && Number(v)<raise;}
|
|
12
|
+
},
|
|
13
|
+
initial:{value:"none"},
|
|
14
|
+
showState:{value:false}
|
|
15
|
+
},
|
|
16
|
+
inputs:1,
|
|
17
|
+
outputs:1,
|
|
18
|
+
icon: "hysteresis.png",
|
|
19
|
+
label: function() {
|
|
20
|
+
return this.name||"hysteresis";
|
|
21
|
+
},
|
|
22
|
+
paletteLabel: "hysteresis",
|
|
23
|
+
inputLabels: 'input',
|
|
24
|
+
outputLabels: 'hysteresis trigger',
|
|
25
|
+
oneditprepare: function() {
|
|
26
|
+
$("#node-input-property").typedInput({
|
|
27
|
+
type:"msg",
|
|
28
|
+
types:["msg"],
|
|
29
|
+
typeField: "#node-input-property-type"
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<script type="text/html" data-template-name="hysteresisEdge">
|
|
36
|
+
<div class="form-row">
|
|
37
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
38
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
42
|
+
<input type="text" id="node-input-property">
|
|
43
|
+
<input type="hidden" id="node-input-property-type">
|
|
44
|
+
</div>
|
|
45
|
+
<div class="form-row">
|
|
46
|
+
<label for="node-input-threshold_raise"><i class="fa fa-chevron-up"></i> up threshold</label>
|
|
47
|
+
<input type="text" id="node-input-threshold_raise">
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<label for="node-input-threshold_fall"><i class="fa fa-chevron-down"></i> dn threshold</label>
|
|
51
|
+
<input type="text" id="node-input-threshold_fall">
|
|
52
|
+
</div>
|
|
53
|
+
<div class="form-row">
|
|
54
|
+
<label for="node-input-initial"><i class="fa fa-play"></i> 1st message</label>
|
|
55
|
+
<select id="node-input-initial">
|
|
56
|
+
<option value="none">None</option>
|
|
57
|
+
<option value="rising">Rising</option>
|
|
58
|
+
<option value="falling">Falling</option>
|
|
59
|
+
<option value="any">Any</option>
|
|
60
|
+
</select>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="form-row">
|
|
63
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
64
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
65
|
+
</div>
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<script type="text/html" data-help-name="hysteresisEdge">
|
|
69
|
+
|
|
70
|
+
<p>Message is only forwarded, if the payload raises above an upper limit or falls below a lower limit.</p>
|
|
71
|
+
<p>Each <code>topic</code> is treated seperatly.</p>
|
|
72
|
+
|
|
73
|
+
<h3>Input</h3>
|
|
74
|
+
|
|
75
|
+
<p>The message property to be used as payload can be defined with the <code>Property</code> property.</p>
|
|
76
|
+
|
|
77
|
+
<dl class="message-properties">
|
|
78
|
+
<dt>topic <span class="property-type">string</span></dt>
|
|
79
|
+
<dd> name of the input channel.</dd>
|
|
80
|
+
<dt>payload <span class="property-type"></span></dt>
|
|
81
|
+
<dd> input value for <code>topic</code>.</dd>
|
|
82
|
+
</dl>
|
|
83
|
+
|
|
84
|
+
<h3>Output</h3>
|
|
85
|
+
|
|
86
|
+
<p>Trigger message, in case an edge is detected.</p>
|
|
87
|
+
|
|
88
|
+
<h3>Parameter</h3>
|
|
89
|
+
|
|
90
|
+
<dl class="message-properties">
|
|
91
|
+
<dt>Property <span class="property-type">string</span></dt>
|
|
92
|
+
<dd> defines the message property to be used as payload.</dd>
|
|
93
|
+
<dt>up Threshold <span class="property-type">number</span></dt>
|
|
94
|
+
<dd> threshold value for the raising edge detection.</dd>
|
|
95
|
+
<dt>d(ow)n Threshold <span class="property-type">number</span></dt>
|
|
96
|
+
<dd> threshold value for the falling edge detection.</dd>
|
|
97
|
+
<dt>1st message <span class="property-type">string</span></dt>
|
|
98
|
+
<dd> initial behaviour (None, Rising, Falling, Any).</dd>
|
|
99
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
100
|
+
<dd> shows the actual value as a node status.</dd>
|
|
101
|
+
</dl>
|
|
102
|
+
|
|
103
|
+
</script>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
|
|
3
|
+
function HysteresisEdgeNode(config) {
|
|
4
|
+
RED.nodes.createNode(this,config);
|
|
5
|
+
//this.config = config;
|
|
6
|
+
var node = this;
|
|
7
|
+
var context = this.context();
|
|
8
|
+
this.property = config.property ?? "payload";
|
|
9
|
+
this.threshold_raise = config.threshold_raise;
|
|
10
|
+
this.threshold_fall = config.threshold_fall;
|
|
11
|
+
this.initial = config.initial;
|
|
12
|
+
this.showState = config.showState;
|
|
13
|
+
|
|
14
|
+
node.on('input', function(msg,send,done) {
|
|
15
|
+
|
|
16
|
+
if( msg.reset || msg.topic==="init" )
|
|
17
|
+
{
|
|
18
|
+
context.set( "data", {} );
|
|
19
|
+
node.status( "" );
|
|
20
|
+
}
|
|
21
|
+
else
|
|
22
|
+
{
|
|
23
|
+
msg.payload = Number( RED.util.getMessageProperty( msg, node.property ) );
|
|
24
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
25
|
+
|
|
26
|
+
if( ! isNaN( msg.payload ) )
|
|
27
|
+
{
|
|
28
|
+
let data = context.get( "data" ) ?? {};
|
|
29
|
+
const last = data[msg.topic];
|
|
30
|
+
|
|
31
|
+
function sendMsg(edge)
|
|
32
|
+
{
|
|
33
|
+
status.fill = "green";
|
|
34
|
+
data[msg.topic].edge = edge;
|
|
35
|
+
msg.edge = edge;
|
|
36
|
+
send( msg );
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if( last )
|
|
40
|
+
{
|
|
41
|
+
if( msg.payload > this.threshold_raise && this.threshold_raise >= last.value && last.edge != 'rising')
|
|
42
|
+
{
|
|
43
|
+
sendMsg( 'rising' );
|
|
44
|
+
}
|
|
45
|
+
else if( msg.payload < this.threshold_fall && this.threshold_fall <= last.value && last.edge != 'falling')
|
|
46
|
+
{
|
|
47
|
+
sendMsg( 'falling' );
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else
|
|
51
|
+
{
|
|
52
|
+
data[msg.topic] = {};
|
|
53
|
+
if( this.initial in ['any','rising'] && msg.payload > this.threshold_raise )
|
|
54
|
+
{
|
|
55
|
+
sendMsg( 'rising' );
|
|
56
|
+
}
|
|
57
|
+
else if( this.initial in ['any','falling'] && msg.payload < this.threshold_fall )
|
|
58
|
+
{
|
|
59
|
+
sendMsg( 'falling' );
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
data[msg.topic].value = msg.payload;
|
|
63
|
+
context.set( "data", data );
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
status.fill = "red";
|
|
68
|
+
status.text = "not a Number";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if( node.showState )
|
|
72
|
+
{
|
|
73
|
+
node.status( status );
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
done();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
RED.nodes.registerType("hysteresisEdge",HysteresisEdgeNode);
|
|
81
|
+
}
|
package/math_number.html
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
color: "#C0DEED",
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
|
-
property:{value:"payload",required:true}
|
|
7
|
+
property:{value:"payload",required:true},
|
|
8
|
+
showState:{value:false}
|
|
8
9
|
},
|
|
9
10
|
inputs:1,
|
|
10
11
|
outputs:1,
|
|
@@ -35,6 +36,10 @@
|
|
|
35
36
|
<input type="text" id="node-input-property">
|
|
36
37
|
<input type="hidden" id="node-input-property-type">
|
|
37
38
|
</div>
|
|
39
|
+
<div class="form-row">
|
|
40
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
41
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
42
|
+
</div>
|
|
38
43
|
</script>
|
|
39
44
|
|
|
40
45
|
<script type="text/html" data-help-name="tonumber">
|
|
@@ -62,6 +67,8 @@
|
|
|
62
67
|
<dl class="message-properties">
|
|
63
68
|
<dt>Property <span class="property-type">string</span></dt>
|
|
64
69
|
<dd> defines the message property to be used as payload.</dd>
|
|
70
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
71
|
+
<dd> shows the actual value as a node status.</dd>
|
|
65
72
|
</dl>
|
|
66
73
|
|
|
67
74
|
</script>
|
package/math_number.js
CHANGED
|
@@ -4,19 +4,26 @@ module.exports = function(RED) {
|
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
6
|
var node = this;
|
|
7
|
-
this.property = config.property
|
|
7
|
+
this.property = config.property ?? "payload";
|
|
8
|
+
this.showState = config.showState;
|
|
8
9
|
|
|
9
10
|
node.on('input', function(msg,send,done) {
|
|
10
11
|
msg.payload = Number( RED.util.getMessageProperty( msg, node.property ) );
|
|
11
12
|
|
|
12
13
|
if( ! isNaN( msg.payload ) )
|
|
13
14
|
{
|
|
14
|
-
|
|
15
|
+
if( node.showState )
|
|
16
|
+
{
|
|
17
|
+
node.status( msg.payload );
|
|
18
|
+
}
|
|
15
19
|
send( msg );
|
|
16
20
|
}
|
|
17
21
|
else
|
|
18
22
|
{
|
|
19
|
-
node.
|
|
23
|
+
if( node.showState )
|
|
24
|
+
{
|
|
25
|
+
node.status( "not a Number" );
|
|
26
|
+
}
|
|
20
27
|
}
|
|
21
28
|
done();
|
|
22
29
|
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('raisingEdge',{
|
|
3
|
+
category: 'function',
|
|
4
|
+
color: "#C0DEED",
|
|
5
|
+
defaults: {
|
|
6
|
+
name:{value:""},
|
|
7
|
+
property:{value:"payload",required:true},
|
|
8
|
+
threshold:{value:"",required:true,validate:RED.validators.number()},
|
|
9
|
+
showState:{value:false}
|
|
10
|
+
},
|
|
11
|
+
inputs:1,
|
|
12
|
+
outputs:1,
|
|
13
|
+
icon: "raising-edge.png",
|
|
14
|
+
label: function() {
|
|
15
|
+
return this.name||"raising";
|
|
16
|
+
},
|
|
17
|
+
paletteLabel: "raising edge",
|
|
18
|
+
inputLabels: 'input',
|
|
19
|
+
outputLabels: 'edge trigger',
|
|
20
|
+
oneditprepare: function() {
|
|
21
|
+
$("#node-input-property").typedInput({
|
|
22
|
+
type:"msg",
|
|
23
|
+
types:["msg"],
|
|
24
|
+
typeField: "#node-input-property-type"
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<script type="text/html" data-template-name="raisingEdge">
|
|
31
|
+
<div class="form-row">
|
|
32
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
33
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
34
|
+
</div>
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
37
|
+
<input type="text" id="node-input-property">
|
|
38
|
+
<input type="hidden" id="node-input-property-type">
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-threshold"><i class="fa fa-chevron-up"></i> Threshold</label>
|
|
42
|
+
<input type="text" id="node-input-threshold">
|
|
43
|
+
</div>
|
|
44
|
+
<div class="form-row">
|
|
45
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
46
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
47
|
+
</div>
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<script type="text/html" data-help-name="raisingEdge">
|
|
51
|
+
|
|
52
|
+
<p>Message is only forwarded, if the payload raises above a threshold value.</p>
|
|
53
|
+
<p>Each <code>topic</code> is treated seperatly.</p>
|
|
54
|
+
|
|
55
|
+
<h3>Input</h3>
|
|
56
|
+
|
|
57
|
+
<p>The message property to be used as payload can be defined with the <code>Property</code> property.</p>
|
|
58
|
+
|
|
59
|
+
<dl class="message-properties">
|
|
60
|
+
<dt>topic <span class="property-type">string</span></dt>
|
|
61
|
+
<dd> name of the input channel.</dd>
|
|
62
|
+
<dt>payload <span class="property-type"></span></dt>
|
|
63
|
+
<dd> input value for <code>topic</code>.</dd>
|
|
64
|
+
</dl>
|
|
65
|
+
|
|
66
|
+
<h3>Output</h3>
|
|
67
|
+
|
|
68
|
+
<p>Trigger message, in case a raising edge is detected.</p>
|
|
69
|
+
|
|
70
|
+
<h3>Parameter</h3>
|
|
71
|
+
|
|
72
|
+
<dl class="message-properties">
|
|
73
|
+
<dt>Property <span class="property-type">string</span></dt>
|
|
74
|
+
<dd> defines the message property to be used as payload.</dd>
|
|
75
|
+
<dt>Threshold <span class="property-type">number</span></dt>
|
|
76
|
+
<dd> threshold value for the edge detection.</dd>
|
|
77
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
78
|
+
<dd> shows the actual value as a node status.</dd>
|
|
79
|
+
</dl>
|
|
80
|
+
|
|
81
|
+
</script>
|
package/math_raising.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
|
|
3
|
+
function RaisingEdgeNode(config) {
|
|
4
|
+
RED.nodes.createNode(this,config);
|
|
5
|
+
//this.config = config;
|
|
6
|
+
var node = this;
|
|
7
|
+
var context = this.context();
|
|
8
|
+
this.property = config.property ?? "payload";
|
|
9
|
+
this.threshold = config.threshold;
|
|
10
|
+
this.showState = config.showState;
|
|
11
|
+
|
|
12
|
+
node.on('input', function(msg,send,done) {
|
|
13
|
+
if( msg.reset || msg.topic==="init" )
|
|
14
|
+
{
|
|
15
|
+
context.set( "data", {} );
|
|
16
|
+
node.status( "" );
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
{
|
|
20
|
+
msg.payload = Number( RED.util.getMessageProperty( msg, node.property ) );
|
|
21
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
22
|
+
|
|
23
|
+
if( ! isNaN( msg.payload ) )
|
|
24
|
+
{
|
|
25
|
+
let data = context.get( "data" ) ?? {};
|
|
26
|
+
const last = data[msg.topic] ?? Number.MAX_SAFE_INTEGER;
|
|
27
|
+
if( msg.payload > this.threshold && this.threshold >= last )
|
|
28
|
+
{
|
|
29
|
+
status.fill = "green";
|
|
30
|
+
msg.edge = "raising";
|
|
31
|
+
send( msg );
|
|
32
|
+
}
|
|
33
|
+
data[msg.topic] = msg.payload;
|
|
34
|
+
context.set( "data", data );
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
{
|
|
38
|
+
status.fill = "red";
|
|
39
|
+
status.text = "not a Number";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if( node.showState )
|
|
43
|
+
{
|
|
44
|
+
node.status( status );
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
done();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
RED.nodes.registerType("raisingEdge",RaisingEdgeNode);
|
|
52
|
+
}
|
package/math_reduce.html
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
types:["msg"],
|
|
43
43
|
typeField: "#node-input-property-type"
|
|
44
44
|
});
|
|
45
|
+
/*
|
|
45
46
|
$("#node-input-algo").typedInput({
|
|
46
47
|
types:[{
|
|
47
48
|
value:"algo",
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
{ value: "max", label: "Maximum" }
|
|
54
55
|
]
|
|
55
56
|
}]
|
|
56
|
-
})
|
|
57
|
+
})*/
|
|
57
58
|
}
|
|
58
59
|
});
|
|
59
60
|
</script>
|
|
@@ -86,7 +87,13 @@
|
|
|
86
87
|
</div>
|
|
87
88
|
<div class="form-row">
|
|
88
89
|
<label for="node-input-algo"><i class="fa fa-flask"></i> Algorithm</label>
|
|
89
|
-
<
|
|
90
|
+
<select type="text" id="node-input-algo">
|
|
91
|
+
<option value="add">Adition</option>
|
|
92
|
+
<option value="mean">Mean Value</option>
|
|
93
|
+
<option value="prod">Product</option>
|
|
94
|
+
<option value="min">Minimum</option>
|
|
95
|
+
<option value="max">Maximum</option>
|
|
96
|
+
</select>
|
|
90
97
|
</div>
|
|
91
98
|
</script>
|
|
92
99
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mschaeffler/node-red-logic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "nodes for simple mathematical operations.",
|
|
5
5
|
"license": "LGPL-2.1",
|
|
6
6
|
"homepage": "https://github.com/m-schaeffler/node-red-my-nodes/tree/main/node-red-logic",
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"tonumber":"math_number.js",
|
|
23
23
|
"or":"logic_or.js",
|
|
24
24
|
"and":"logic_and.js",
|
|
25
|
+
"fallingEdge":"math_falling.js",
|
|
26
|
+
"raisingEdge":"math_raising.js",
|
|
27
|
+
"hysteresisEdge":"math_hysteresis.js",
|
|
25
28
|
"reduce":"math_reduce.js"
|
|
26
29
|
}
|
|
27
30
|
},
|