@mschaeffler/node-red-logic 1.3.0 → 1.4.1
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/counter.js +1 -1
- package/logic_and.js +3 -4
- package/logic_bool.js +1 -1
- package/logic_not.js +1 -1
- package/logic_or.js +3 -4
- package/math_falling.html +4 -3
- package/math_falling.js +62 -27
- package/math_hysteresis.html +4 -3
- package/math_hysteresis.js +77 -42
- package/math_mean.html +4 -3
- package/math_mean.js +79 -44
- package/math_minus.html +4 -3
- package/math_minus.js +61 -26
- package/math_number.html +4 -3
- package/math_number.js +61 -26
- package/math_raising.html +4 -3
- package/math_raising.js +62 -27
- package/math_reduce.js +3 -3
- package/math_statistics.html +4 -3
- package/math_statistics.js +78 -43
- package/package.json +3 -3
package/counter.js
CHANGED
package/logic_and.js
CHANGED
|
@@ -16,12 +16,12 @@ module.exports = function(RED) {
|
|
|
16
16
|
if( msg.invalid )
|
|
17
17
|
{
|
|
18
18
|
done();
|
|
19
|
-
return null;
|
|
20
19
|
}
|
|
21
|
-
if( msg.reset || msg.topic==="init" )
|
|
20
|
+
else if( msg.reset || msg.topic==="init" )
|
|
22
21
|
{
|
|
23
22
|
context.set( "data", {} );
|
|
24
23
|
node.status( "" );
|
|
24
|
+
done();
|
|
25
25
|
}
|
|
26
26
|
else
|
|
27
27
|
{
|
|
@@ -73,9 +73,8 @@ module.exports = function(RED) {
|
|
|
73
73
|
node.status( "waiting for data" );
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
done();
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
-
done();
|
|
79
78
|
});
|
|
80
79
|
}
|
|
81
80
|
|
package/logic_bool.js
CHANGED
package/logic_not.js
CHANGED
package/logic_or.js
CHANGED
|
@@ -16,12 +16,12 @@ module.exports = function(RED) {
|
|
|
16
16
|
if( msg.invalid )
|
|
17
17
|
{
|
|
18
18
|
done();
|
|
19
|
-
return null;
|
|
20
19
|
}
|
|
21
|
-
if( msg.reset || msg.topic==="init" )
|
|
20
|
+
else if( msg.reset || msg.topic==="init" )
|
|
22
21
|
{
|
|
23
22
|
context.set( "data", {} );
|
|
24
23
|
node.status( "" );
|
|
24
|
+
done();
|
|
25
25
|
}
|
|
26
26
|
else
|
|
27
27
|
{
|
|
@@ -73,9 +73,8 @@ module.exports = function(RED) {
|
|
|
73
73
|
node.status( "waiting for data" );
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
done();
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
-
done();
|
|
79
78
|
});
|
|
80
79
|
}
|
|
81
80
|
|
package/math_falling.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload",required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
threshold:{value:"",required:true,validate:RED.validators.number()},
|
|
9
10
|
showState:{value:false}
|
|
10
11
|
},
|
|
@@ -23,8 +24,8 @@
|
|
|
23
24
|
oneditprepare: function() {
|
|
24
25
|
$("#node-input-property").typedInput({
|
|
25
26
|
type:"msg",
|
|
26
|
-
types:["msg"],
|
|
27
|
-
typeField: "#node-input-
|
|
27
|
+
types:["msg","jsonata"],
|
|
28
|
+
typeField: "#node-input-propertyType"
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
});
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
<div class="form-row">
|
|
39
40
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
40
41
|
<input type="text" id="node-input-property">
|
|
41
|
-
<input type="hidden" id="node-input-
|
|
42
|
+
<input type="hidden" id="node-input-propertyType">
|
|
42
43
|
</div>
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-threshold"><i class="fa fa-chevron-down"></i> Threshold</label>
|
package/math_falling.js
CHANGED
|
@@ -3,53 +3,88 @@ module.exports = function(RED) {
|
|
|
3
3
|
function FallingEdgeNode(config) {
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
|
-
var node
|
|
6
|
+
var node = this;
|
|
7
7
|
var context = this.context();
|
|
8
|
-
this.property
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
8
|
+
this.property = config.property ?? "payload";
|
|
9
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
10
|
+
this.threshold = config.threshold;
|
|
11
|
+
this.showState = config.showState;
|
|
12
|
+
if( this.propertyType === "jsonata" )
|
|
13
|
+
{
|
|
14
|
+
try {
|
|
15
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
node.on('input', function(msg,send,done) {
|
|
13
24
|
if( msg.invalid )
|
|
14
25
|
{
|
|
15
26
|
done();
|
|
16
|
-
return null;
|
|
17
27
|
}
|
|
18
|
-
if( msg.reset || msg.topic==="init" )
|
|
28
|
+
else if( msg.reset || msg.topic==="init" )
|
|
19
29
|
{
|
|
20
30
|
context.set( "data", {} );
|
|
21
31
|
node.status( "" );
|
|
32
|
+
done();
|
|
22
33
|
}
|
|
23
34
|
else
|
|
24
35
|
{
|
|
25
|
-
|
|
26
|
-
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
27
|
-
|
|
28
|
-
if( ! isNaN( msg.payload ) )
|
|
36
|
+
function getPayload(callback)
|
|
29
37
|
{
|
|
30
|
-
|
|
31
|
-
const last = data[msg.topic] ?? Number.MIN_SAFE_INTEGER;
|
|
32
|
-
if( msg.payload < this.threshold && this.threshold <= last )
|
|
38
|
+
if( node.propertyPrepared )
|
|
33
39
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
41
|
+
{
|
|
42
|
+
if( err )
|
|
43
|
+
{
|
|
44
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
{
|
|
48
|
+
callback( value );
|
|
49
|
+
}
|
|
50
|
+
} );
|
|
51
|
+
}
|
|
52
|
+
else
|
|
53
|
+
{
|
|
54
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
37
55
|
}
|
|
38
|
-
data[msg.topic] = msg.payload;
|
|
39
|
-
context.set( "data", data );
|
|
40
56
|
}
|
|
41
|
-
|
|
57
|
+
getPayload( function(value)
|
|
42
58
|
{
|
|
43
|
-
|
|
44
|
-
status
|
|
45
|
-
}
|
|
59
|
+
msg.payload = Number( value );
|
|
60
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
46
61
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
if( ! isNaN( msg.payload ) )
|
|
63
|
+
{
|
|
64
|
+
let data = context.get( "data" ) ?? {};
|
|
65
|
+
const last = data[msg.topic] ?? Number.MIN_SAFE_INTEGER;
|
|
66
|
+
if( msg.payload < this.threshold && this.threshold <= last )
|
|
67
|
+
{
|
|
68
|
+
status.fill = "green";
|
|
69
|
+
msg.edge = "falling";
|
|
70
|
+
send( msg );
|
|
71
|
+
}
|
|
72
|
+
data[msg.topic] = msg.payload;
|
|
73
|
+
context.set( "data", data );
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
{
|
|
77
|
+
status.fill = "red";
|
|
78
|
+
status.text = "not a Number";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if( node.showState )
|
|
82
|
+
{
|
|
83
|
+
node.status( status );
|
|
84
|
+
}
|
|
85
|
+
done();
|
|
86
|
+
} );
|
|
51
87
|
}
|
|
52
|
-
done();
|
|
53
88
|
});
|
|
54
89
|
}
|
|
55
90
|
|
package/math_hysteresis.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload",required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
threshold_raise:{value:"",required:true,validate:RED.validators.number()},
|
|
9
10
|
threshold_fall:{value:"",required:true,validate:function(v){
|
|
10
11
|
const raise = $("#node-input-threshold_raise").length ? $("#node-input-threshold_raise").val() : this.threshold_raise;
|
|
@@ -28,8 +29,8 @@
|
|
|
28
29
|
oneditprepare: function() {
|
|
29
30
|
$("#node-input-property").typedInput({
|
|
30
31
|
type:"msg",
|
|
31
|
-
types:["msg"],
|
|
32
|
-
typeField: "#node-input-
|
|
32
|
+
types:["msg","jsonata"],
|
|
33
|
+
typeField: "#node-input-propertyType"
|
|
33
34
|
})
|
|
34
35
|
}
|
|
35
36
|
});
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
45
46
|
<input type="text" id="node-input-property">
|
|
46
|
-
<input type="hidden" id="node-input-
|
|
47
|
+
<input type="hidden" id="node-input-propertyType">
|
|
47
48
|
</div>
|
|
48
49
|
<div class="form-row">
|
|
49
50
|
<label for="node-input-threshold_raise"><i class="fa fa-chevron-up"></i> up threshold</label>
|
package/math_hysteresis.js
CHANGED
|
@@ -3,81 +3,116 @@ module.exports = function(RED) {
|
|
|
3
3
|
function HysteresisEdgeNode(config) {
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
|
-
var node
|
|
6
|
+
var node = this;
|
|
7
7
|
var context = this.context();
|
|
8
8
|
this.property = config.property ?? "payload";
|
|
9
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
9
10
|
this.threshold_raise = config.threshold_raise;
|
|
10
11
|
this.threshold_fall = config.threshold_fall;
|
|
11
12
|
this.initial = config.initial;
|
|
12
13
|
this.showState = config.showState;
|
|
14
|
+
if( this.propertyType === "jsonata" )
|
|
15
|
+
{
|
|
16
|
+
try {
|
|
17
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
13
24
|
|
|
14
25
|
node.on('input', function(msg,send,done) {
|
|
15
26
|
if( msg.invalid )
|
|
16
27
|
{
|
|
17
28
|
done();
|
|
18
|
-
return null;
|
|
19
29
|
}
|
|
20
|
-
if( msg.reset || msg.topic==="init" )
|
|
30
|
+
else if( msg.reset || msg.topic==="init" )
|
|
21
31
|
{
|
|
22
32
|
context.set( "data", {} );
|
|
23
33
|
node.status( "" );
|
|
34
|
+
done();
|
|
24
35
|
}
|
|
25
36
|
else
|
|
26
37
|
{
|
|
27
|
-
|
|
28
|
-
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
29
|
-
|
|
30
|
-
if( ! isNaN( msg.payload ) )
|
|
38
|
+
function getPayload(callback)
|
|
31
39
|
{
|
|
32
|
-
|
|
33
|
-
const last = data[msg.topic];
|
|
34
|
-
|
|
35
|
-
function sendMsg(edge)
|
|
40
|
+
if( node.propertyPrepared )
|
|
36
41
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
43
|
+
{
|
|
44
|
+
if( err )
|
|
45
|
+
{
|
|
46
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
{
|
|
50
|
+
callback( value );
|
|
51
|
+
}
|
|
52
|
+
} );
|
|
41
53
|
}
|
|
54
|
+
else
|
|
55
|
+
{
|
|
56
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
getPayload( function(value)
|
|
60
|
+
{
|
|
61
|
+
msg.payload = Number( value );
|
|
62
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
42
63
|
|
|
43
|
-
if(
|
|
64
|
+
if( ! isNaN( msg.payload ) )
|
|
44
65
|
{
|
|
45
|
-
|
|
66
|
+
let data = context.get( "data" ) ?? {};
|
|
67
|
+
const last = data[msg.topic];
|
|
68
|
+
|
|
69
|
+
function sendMsg(edge)
|
|
70
|
+
{
|
|
71
|
+
status.fill = "green";
|
|
72
|
+
data[msg.topic].edge = edge;
|
|
73
|
+
msg.edge = edge;
|
|
74
|
+
send( msg );
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if( last )
|
|
46
78
|
{
|
|
47
|
-
|
|
79
|
+
if( msg.payload > this.threshold_raise && this.threshold_raise >= last.value && last.edge != 'rising')
|
|
80
|
+
{
|
|
81
|
+
sendMsg( 'rising' );
|
|
82
|
+
}
|
|
83
|
+
else if( msg.payload < this.threshold_fall && this.threshold_fall <= last.value && last.edge != 'falling')
|
|
84
|
+
{
|
|
85
|
+
sendMsg( 'falling' );
|
|
86
|
+
}
|
|
48
87
|
}
|
|
49
|
-
else
|
|
88
|
+
else
|
|
50
89
|
{
|
|
51
|
-
|
|
90
|
+
data[msg.topic] = {};
|
|
91
|
+
if( ['any','rising'].includes(this.initial) && msg.payload > this.threshold_raise )
|
|
92
|
+
{
|
|
93
|
+
sendMsg( 'rising' );
|
|
94
|
+
}
|
|
95
|
+
else if( ['any','falling'].includes(this.initial) && msg.payload < this.threshold_fall )
|
|
96
|
+
{
|
|
97
|
+
sendMsg( 'falling' );
|
|
98
|
+
}
|
|
52
99
|
}
|
|
100
|
+
data[msg.topic].value = msg.payload;
|
|
101
|
+
context.set( "data", data );
|
|
53
102
|
}
|
|
54
103
|
else
|
|
55
104
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
sendMsg( 'rising' );
|
|
60
|
-
}
|
|
61
|
-
else if( ['any','falling'].includes(this.initial) && msg.payload < this.threshold_fall )
|
|
62
|
-
{
|
|
63
|
-
sendMsg( 'falling' );
|
|
64
|
-
}
|
|
105
|
+
status.fill = "red";
|
|
106
|
+
status.text = "not a Number";
|
|
65
107
|
}
|
|
66
|
-
data[msg.topic].value = msg.payload;
|
|
67
|
-
context.set( "data", data );
|
|
68
|
-
}
|
|
69
|
-
else
|
|
70
|
-
{
|
|
71
|
-
status.fill = "red";
|
|
72
|
-
status.text = "not a Number";
|
|
73
|
-
}
|
|
74
108
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
109
|
+
if( node.showState )
|
|
110
|
+
{
|
|
111
|
+
node.status( status );
|
|
112
|
+
}
|
|
113
|
+
done();
|
|
114
|
+
} );
|
|
79
115
|
}
|
|
80
|
-
done();
|
|
81
116
|
});
|
|
82
117
|
}
|
|
83
118
|
|
package/math_mean.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload", required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
deltaTime:{value:"60", required:true, validate:function(v){
|
|
9
10
|
return v!=='' && !isNaN(v) && Number(v)>0;}
|
|
10
11
|
},
|
|
@@ -28,8 +29,8 @@
|
|
|
28
29
|
oneditprepare: function() {
|
|
29
30
|
$("#node-input-property").typedInput({
|
|
30
31
|
type:"msg",
|
|
31
|
-
types:["msg"],
|
|
32
|
-
typeField: "#node-input-
|
|
32
|
+
types:["msg","jsonata"],
|
|
33
|
+
typeField: "#node-input-propertyType"
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
});
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
45
46
|
<input type="text" id="node-input-property">
|
|
46
|
-
<input type="hidden" id="node-input-
|
|
47
|
+
<input type="hidden" id="node-input-propertyType">
|
|
47
48
|
</div>
|
|
48
49
|
<div class="form-row">
|
|
49
50
|
<label for="node-input-minMean"><i class="fa fa-hourglass-o"></i> Zeitspanne</label>
|
package/math_mean.js
CHANGED
|
@@ -5,81 +5,116 @@ module.exports = function(RED) {
|
|
|
5
5
|
//this.config = config;
|
|
6
6
|
var node = this;
|
|
7
7
|
var context = this.context();
|
|
8
|
-
this.property
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
8
|
+
this.property = config.property || "payload";
|
|
9
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
10
|
+
this.deltaTime = Number( config.deltaTime )*1000;
|
|
11
|
+
this.minData = Number( config.minData );
|
|
12
|
+
this.filter = Number( config.filter ?? 0 )*1000;
|
|
13
|
+
this.zeroIsZero = config.zeroIsZero ?? false;
|
|
14
|
+
if( this.propertyType === "jsonata" )
|
|
15
|
+
{
|
|
16
|
+
try {
|
|
17
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
13
24
|
|
|
14
25
|
node.on('input', function(msg,send,done) {
|
|
15
26
|
if( msg.invalid )
|
|
16
27
|
{
|
|
17
28
|
done();
|
|
18
|
-
return null;
|
|
19
29
|
}
|
|
20
|
-
if( msg.reset || msg.topic==="init" )
|
|
30
|
+
else if( msg.reset || msg.topic==="init" )
|
|
21
31
|
{
|
|
22
32
|
context.set( "data", {} );
|
|
23
33
|
context.set( "last", {} );
|
|
24
34
|
node.status( "" );
|
|
35
|
+
done();
|
|
25
36
|
}
|
|
26
37
|
else
|
|
27
38
|
{
|
|
28
|
-
const now
|
|
29
|
-
|
|
30
|
-
if( ! isNaN( payload ) )
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
function getPayload(callback)
|
|
31
41
|
{
|
|
32
|
-
|
|
33
|
-
let data = context.get( "data" ) ?? {};
|
|
34
|
-
let item = data[msg.topic] ?? [];
|
|
35
|
-
item.push( { time:now, value:payload } );
|
|
36
|
-
while( item[0].time < now - this.deltaTime )
|
|
37
|
-
{
|
|
38
|
-
item.shift();
|
|
39
|
-
}
|
|
40
|
-
data[msg.topic] = item;
|
|
41
|
-
context.set( "data", data );
|
|
42
|
-
|
|
43
|
-
function sendValue(value)
|
|
42
|
+
if( node.propertyPrepared )
|
|
44
43
|
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
45
|
+
{
|
|
46
|
+
if( err )
|
|
47
|
+
{
|
|
48
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
49
|
+
}
|
|
50
|
+
else
|
|
51
|
+
{
|
|
52
|
+
callback( value );
|
|
53
|
+
}
|
|
54
|
+
} );
|
|
50
55
|
}
|
|
51
|
-
|
|
52
|
-
if( this.zeroIsZero && payload === 0 )
|
|
56
|
+
else
|
|
53
57
|
{
|
|
54
|
-
|
|
58
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
55
59
|
}
|
|
56
|
-
|
|
60
|
+
}
|
|
61
|
+
getPayload( function(value)
|
|
62
|
+
{
|
|
63
|
+
msg.payload = Number( value );
|
|
64
|
+
if( ! isNaN( payload ) )
|
|
57
65
|
{
|
|
58
|
-
let
|
|
59
|
-
|
|
66
|
+
let last = context.get( "last" ) ?? {};
|
|
67
|
+
let data = context.get( "data" ) ?? {};
|
|
68
|
+
let item = data[msg.topic] ?? [];
|
|
69
|
+
item.push( { time:now, value:payload } );
|
|
70
|
+
while( item[0].time < now - this.deltaTime )
|
|
71
|
+
{
|
|
72
|
+
item.shift();
|
|
73
|
+
}
|
|
74
|
+
data[msg.topic] = item;
|
|
75
|
+
context.set( "data", data );
|
|
76
|
+
|
|
77
|
+
function sendValue(value)
|
|
78
|
+
{
|
|
79
|
+
msg.payload = value;
|
|
80
|
+
last[msg.topic] = now;
|
|
81
|
+
context.set( "last", last );
|
|
82
|
+
node.status({fill:"green",shape:"dot",text:`${item.length} / ${msg.payload.toPrecision(4)}`});
|
|
83
|
+
send( msg );
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if( this.zeroIsZero && payload === 0 )
|
|
60
87
|
{
|
|
61
|
-
|
|
88
|
+
sendValue( 0 );
|
|
62
89
|
}
|
|
63
|
-
if(
|
|
90
|
+
else if( item.length >= this.minData )
|
|
64
91
|
{
|
|
65
|
-
|
|
92
|
+
let sum = 0;
|
|
93
|
+
for( const value of item )
|
|
94
|
+
{
|
|
95
|
+
sum += value.value;
|
|
96
|
+
}
|
|
97
|
+
if( (last[msg.topic]??0)+this.filter < now )
|
|
98
|
+
{
|
|
99
|
+
sendValue( sum/item.length );
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
{
|
|
103
|
+
node.status({fill:"gray",shape:"dot",text:`${item.length} / ${msg.payload.toPrecision(4)}`});
|
|
104
|
+
}
|
|
66
105
|
}
|
|
67
106
|
else
|
|
68
107
|
{
|
|
69
|
-
node.status({fill:"gray",shape:"dot",text
|
|
108
|
+
node.status({fill:"gray",shape:"dot",text:"to less data"});
|
|
70
109
|
}
|
|
71
110
|
}
|
|
72
111
|
else
|
|
73
112
|
{
|
|
74
|
-
node.status({fill:"
|
|
113
|
+
node.status({fill:"red",shape:"dot",text:"payload is NaN"});
|
|
75
114
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
node.status({fill:"red",shape:"dot",text:"payload is NaN"});
|
|
80
|
-
}
|
|
115
|
+
done();
|
|
116
|
+
} );
|
|
81
117
|
}
|
|
82
|
-
done();
|
|
83
118
|
});
|
|
84
119
|
}
|
|
85
120
|
|
package/math_minus.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload",required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
showState:{value:false},
|
|
9
10
|
filter:{value:false}
|
|
10
11
|
},
|
|
@@ -23,8 +24,8 @@
|
|
|
23
24
|
oneditprepare: function() {
|
|
24
25
|
$("#node-input-property").typedInput({
|
|
25
26
|
type:"msg",
|
|
26
|
-
types:["msg"],
|
|
27
|
-
typeField: "#node-input-
|
|
27
|
+
types:["msg","jsonata"],
|
|
28
|
+
typeField: "#node-input-propertyType"
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
});
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
<div class="form-row">
|
|
39
40
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
40
41
|
<input type="text" id="node-input-property">
|
|
41
|
-
<input type="hidden" id="node-input-
|
|
42
|
+
<input type="hidden" id="node-input-propertyType">
|
|
42
43
|
</div>
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
package/math_minus.js
CHANGED
|
@@ -4,49 +4,84 @@ module.exports = function(RED) {
|
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
6
|
var node = this;
|
|
7
|
-
this.property
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
7
|
+
this.property = config.property ?? "payload";
|
|
8
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
9
|
+
this.showState = config.showState;
|
|
10
|
+
this.filter = Boolean( config.filter );
|
|
11
|
+
this.last = null;
|
|
12
|
+
if( this.propertyType === "jsonata" )
|
|
13
|
+
{
|
|
14
|
+
try {
|
|
15
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
node.on('input', function(msg,send,done) {
|
|
13
24
|
if( msg.invalid )
|
|
14
25
|
{
|
|
15
26
|
done();
|
|
16
|
-
return
|
|
27
|
+
return;
|
|
17
28
|
}
|
|
18
|
-
|
|
19
|
-
let status = { text:msg.payload };
|
|
20
|
-
if( ! isNaN( msg.payload ) )
|
|
29
|
+
function getPayload(callback)
|
|
21
30
|
{
|
|
22
|
-
if( node.
|
|
31
|
+
if( node.propertyPrepared )
|
|
23
32
|
{
|
|
24
|
-
|
|
25
|
-
if( msg.payload !== node.last )
|
|
33
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
26
34
|
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
if( err )
|
|
36
|
+
{
|
|
37
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
{
|
|
41
|
+
callback( value );
|
|
42
|
+
}
|
|
43
|
+
} );
|
|
44
|
+
}
|
|
45
|
+
else
|
|
46
|
+
{
|
|
47
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
getPayload( function(value)
|
|
51
|
+
{
|
|
52
|
+
msg.payload = Number( value );
|
|
53
|
+
let status = { text:msg.payload };
|
|
54
|
+
if( ! isNaN( msg.payload ) )
|
|
55
|
+
{
|
|
56
|
+
if( node.filter )
|
|
57
|
+
{
|
|
58
|
+
status.shape = "dot";
|
|
59
|
+
if( msg.payload !== node.last )
|
|
60
|
+
{
|
|
61
|
+
node.last = msg.payload;
|
|
62
|
+
status.fill = "green";
|
|
63
|
+
send( msg );
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
status.fill = "gray";
|
|
68
|
+
}
|
|
30
69
|
}
|
|
31
70
|
else
|
|
32
71
|
{
|
|
33
|
-
|
|
72
|
+
send( msg );
|
|
34
73
|
}
|
|
35
74
|
}
|
|
36
75
|
else
|
|
37
76
|
{
|
|
38
|
-
|
|
77
|
+
status.text = "not a Number";
|
|
39
78
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
node.status( status );
|
|
48
|
-
}
|
|
49
|
-
done();
|
|
79
|
+
if( node.showState )
|
|
80
|
+
{
|
|
81
|
+
node.status( status );
|
|
82
|
+
}
|
|
83
|
+
done();
|
|
84
|
+
} );
|
|
50
85
|
});
|
|
51
86
|
}
|
|
52
87
|
|
package/math_number.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload",required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
showState:{value:false},
|
|
9
10
|
filter:{value:false}
|
|
10
11
|
},
|
|
@@ -23,8 +24,8 @@
|
|
|
23
24
|
oneditprepare: function() {
|
|
24
25
|
$("#node-input-property").typedInput({
|
|
25
26
|
type:"msg",
|
|
26
|
-
types:["msg"],
|
|
27
|
-
typeField: "#node-input-
|
|
27
|
+
types:["msg","jsonata"],
|
|
28
|
+
typeField: "#node-input-propertyType"
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
});
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
<div class="form-row">
|
|
39
40
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
40
41
|
<input type="text" id="node-input-property">
|
|
41
|
-
<input type="hidden" id="node-input-
|
|
42
|
+
<input type="hidden" id="node-input-propertyType">
|
|
42
43
|
</div>
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
package/math_number.js
CHANGED
|
@@ -4,49 +4,84 @@ module.exports = function(RED) {
|
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
6
|
var node = this;
|
|
7
|
-
this.property
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
7
|
+
this.property = config.property ?? "payload";
|
|
8
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
9
|
+
this.showState = config.showState;
|
|
10
|
+
this.filter = Boolean( config.filter );
|
|
11
|
+
this.last = null;
|
|
12
|
+
if( this.propertyType === "jsonata" )
|
|
13
|
+
{
|
|
14
|
+
try {
|
|
15
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
node.on('input', function(msg,send,done) {
|
|
13
24
|
if( msg.invalid )
|
|
14
25
|
{
|
|
15
26
|
done();
|
|
16
|
-
return
|
|
27
|
+
return;
|
|
17
28
|
}
|
|
18
|
-
|
|
19
|
-
let status = { text:msg.payload };
|
|
20
|
-
if( ! isNaN( msg.payload ) )
|
|
29
|
+
function getPayload(callback)
|
|
21
30
|
{
|
|
22
|
-
if( node.
|
|
31
|
+
if( node.propertyPrepared )
|
|
23
32
|
{
|
|
24
|
-
|
|
25
|
-
if( msg.payload !== node.last )
|
|
33
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
26
34
|
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
if( err )
|
|
36
|
+
{
|
|
37
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
{
|
|
41
|
+
callback( value );
|
|
42
|
+
}
|
|
43
|
+
} );
|
|
44
|
+
}
|
|
45
|
+
else
|
|
46
|
+
{
|
|
47
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
getPayload( function(value)
|
|
51
|
+
{
|
|
52
|
+
msg.payload = Number( value );
|
|
53
|
+
let status = { text:msg.payload };
|
|
54
|
+
if( ! isNaN( msg.payload ) )
|
|
55
|
+
{
|
|
56
|
+
if( node.filter )
|
|
57
|
+
{
|
|
58
|
+
status.shape = "dot";
|
|
59
|
+
if( msg.payload !== node.last )
|
|
60
|
+
{
|
|
61
|
+
node.last = msg.payload;
|
|
62
|
+
status.fill = "green";
|
|
63
|
+
send( msg );
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
status.fill = "gray";
|
|
68
|
+
}
|
|
30
69
|
}
|
|
31
70
|
else
|
|
32
71
|
{
|
|
33
|
-
|
|
72
|
+
send( msg );
|
|
34
73
|
}
|
|
35
74
|
}
|
|
36
75
|
else
|
|
37
76
|
{
|
|
38
|
-
|
|
77
|
+
status.text = "not a Number";
|
|
39
78
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
node.status( status );
|
|
48
|
-
}
|
|
49
|
-
done();
|
|
79
|
+
if( node.showState )
|
|
80
|
+
{
|
|
81
|
+
node.status( status );
|
|
82
|
+
}
|
|
83
|
+
done();
|
|
84
|
+
} );
|
|
50
85
|
});
|
|
51
86
|
}
|
|
52
87
|
|
package/math_raising.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload",required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
threshold:{value:"",required:true,validate:RED.validators.number()},
|
|
9
10
|
showState:{value:false}
|
|
10
11
|
},
|
|
@@ -23,8 +24,8 @@
|
|
|
23
24
|
oneditprepare: function() {
|
|
24
25
|
$("#node-input-property").typedInput({
|
|
25
26
|
type:"msg",
|
|
26
|
-
types:["msg"],
|
|
27
|
-
typeField: "#node-input-
|
|
27
|
+
types:["msg","jsonata"],
|
|
28
|
+
typeField: "#node-input-propertyType"
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
});
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
<div class="form-row">
|
|
39
40
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
40
41
|
<input type="text" id="node-input-property">
|
|
41
|
-
<input type="hidden" id="node-input-
|
|
42
|
+
<input type="hidden" id="node-input-propertyType">
|
|
42
43
|
</div>
|
|
43
44
|
<div class="form-row">
|
|
44
45
|
<label for="node-input-threshold"><i class="fa fa-chevron-up"></i> Threshold</label>
|
package/math_raising.js
CHANGED
|
@@ -3,53 +3,88 @@ module.exports = function(RED) {
|
|
|
3
3
|
function RaisingEdgeNode(config) {
|
|
4
4
|
RED.nodes.createNode(this,config);
|
|
5
5
|
//this.config = config;
|
|
6
|
-
var node
|
|
6
|
+
var node = this;
|
|
7
7
|
var context = this.context();
|
|
8
|
-
this.property
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
8
|
+
this.property = config.property ?? "payload";
|
|
9
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
10
|
+
this.threshold = config.threshold;
|
|
11
|
+
this.showState = config.showState;
|
|
12
|
+
if( this.propertyType === "jsonata" )
|
|
13
|
+
{
|
|
14
|
+
try {
|
|
15
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
node.on('input', function(msg,send,done) {
|
|
13
24
|
if( msg.invalid )
|
|
14
25
|
{
|
|
15
26
|
done();
|
|
16
|
-
return null;
|
|
17
27
|
}
|
|
18
|
-
if( msg.reset || msg.topic==="init" )
|
|
28
|
+
else if( msg.reset || msg.topic==="init" )
|
|
19
29
|
{
|
|
20
30
|
context.set( "data", {} );
|
|
21
31
|
node.status( "" );
|
|
32
|
+
done();
|
|
22
33
|
}
|
|
23
34
|
else
|
|
24
35
|
{
|
|
25
|
-
|
|
26
|
-
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
27
|
-
|
|
28
|
-
if( ! isNaN( msg.payload ) )
|
|
36
|
+
function getPayload(callback)
|
|
29
37
|
{
|
|
30
|
-
|
|
31
|
-
const last = data[msg.topic] ?? Number.MAX_SAFE_INTEGER;
|
|
32
|
-
if( msg.payload > this.threshold && this.threshold >= last )
|
|
38
|
+
if( node.propertyPrepared )
|
|
33
39
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
41
|
+
{
|
|
42
|
+
if( err )
|
|
43
|
+
{
|
|
44
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
{
|
|
48
|
+
callback( value );
|
|
49
|
+
}
|
|
50
|
+
} );
|
|
51
|
+
}
|
|
52
|
+
else
|
|
53
|
+
{
|
|
54
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
37
55
|
}
|
|
38
|
-
data[msg.topic] = msg.payload;
|
|
39
|
-
context.set( "data", data );
|
|
40
56
|
}
|
|
41
|
-
|
|
57
|
+
getPayload( function(value)
|
|
42
58
|
{
|
|
43
|
-
|
|
44
|
-
status
|
|
45
|
-
}
|
|
59
|
+
msg.payload = Number( value );
|
|
60
|
+
let status = { fill:"gray", shape:"dot", text:msg.payload };
|
|
46
61
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
if( ! isNaN( msg.payload ) )
|
|
63
|
+
{
|
|
64
|
+
let data = context.get( "data" ) ?? {};
|
|
65
|
+
const last = data[msg.topic] ?? Number.MAX_SAFE_INTEGER;
|
|
66
|
+
if( msg.payload > this.threshold && this.threshold >= last )
|
|
67
|
+
{
|
|
68
|
+
status.fill = "green";
|
|
69
|
+
msg.edge = "raising";
|
|
70
|
+
send( msg );
|
|
71
|
+
}
|
|
72
|
+
data[msg.topic] = msg.payload;
|
|
73
|
+
context.set( "data", data );
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
{
|
|
77
|
+
status.fill = "red";
|
|
78
|
+
status.text = "not a Number";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if( node.showState )
|
|
82
|
+
{
|
|
83
|
+
node.status( status );
|
|
84
|
+
}
|
|
85
|
+
done();
|
|
86
|
+
} );
|
|
51
87
|
}
|
|
52
|
-
done();
|
|
53
88
|
});
|
|
54
89
|
}
|
|
55
90
|
|
package/math_reduce.js
CHANGED
|
@@ -18,12 +18,12 @@ module.exports = function(RED) {
|
|
|
18
18
|
if( msg.invalid )
|
|
19
19
|
{
|
|
20
20
|
done();
|
|
21
|
-
return null;
|
|
22
21
|
}
|
|
23
|
-
if( msg.reset || msg.topic==="init" )
|
|
22
|
+
else if( msg.reset || msg.topic==="init" )
|
|
24
23
|
{
|
|
25
24
|
context.set( "data", {} );
|
|
26
25
|
node.status( "" );
|
|
26
|
+
done();
|
|
27
27
|
}
|
|
28
28
|
else
|
|
29
29
|
{
|
|
@@ -108,8 +108,8 @@ module.exports = function(RED) {
|
|
|
108
108
|
status.text = "payload is NaN";
|
|
109
109
|
}
|
|
110
110
|
node.status( status );
|
|
111
|
+
done();
|
|
111
112
|
}
|
|
112
|
-
done();
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
|
package/math_statistics.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name:{value:""},
|
|
7
7
|
property:{value:"payload", required:true},
|
|
8
|
+
propertyType:{value:"msg"},
|
|
8
9
|
deltaTime:{value:"60", required:true, validate:function(v){
|
|
9
10
|
return v!=='' && !isNaN(v) && Number(v)>0;}
|
|
10
11
|
},
|
|
@@ -26,8 +27,8 @@
|
|
|
26
27
|
oneditprepare: function() {
|
|
27
28
|
$("#node-input-property").typedInput({
|
|
28
29
|
type:"msg",
|
|
29
|
-
types:["msg"],
|
|
30
|
-
typeField: "#node-input-
|
|
30
|
+
types:["msg","jsonata"],
|
|
31
|
+
typeField: "#node-input-propertyType"
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
});
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
<div class="form-row">
|
|
42
43
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
43
44
|
<input type="text" id="node-input-property">
|
|
44
|
-
<input type="hidden" id="node-input-
|
|
45
|
+
<input type="hidden" id="node-input-propertyType">
|
|
45
46
|
</div>
|
|
46
47
|
<div class="form-row">
|
|
47
48
|
<label for="node-input-minMean"><i class="fa fa-hourglass-o"></i> Zeitspanne</label>
|
package/math_statistics.js
CHANGED
|
@@ -5,78 +5,113 @@ module.exports = function(RED) {
|
|
|
5
5
|
//this.config = config;
|
|
6
6
|
var node = this;
|
|
7
7
|
var context = this.context();
|
|
8
|
-
this.property
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
8
|
+
this.property = config.property || "payload";
|
|
9
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
10
|
+
this.deltaTime = Number( config.deltaTime )*1000;
|
|
11
|
+
this.minData = Number( config.minData );
|
|
12
|
+
if( this.propertyType === "jsonata" )
|
|
13
|
+
{
|
|
14
|
+
try {
|
|
15
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
node.on('input', function(msg,send,done) {
|
|
13
24
|
if( msg.invalid )
|
|
14
25
|
{
|
|
15
26
|
done();
|
|
16
|
-
return null;
|
|
17
27
|
}
|
|
18
|
-
if( msg.reset || msg.topic==="init" )
|
|
28
|
+
else if( msg.reset || msg.topic==="init" )
|
|
19
29
|
{
|
|
20
30
|
context.set( "data", {} );
|
|
21
31
|
node.status( "" );
|
|
32
|
+
done();
|
|
22
33
|
}
|
|
23
34
|
else
|
|
24
35
|
{
|
|
25
|
-
const now
|
|
26
|
-
|
|
27
|
-
if( ! isNaN( payload ) )
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
function getPayload(callback)
|
|
28
38
|
{
|
|
29
|
-
|
|
30
|
-
let item = data[msg.topic] ?? [];
|
|
31
|
-
item.push( { time:now, value:payload } );
|
|
32
|
-
while( item[0].time < now - this.deltaTime )
|
|
39
|
+
if( node.propertyPrepared )
|
|
33
40
|
{
|
|
34
|
-
|
|
41
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
42
|
+
{
|
|
43
|
+
if( err )
|
|
44
|
+
{
|
|
45
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
{
|
|
49
|
+
callback( value );
|
|
50
|
+
}
|
|
51
|
+
} );
|
|
35
52
|
}
|
|
36
|
-
|
|
37
|
-
context.set( "data", data );
|
|
38
|
-
|
|
39
|
-
if( item.length >= this.minData )
|
|
53
|
+
else
|
|
40
54
|
{
|
|
41
|
-
msg.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
getPayload( function(value)
|
|
59
|
+
{
|
|
60
|
+
msg.payload = Number( value );
|
|
61
|
+
if( ! isNaN( payload ) )
|
|
62
|
+
{
|
|
63
|
+
let data = context.get( "data" ) ?? {};
|
|
64
|
+
let item = data[msg.topic] ?? [];
|
|
65
|
+
item.push( { time:now, value:payload } );
|
|
66
|
+
while( item[0].time < now - this.deltaTime )
|
|
67
|
+
{
|
|
68
|
+
item.shift();
|
|
69
|
+
}
|
|
70
|
+
data[msg.topic] = item;
|
|
71
|
+
context.set( "data", data );
|
|
72
|
+
|
|
73
|
+
if( item.length >= this.minData )
|
|
47
74
|
{
|
|
48
|
-
|
|
49
|
-
|
|
75
|
+
msg.stat = {
|
|
76
|
+
count: item.length,
|
|
77
|
+
min: Number.MAX_SAFE_INTEGER,
|
|
78
|
+
max: Number.MIN_SAFE_INTEGER };
|
|
79
|
+
let sum = 0;
|
|
80
|
+
for( const value of item )
|
|
50
81
|
{
|
|
51
|
-
|
|
82
|
+
sum += value.value;
|
|
83
|
+
if( value.value < msg.stat.min )
|
|
84
|
+
{
|
|
85
|
+
msg.stat.min = value.value;
|
|
86
|
+
}
|
|
87
|
+
if( value.value > msg.stat.max )
|
|
88
|
+
{
|
|
89
|
+
msg.stat.max = value.value;
|
|
90
|
+
}
|
|
52
91
|
}
|
|
53
|
-
|
|
92
|
+
msg.stat.average = sum/msg.stat.count;
|
|
93
|
+
let varianz = 0;
|
|
94
|
+
for( const value of item )
|
|
54
95
|
{
|
|
55
|
-
msg.stat.
|
|
96
|
+
varianz += ( value.value - msg.stat.average ) ** 2;
|
|
56
97
|
}
|
|
98
|
+
msg.stat.deviation = Math.sqrt( varianz / msg.stat.count );
|
|
99
|
+
msg.stat.variation = msg.stat.deviation / msg.stat.average;
|
|
100
|
+
node.status({fill:"green",shape:"dot",text:`${msg.stat.count} / ${msg.stat.deviation.toPrecision(4)}`});
|
|
101
|
+
send( msg );
|
|
57
102
|
}
|
|
58
|
-
|
|
59
|
-
let varianz = 0;
|
|
60
|
-
for( const value of item )
|
|
103
|
+
else
|
|
61
104
|
{
|
|
62
|
-
|
|
105
|
+
node.status({fill:"gray",shape:"dot",text:"to less data"});
|
|
63
106
|
}
|
|
64
|
-
msg.stat.deviation = Math.sqrt( varianz / msg.stat.count );
|
|
65
|
-
msg.stat.variation = msg.stat.deviation / msg.stat.average;
|
|
66
|
-
node.status({fill:"green",shape:"dot",text:`${msg.stat.count} / ${msg.stat.deviation.toPrecision(4)}`});
|
|
67
|
-
send( msg );
|
|
68
107
|
}
|
|
69
108
|
else
|
|
70
109
|
{
|
|
71
|
-
node.status({fill:"
|
|
110
|
+
node.status({fill:"red",shape:"dot",text:"payload is NaN"});
|
|
72
111
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
{
|
|
76
|
-
node.status({fill:"red",shape:"dot",text:"payload is NaN"});
|
|
77
|
-
}
|
|
112
|
+
done();
|
|
113
|
+
} );
|
|
78
114
|
}
|
|
79
|
-
done();
|
|
80
115
|
});
|
|
81
116
|
}
|
|
82
117
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mschaeffler/node-red-logic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "nodes for simple operations.",
|
|
5
5
|
"license": "LGPL-2.1",
|
|
6
6
|
"homepage": "https://github.com/m-schaeffler/node-red-my-nodes/tree/main/node-red-logic",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"url": "git+https://github.com/m-schaeffler/node-red-my-nodes.git"
|
|
10
10
|
},
|
|
11
11
|
"engines": {
|
|
12
|
-
"node": ">=
|
|
12
|
+
"node": ">=18"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"node-red"
|
|
16
16
|
],
|
|
17
17
|
"node-red": {
|
|
18
|
-
"version": ">=3.
|
|
18
|
+
"version": ">=3.1.0",
|
|
19
19
|
"nodes": {
|
|
20
20
|
"counter":"counter.js",
|
|
21
21
|
"tobool":"logic_bool.js",
|