@mschaeffler/node-red-logic 2.0.0 → 2.2.0
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/math_reduce.html +11 -3
- package/math_reduce.js +96 -56
- package/package.json +1 -1
package/math_reduce.html
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
name:{value:""},
|
|
7
7
|
topic:{value:""},
|
|
8
8
|
property:{value:"payload", required:true},
|
|
9
|
+
propertyType:{value:"msg"},
|
|
9
10
|
minMean:{value:"1", required:true, validate:function(v){
|
|
10
11
|
return v!=='' && !isNaN(v) && Number(v)>0;}
|
|
11
12
|
},
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
return v!=='' && !isNaN(v) && Number(v)>0;}
|
|
18
19
|
},
|
|
19
20
|
algo:{value:"", required:true},
|
|
21
|
+
showState:{value:false},
|
|
20
22
|
filter:{value:false}
|
|
21
23
|
},
|
|
22
24
|
inputs:1,
|
|
@@ -43,8 +45,8 @@
|
|
|
43
45
|
oneditprepare: function() {
|
|
44
46
|
$("#node-input-property").typedInput({
|
|
45
47
|
type:"msg",
|
|
46
|
-
types:["msg"],
|
|
47
|
-
typeField: "#node-input-
|
|
48
|
+
types:["msg","jsonata"],
|
|
49
|
+
typeField: "#node-input-propertyType"
|
|
48
50
|
});
|
|
49
51
|
}
|
|
50
52
|
});
|
|
@@ -62,7 +64,7 @@
|
|
|
62
64
|
<div class="form-row">
|
|
63
65
|
<label for="node-input-input"><i class="fa fa-ellipsis-h"></i> Eigenschaft</label>
|
|
64
66
|
<input type="text" id="node-input-property">
|
|
65
|
-
<input type="hidden" id="node-input-
|
|
67
|
+
<input type="hidden" id="node-input-propertyType">
|
|
66
68
|
</div>
|
|
67
69
|
<div class="form-row">
|
|
68
70
|
<label for="node-input-minMean"><i class="fa fa-hourglass-o"></i> min. Mean</label>
|
|
@@ -86,6 +88,10 @@
|
|
|
86
88
|
<option value="max">Maximum</option>
|
|
87
89
|
</select>
|
|
88
90
|
</div>
|
|
91
|
+
<div class="form-row">
|
|
92
|
+
<label for="node-input-showStatus"><i class="fa fa-star-o"></i> Status</label>
|
|
93
|
+
<input type="checkbox" id="node-input-showState" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
94
|
+
</div>
|
|
89
95
|
<div class="form-row">
|
|
90
96
|
<label for="node-input-filter"><i class="fa fa-filter"></i> Filter</label>
|
|
91
97
|
<input type="checkbox" id="node-input-filter" style="display:inline-block; width:20px; vertical-align:baseline;">
|
|
@@ -136,6 +142,8 @@
|
|
|
136
142
|
<dd> min. amount of topics to generate an output.</dd>
|
|
137
143
|
<dt>Algorithm <span class="property-type">string</span></dt>
|
|
138
144
|
<dd> algorithm to combine the values.</dd>
|
|
145
|
+
<dt>Status <span class="property-type">boolean</span></dt>
|
|
146
|
+
<dd> shows the actual value as a node status.</dd>
|
|
139
147
|
<dt>Filter <span class="property-type">boolean</span></dt>
|
|
140
148
|
<dd> block sending of unchanged <code>property</code>.</dd>
|
|
141
149
|
</dl>
|
package/math_reduce.js
CHANGED
|
@@ -7,12 +7,25 @@ module.exports = function(RED) {
|
|
|
7
7
|
var context = this.context();
|
|
8
8
|
this.topic = config.topic ?? "";
|
|
9
9
|
this.property = config.property || "payload";
|
|
10
|
+
this.propertyType = config.propertyType ?? "msg";
|
|
10
11
|
this.minMean = Number( config.minMean ?? 1 );
|
|
11
12
|
this.maxMean = Number( config.maxMean ?? 1 );
|
|
12
13
|
this.minData = Number( config.minData ?? 1 );
|
|
13
14
|
this.algo = config.algo;
|
|
15
|
+
this.showState= Boolean( config.showState );
|
|
14
16
|
this.filter = Boolean( config.filter );
|
|
15
17
|
this.last = null;
|
|
18
|
+
if( this.propertyType === "jsonata" )
|
|
19
|
+
{
|
|
20
|
+
try {
|
|
21
|
+
this.propertyPrepared = RED.util.prepareJSONataExpression( this.property, this );
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
node.error(RED._("debug.invalid-exp", {error: this.property}));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
node.status( "" );
|
|
16
29
|
|
|
17
30
|
node.on('input', function(msg,send,done) {
|
|
18
31
|
if( msg.invalid )
|
|
@@ -27,88 +40,115 @@ module.exports = function(RED) {
|
|
|
27
40
|
}
|
|
28
41
|
else
|
|
29
42
|
{
|
|
30
|
-
|
|
31
|
-
let status = { shape:"dot" };
|
|
32
|
-
if( ! isNaN( payload ) )
|
|
43
|
+
function getPayload(callback)
|
|
33
44
|
{
|
|
34
|
-
|
|
35
|
-
let item = data[msg.topic] ?? [];
|
|
36
|
-
item.push( payload )
|
|
37
|
-
data[msg.topic] = item;
|
|
38
|
-
|
|
39
|
-
msg.topic = node.topic;
|
|
40
|
-
msg.count = 0;
|
|
41
|
-
msg.data = data;
|
|
42
|
-
switch( node.algo )
|
|
43
|
-
{
|
|
44
|
-
case "add":
|
|
45
|
-
case "mean": msg.payload = 0; break;
|
|
46
|
-
case "prod": msg.payload = 1; break;
|
|
47
|
-
case "min": msg.payload = Number.MAX_SAFE_INTEGER; break;
|
|
48
|
-
case "max": msg.payload = Number.MIN_SAFE_INTEGER; break;
|
|
49
|
-
default: done( "invalid algo: "+node.algo ); return;
|
|
50
|
-
}
|
|
51
|
-
for( const key in data )
|
|
45
|
+
if( node.propertyPrepared )
|
|
52
46
|
{
|
|
53
|
-
|
|
47
|
+
RED.util.evaluateJSONataExpression( node.propertyPrepared, msg, function(err, value)
|
|
54
48
|
{
|
|
55
|
-
|
|
56
|
-
while( data[key].length > node.maxMean )
|
|
49
|
+
if( err )
|
|
57
50
|
{
|
|
58
|
-
|
|
51
|
+
done( RED._("debug.invalid-exp", {error: editExpression}) );
|
|
59
52
|
}
|
|
60
|
-
|
|
61
|
-
switch( node.algo )
|
|
53
|
+
else
|
|
62
54
|
{
|
|
63
|
-
|
|
64
|
-
case "mean": msg.payload += help; break;
|
|
65
|
-
case "prod": msg.payload *= help; break;
|
|
66
|
-
case "min": msg.payload = Math.min( msg.payload, help ); break;
|
|
67
|
-
case "max": msg.payload = Math.max( msg.payload, help ); break;
|
|
55
|
+
callback( value );
|
|
68
56
|
}
|
|
69
|
-
}
|
|
57
|
+
} );
|
|
70
58
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
59
|
+
else
|
|
60
|
+
{
|
|
61
|
+
callback( RED.util.getMessageProperty( msg, node.property ) );
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
getPayload( function(value)
|
|
65
|
+
{
|
|
66
|
+
const payload = Number( value );
|
|
67
|
+
let status = { shape:"dot" };
|
|
68
|
+
if( ! isNaN( payload ) )
|
|
74
69
|
{
|
|
70
|
+
let data = context.get( "data" ) ?? {};
|
|
71
|
+
let item = data[msg.topic] ?? [];
|
|
72
|
+
item.push( payload )
|
|
73
|
+
data[msg.topic] = item;
|
|
74
|
+
|
|
75
|
+
msg.topic = node.topic;
|
|
76
|
+
msg.count = 0;
|
|
77
|
+
msg.data = data;
|
|
75
78
|
switch( node.algo )
|
|
76
79
|
{
|
|
77
|
-
case "
|
|
80
|
+
case "add":
|
|
81
|
+
case "mean": msg.payload = 0; break;
|
|
82
|
+
case "prod": msg.payload = 1; break;
|
|
83
|
+
case "min": msg.payload = Number.MAX_SAFE_INTEGER; break;
|
|
84
|
+
case "max": msg.payload = Number.MIN_SAFE_INTEGER; break;
|
|
85
|
+
default: done( "invalid algo: "+node.algo ); return;
|
|
78
86
|
}
|
|
79
|
-
|
|
80
|
-
if( node.filter )
|
|
87
|
+
for( const key in data )
|
|
81
88
|
{
|
|
82
|
-
if(
|
|
89
|
+
if( data[key].length >= node.minMean )
|
|
83
90
|
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
msg.count++;
|
|
92
|
+
while( data[key].length > node.maxMean )
|
|
93
|
+
{
|
|
94
|
+
data[key].shift();
|
|
95
|
+
}
|
|
96
|
+
const help = data[key].reduce( (accumulator,value)=>accumulator+value ) / data[key].length;
|
|
97
|
+
switch( node.algo )
|
|
98
|
+
{
|
|
99
|
+
case "add":
|
|
100
|
+
case "mean": msg.payload += help; break;
|
|
101
|
+
case "prod": msg.payload *= help; break;
|
|
102
|
+
case "min": msg.payload = Math.min( msg.payload, help ); break;
|
|
103
|
+
case "max": msg.payload = Math.max( msg.payload, help ); break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
context.set( "data", data );
|
|
108
|
+
|
|
109
|
+
if( msg.count >= node.minData )
|
|
110
|
+
{
|
|
111
|
+
switch( node.algo )
|
|
112
|
+
{
|
|
113
|
+
case "mean": msg.payload /= msg.count; break;
|
|
114
|
+
}
|
|
115
|
+
status.text = msg.payload;
|
|
116
|
+
if( node.filter )
|
|
117
|
+
{
|
|
118
|
+
if( msg.payload !== node.last )
|
|
119
|
+
{
|
|
120
|
+
node.last = msg.payload;
|
|
121
|
+
status.fill = "green";
|
|
122
|
+
send( msg );
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
{
|
|
126
|
+
status.fill = "gray";
|
|
127
|
+
}
|
|
87
128
|
}
|
|
88
129
|
else
|
|
89
130
|
{
|
|
90
|
-
status.fill = "
|
|
131
|
+
status.fill = "green";
|
|
132
|
+
send( msg );
|
|
91
133
|
}
|
|
92
134
|
}
|
|
93
135
|
else
|
|
94
136
|
{
|
|
95
|
-
status.fill = "
|
|
96
|
-
|
|
137
|
+
status.fill = "gray";
|
|
138
|
+
status.text = "to less data";
|
|
97
139
|
}
|
|
98
140
|
}
|
|
99
141
|
else
|
|
100
142
|
{
|
|
101
|
-
status.fill = "
|
|
102
|
-
status.text = "
|
|
143
|
+
status.fill = "red";
|
|
144
|
+
status.text = "payload is NaN";
|
|
103
145
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
node.status( status );
|
|
111
|
-
done();
|
|
146
|
+
if( node.showState )
|
|
147
|
+
{
|
|
148
|
+
node.status( status );
|
|
149
|
+
}
|
|
150
|
+
done();
|
|
151
|
+
} );
|
|
112
152
|
}
|
|
113
153
|
});
|
|
114
154
|
}
|
package/package.json
CHANGED