node-red-contrib-prib-functions 0.19.2 → 0.21.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/.github/workflows/codeql-analysis.yml +3 -3
- package/.github/workflows/npmpublish.yml +6 -6
- package/.vs/VSWorkspaceState.json +7 -0
- package/.vs/node-red-contrib-prib-functions/v17/.wsuo +0 -0
- package/README.md +84 -70
- package/dataAnalysis/arrayAllRowsSwap.js +15 -0
- package/dataAnalysis/arrayCompareToPrecision.js +34 -0
- package/dataAnalysis/arrayDifference.js +14 -0
- package/dataAnalysis/arrayDifferenceSeasonal.js +15 -0
- package/dataAnalysis/arrayDifferenceSeasonalSecondOrder.js +20 -0
- package/dataAnalysis/arrayDifferenceSecondOrder.js +14 -0
- package/dataAnalysis/arrayForEachRange.js +38 -0
- package/dataAnalysis/arrayOverlay.js +13 -0
- package/dataAnalysis/arrayProduct.js +11 -0
- package/dataAnalysis/arrayRandom.js +14 -0
- package/dataAnalysis/arrayReduceRange.js +11 -0
- package/dataAnalysis/arrayScale.js +11 -0
- package/dataAnalysis/arraySum.js +11 -0
- package/dataAnalysis/arraySumSquared.js +11 -0
- package/dataAnalysis/arraySwap.js +11 -0
- package/dataAnalysis/dataAnalysis.html +52 -21
- package/dataAnalysis/dataAnalysis.js +73 -44
- package/dataAnalysis/generateMatrixFunction.js +89 -0
- package/dataAnalysis/generateVectorFunction.js +25 -0
- package/dataAnalysis/pca.js +472 -325
- package/dataAnalysis/svd.js +239 -0
- package/documentation/DataAnalysisRealtime.JPG +0 -0
- package/documentation/monitorSystem.JPG +0 -0
- package/documentation/monitorSystemTest.JPG +0 -0
- package/echart/echart.html +68 -0
- package/echart/echart.js +85 -0
- package/echart/icons/chart-671.png +0 -0
- package/echart/lib/echarts.js +95886 -0
- package/lib/Chart.js +177 -0
- package/lib/Column.js +99 -0
- package/lib/GraphDB.js +14 -0
- package/lib/Table.js +185 -0
- package/lib/objectExtensions.js +361 -0
- package/matrix/matrix.js +95 -56
- package/matrix/matrixNode.html +88 -55
- package/matrix/matrixNode.js +12 -5
- package/monitor/BarGauge.js +8 -0
- package/monitor/Dataset.js +29 -0
- package/monitor/DialGauge.js +109 -0
- package/monitor/DialNeedle.js +36 -0
- package/monitor/Format.js +74 -0
- package/monitor/centerElement.js +14 -0
- package/monitor/compareElements.js +95 -0
- package/monitor/defs.js +23 -0
- package/monitor/extensions.js +906 -0
- package/monitor/functions.js +36 -0
- package/monitor/json2xml.js +103 -0
- package/monitor/monitorSystem.html +199 -0
- package/monitor/monitorSystem.js +322 -0
- package/monitor/svgHTML.js +179 -0
- package/monitor/svgObjects.js +64 -0
- package/package.json +20 -6
- package/test/00-objectExtensions.js +94 -0
- package/test/04-tables.js +33 -0
- package/test/data/.config.nodes.json +608 -0
- package/test/data/.config.nodes.json.backup +608 -0
- package/test/data/.config.runtime.json +4 -0
- package/test/data/.config.runtime.json.backup +3 -0
- package/test/data/.config.users.json +21 -0
- package/test/data/.config.users.json.backup +21 -0
- package/test/data/.flow.json.backup +2820 -2003
- package/test/data/float32vector10.npy +0 -0
- package/test/data/flow.json +2830 -2033
- package/test/data/int2matrix2x3.npy +0 -0
- package/test/data/package-lock.json +158 -0
- package/test/data/package.json +11 -0
- package/test/dataAnalysisExtensions.js +471 -0
- package/test/dataAnalysisPCA.js +54 -0
- package/test/dataAnalysisSVD.js +31 -0
- package/test/euclideanDistance.js +2 -2
- package/test/transformConfluence.js +1 -1
- package/test/transformNumPy.js +132 -0
- package/testing/test.html +1 -1
- package/testing/test.js +78 -53
- package/transform/NumPy.js +303 -0
- package/transform/transform.html +12 -0
- package/transform/transform.js +34 -2
package/matrix/matrixNode.html
CHANGED
|
@@ -7,18 +7,20 @@
|
|
|
7
7
|
name: {value:null},
|
|
8
8
|
action: {value: "create",required:true},
|
|
9
9
|
args: {value:[]},
|
|
10
|
-
arg: {value:null},"arg-type": {value:"msg"},
|
|
11
10
|
call:{value:null},
|
|
12
|
-
column: {value:
|
|
13
|
-
columns: {value:
|
|
11
|
+
column: {value:2},"column-type": {value:"num"},
|
|
12
|
+
columns: {value:2},"columns-type": {value:"num"},
|
|
13
|
+
dataType: {value:"Float32Array"},"columns-type": {value:"Float32Array"},
|
|
14
14
|
end: {value:null},"end-type": {value:"num"},
|
|
15
15
|
factor: {value:null},"factor-type": {value:"num"},
|
|
16
|
+
initialState:{value:"setZero"},
|
|
16
17
|
matrix: {value:"payload"},"matrix-type": {value:"msg"},
|
|
17
18
|
precision: {value:3},"precision-type": {value:"num"},
|
|
18
19
|
row: {value:3},"row-type": {value:"num"},
|
|
19
20
|
rows: {value:3},"rows-type": {value:"num"},
|
|
20
21
|
rowTarget: {value:null},"rowTarget-type": {value:"num"},
|
|
21
22
|
source: {value:"_matrix"},"source-type": {value:"msg"},
|
|
23
|
+
sourceArray: {value:"payload"},"sourceArray-type": {value:"msg,json,flow,global"},
|
|
22
24
|
start: {value:null},"start-type": {value:"num"},
|
|
23
25
|
target: {value:"_matrix"},"target-type": {value:"msg"},
|
|
24
26
|
value: {value:"payload"},"value-type": {value:"msg"},
|
|
@@ -35,70 +37,70 @@
|
|
|
35
37
|
return this.name || ("Matrix "+this.action||"*** new ***");
|
|
36
38
|
},
|
|
37
39
|
oneditprepare: function() {
|
|
40
|
+
console.log("+++")
|
|
38
41
|
const node=this;
|
|
39
42
|
node.properties=[];
|
|
40
43
|
node.editors=[];
|
|
41
44
|
const actions={
|
|
42
|
-
define:{label:"Define",show:["target"],args:["rows","columns"]},
|
|
43
|
-
defineEmpty:{label:"Define Empty",show:["target"],args:["rows","columns"]},
|
|
44
|
-
create:{label:"Create",show:["target"],args:[]},
|
|
45
|
-
createLike:{label:"Create Like",show:["source","target"],args:[]},
|
|
46
|
-
clone:{label:"Clone",show:["source","target"],args:[]},
|
|
47
45
|
add:{label:"Add",show:["source"],args:["matrix"]},
|
|
48
46
|
addRow:{label:"Add Row",show:["source"],args:["row","vector"]},
|
|
49
47
|
addRow2Row:{label:"Add Row to Row",show:["source"],args:["row","target","factor","start","end"]},
|
|
50
48
|
addCell:{label:"Add to Cell",show:["source"],args:["row","column","value"]},
|
|
51
|
-
subtractCell:{label:"Subtract Cell",show:["source","target"],args:["row","column","value"]},
|
|
52
|
-
multiple:{label:"Multiple",show:["source","target"],args:[]},
|
|
53
|
-
multipleCell:{label:"Multiple Cell",show:["source","target"],args:["rows","columns","value"]},
|
|
54
|
-
divideCell:{label:"Divide Cell",show:["source"],args:["rows","columns","value"]},
|
|
55
|
-
divideRow:{label:"Divide Row",show:["source"],args:["row","factor","start","end"]},
|
|
56
|
-
transpose:{label:"Transpose",show:["source","target"],args:[]},
|
|
57
|
-
getAdjoint:{label:"Adjoint",show:["source","target"],args:[]},
|
|
58
|
-
getCofactor:{label:"Cofactor",show:["source","target"],args:[]},
|
|
59
|
-
getComplementMinor:{label:"Complement Minor",show:["source","target"],args:[]},
|
|
60
|
-
getIdentity:{label:"Identity",show:["source","target"],args:[]},
|
|
61
|
-
getInverse:{label:"Inverse",show:["source","target"],args:[]},
|
|
62
|
-
getInverseAdjointMethod:{label:"Inverse (Adjoint Method)",show:["source","target"],args:[]},
|
|
63
|
-
getInverseGaussJordan:{label:"Inverse (Gauss Jordan Method)",show:["source","target"],args:[]},
|
|
64
|
-
norm:{label:"Norm",show:["source","target"],args:[]},
|
|
65
|
-
getDeterminant:{label:"Determinant",show:["source","target"],args:[]},
|
|
66
|
-
getDeterminantUsingCofactor:{label:"Determinant (Cofactor)",show:["source","target"],args:[]},
|
|
67
|
-
getDeterminantUsingCofactor:{label:"Determinant (Row Echelon Form)",show:["source","target"],args:[]},
|
|
68
49
|
backwardSubstitution:{label:"Backward Substitution",show:["source"],args:[]},
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
rowEchelonForm:{label:"Row Echelon Form",show:["source"],args:[]},
|
|
73
|
-
equalsNearly:{label:"Nearly Equals",show:["source"],args:[]},
|
|
74
|
-
testIsSquare:{label:"Is Square",show:["source"],args:[]},
|
|
75
|
-
get:{label:"Get Cell",show:["source","target"],args:[]},
|
|
76
|
-
sumRow:{label:"Sum Row",show:["source","target"],args:[]},
|
|
77
|
-
swapRows:{label:"Swap Rows",show:["source"],args:[]},
|
|
78
|
-
toArray:{label:"To Array Object",show:["source","target"],args:[]},
|
|
79
|
-
runningSum:{label:"Running Sum",show:["source","target"],args:[]},
|
|
80
|
-
getVandermonde:{label:"Vandermonde",show:["target"],args:["vector","columns"]},
|
|
81
|
-
create:{label:"Create",show:[,"target"],args:["rows","columns"]},
|
|
50
|
+
create:{label:"Create", show:["target"],args:["initialState","rows","columns","dataType"]},
|
|
51
|
+
createLike:{label:"Create Like",show:["source","target"],args:[]},
|
|
52
|
+
clone:{label:"Clone",show:["source","target"],args:[]},
|
|
82
53
|
createForEachCellPairSet:{label:"Create Pair Set Cells",show:["source","target"],args:["matrix","call"],default:{call:"(baseCellValue,matrixCellValue)=>{}"}},
|
|
54
|
+
define:{label:"Define",show:["target"],args:["rows","columns","dataType"]},
|
|
55
|
+
defineEmpty:{label:"Define Empty",show:["target"],args:["rows","columns","dataType"]},
|
|
56
|
+
divideCell:{label:"Divide Cell",show:["source"],args:["rows","columns","value"]},
|
|
57
|
+
divideRow:{label:"Divide Row",show:["source"],args:["row","factor","start","end"]},
|
|
58
|
+
equalsNearly:{label:"Nearly Equals",show:["source"],args:[]},
|
|
59
|
+
fillArray:{label:"Fill",show:["source"],args:["matrix"]},
|
|
60
|
+
findColumnRow:{label:"Find in Column",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
|
|
83
61
|
findRowColumn:{label:"Find in Row",show:["source"],args:["row","call","start","end"],default:{call:"(value,row,column,offset,vector)=>true"}},
|
|
84
62
|
forRowCells:{label:"Row Cells",show:["source"],args:["row","call","start","end"],default:{call:"()=>{}"}},
|
|
85
|
-
fillArray:{label:"fill",show:["source"],args:["matrix"]},
|
|
86
|
-
findColumnRow:{label:"Find in Column",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
|
|
87
63
|
forColumnCells:{label:"Column Cells",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
|
|
88
64
|
forEachCell:{label:"For Each Cell",show:["source"],args:["call"],default:{call:"()=>{}"}},
|
|
89
65
|
forEachRow:{label:"For Each Row",show:["source"],args:["call"],default:{call:"()=>{}"}},
|
|
90
66
|
forEachCellPairSet:{label:"For Each Cell Pair Set",show:["source"],args:["matrix","call"],default:{call:"()=>{}"}},
|
|
67
|
+
forwardElimination:{label:"Forward Elimination",show:["source"],args:[]},
|
|
68
|
+
gaussianElimination:{label:"Gaussian Elimination",show:["source"],args:[]},
|
|
69
|
+
get:{label:"Get Cell",show:["source","target"],args:[]},
|
|
70
|
+
getAdjoint:{label:"Adjoint",show:["source","target"],args:[]},
|
|
71
|
+
getCofactor:{label:"Cofactor",show:["source","target"],args:[]},
|
|
72
|
+
getComplementMinor:{label:"Complement Minor",show:["source","target"],args:[]},
|
|
73
|
+
getDeterminant:{label:"Determinant",show:["source","target"],args:[]},
|
|
74
|
+
getDeterminantUsingCofactor:{label:"Determinant (Cofactor)",show:["source","target"],args:[]},
|
|
75
|
+
getDeterminantUsingCofactor:{label:"Determinant (Row Echelon Form)",show:["source","target"],args:[]},
|
|
76
|
+
getIdentity:{label:"Identity",show:["source","target"],args:[]},
|
|
77
|
+
getInverse:{label:"Inverse",show:["source","target"],args:[]},
|
|
78
|
+
getInverseAdjointMethod:{label:"Inverse (Adjoint Method)",show:["source","target"],args:[]},
|
|
79
|
+
getInverseGaussJordan:{label:"Inverse (Gauss Jordan Method)",show:["source","target"],args:[]},
|
|
91
80
|
getIndex:{label:"Get Vector Offset",show:["source","target"],args:["row","column"]},
|
|
92
|
-
|
|
93
|
-
getMatrix:{label:"get Sub Matrix",show:["source","target"],args:["row","column","rows","columns"]},
|
|
81
|
+
getMatrix:{label:"Get Sub Matrix",show:["source","target"],args:["row","column","rows","columns"]},
|
|
94
82
|
getRow:{label:"Get Row",show:["source","target"],args:["row"]},
|
|
83
|
+
getVandermonde:{label:"Vandermonde",show:["target"],args:["vector","columns"]},
|
|
84
|
+
getZeroed:{label:"Get Zeroed",show:["source","target"],args:["row","column"]},
|
|
95
85
|
maxAbsColumn:{label:"Column Maximum Absolute",show:["source","target"],args:["column","start"]},
|
|
96
86
|
maxColumn:{label:"Column Max",show:["source","target"],args:["column","start"]},
|
|
87
|
+
multiple:{label:"Multiple",show:["source","target"],args:[]},
|
|
88
|
+
multipleCell:{label:"Multiple Cell",show:["source","target"],args:["rows","columns","value"]},
|
|
97
89
|
multiplyRow:{label:"Multiply Row",show:["source"],args:["row","factor"]},
|
|
90
|
+
norm:{label:"Norm",show:["source","target"],args:[]},
|
|
98
91
|
reduceRow:{label:"Reduce Row",show:["source","target"],args:["row","call","value"],default:{call:"(agregatevalue,cellValue,row,column)=>agregatevalue+cellValue"}},
|
|
92
|
+
reduce:{label:"Reduce Cells",show:["source","target"],args:["call","value"],default:{call:"()=>{}"}},
|
|
93
|
+
reducedRowEchelonForm:{label:"Reduced Row EchelonForm",show:["source"],args:[]},
|
|
94
|
+
rowEchelonForm:{label:"Row Echelon Form",show:["source"],args:[]},
|
|
95
|
+
runningSum:{label:"Running Sum",show:["source","target"],args:[]},
|
|
99
96
|
set:{label:"Set Cell",show:["source"],args:["row","column","value"]},
|
|
100
97
|
setRow:{label:"Set Row",show:["source"],args:["vector","row"]},
|
|
101
|
-
|
|
98
|
+
subtractCell:{label:"Subtract Cell",show:["source","target"],args:["row","column","value"]},
|
|
99
|
+
sumRow:{label:"Sum Row",show:["source","target"],args:[]},
|
|
100
|
+
swapRows:{label:"Swap Rows",show:["source"],args:[]},
|
|
101
|
+
testIsSquare:{label:"Is Square",show:["source"],args:[]},
|
|
102
|
+
toArray:{label:"To Array Object",show:["source","target"],args:[]},
|
|
103
|
+
transpose:{label:"Transpose",show:["source","target"],args:[]}
|
|
102
104
|
};
|
|
103
105
|
const baseDiv=$("#node-inputDynamicBase");
|
|
104
106
|
function defineProperty(property,...types) {
|
|
@@ -118,16 +120,46 @@
|
|
|
118
120
|
const inputNode=$('<input type="text" id="node-input-'+property.name+'"/>').val(node[property.name]);
|
|
119
121
|
const typeNode=$('<input type="hidden" id="node-input-'+property.name+'-type"/>');
|
|
120
122
|
element.append([inputNode,typeNode]);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
123
|
+
if(types[0] instanceof Array) {
|
|
124
|
+
$("#node-input-"+property.name).typedInput({
|
|
125
|
+
type:property.name,
|
|
126
|
+
types:[{value: property.name,
|
|
127
|
+
options: types[0]
|
|
128
|
+
}]})
|
|
129
|
+
} else {
|
|
130
|
+
const typeValue=node[property.name+"-type"];
|
|
131
|
+
if(typeValue) typeNode.val(typeValue);
|
|
132
|
+
$("#node-input-"+property.name).typedInput({
|
|
133
|
+
type:typeValue||types[0],
|
|
134
|
+
types:types,
|
|
135
|
+
typeField: "#node-input-"+property.name+"-type"
|
|
136
|
+
});
|
|
137
|
+
}
|
|
128
138
|
}
|
|
129
139
|
}
|
|
130
|
-
defineProperty({name:"
|
|
140
|
+
defineProperty({name:"initialState",label:"Initially" ,icon:"tag"},[
|
|
141
|
+
{ value: "setZero", label: "Zeros"},
|
|
142
|
+
{ value: "setRandom", label: "Random Numbers"},
|
|
143
|
+
{ value: "setIdentity", label: "Identity"},
|
|
144
|
+
{ value: "setOne", label: "all 1"},
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
defineProperty({name:"dataType",label:"number Type" ,icon:"tag"},[
|
|
148
|
+
{ value: "Float32Array", label: "float32 -3.4e38 to 3.4e38" },
|
|
149
|
+
{ value: "Float64Array", label: "double/float64 -1.8e308 to 1.8e308" }, { value: "Int8Array", label: "byte -128 to 122" },
|
|
150
|
+
{ value: "Uint8Array", label: "octet 0 to 255" },
|
|
151
|
+
{ value: "Uint8ClampedArray", label: "octet clamped 0 to 255" },
|
|
152
|
+
{ value: "Int16Array", label: "short -32768 to 32767" },
|
|
153
|
+
{ value: "Uint16Array", label: "short unsigned 0 to 65535" },
|
|
154
|
+
{ value: "Int32Array", label: " long -2147483648 to 2147483647" },
|
|
155
|
+
{ value: "Uint32Array", label: "long unsgined 0 to 4294967295" },
|
|
156
|
+
{ value: "BigInt64Array", label: "bigint 2**-263 to 2**263" },
|
|
157
|
+
{ value: "BigUint64Array", label: "bigint unsigned 0 to 2**264" },
|
|
158
|
+
]);
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
defineProperty({name:"source" ,label:"Source" ,icon:"crosshairs"},"msg","json","flow","global");
|
|
131
163
|
defineProperty({name:"arg" ,label:"Argument" ,icon:"tag"},"num","json","msg","flow","global","env");
|
|
132
164
|
defineProperty({name:"matrix" ,label:"Matrix" ,icon:"th"},"msg","flow","global");
|
|
133
165
|
defineProperty({name:"target" ,label:"Target" ,icon:"save"},"msg","flow","global");
|
|
@@ -145,8 +177,10 @@
|
|
|
145
177
|
defineProperty({name:"vector" ,label:"Vector" ,icon:"ellipsis-h"},"json","msg","flow","global");
|
|
146
178
|
defineProperty({name:"call" ,label:"Call" ,icon:"js",mode:"javascript"},"edit");
|
|
147
179
|
|
|
148
|
-
const options=Object.keys(actions)
|
|
149
|
-
[])
|
|
180
|
+
const options=Object.keys(actions)
|
|
181
|
+
.sort((a,b) => actions[a].label<actions[b].label?-1:0)
|
|
182
|
+
.reduce((previousValue,property)=>previousValue.concat({value:property,label:actions[property].label}),
|
|
183
|
+
[]);
|
|
150
184
|
const actionNode=$("#node-input-action");
|
|
151
185
|
actionNode.typedInput({
|
|
152
186
|
types: [{
|
|
@@ -154,7 +188,7 @@
|
|
|
154
188
|
options: options
|
|
155
189
|
}]
|
|
156
190
|
});
|
|
157
|
-
|
|
191
|
+
actionNode.change(function() {
|
|
158
192
|
action=$(this).val();
|
|
159
193
|
node.args=[];
|
|
160
194
|
node.properties.forEach(property=>$(".form-row-http-in-"+property).hide());
|
|
@@ -162,7 +196,6 @@
|
|
|
162
196
|
node.args=actionDef.args;
|
|
163
197
|
node.args.forEach(property=>$(".form-row-http-in-"+property).show());
|
|
164
198
|
actionDef.show.forEach(property=>$(".form-row-http-in-"+property).show());
|
|
165
|
-
|
|
166
199
|
});
|
|
167
200
|
},
|
|
168
201
|
oneditsave: function() {
|
package/matrix/matrixNode.js
CHANGED
|
@@ -23,6 +23,7 @@ function evalInFunction(node,propertyName){
|
|
|
23
23
|
const property=node[propertyName];
|
|
24
24
|
if(property==null) throw Error("no value for "+propertyName);
|
|
25
25
|
const propertyType=propertyName+"-type";
|
|
26
|
+
if(! (propertyType in node)) return evalFunction(propertyName,"()=>node."+property)
|
|
26
27
|
switch (node[propertyType]){
|
|
27
28
|
case "num":
|
|
28
29
|
case "json":
|
|
@@ -86,7 +87,11 @@ module.exports = function (RED) {
|
|
|
86
87
|
}
|
|
87
88
|
node.argFunction=[];
|
|
88
89
|
node.args.forEach(property=>{
|
|
89
|
-
|
|
90
|
+
try{
|
|
91
|
+
node.argFunction.push(evalInFunction(node,property).bind(this));
|
|
92
|
+
} catch(ex) {
|
|
93
|
+
throw Error("args "+property+" "+ex.message)
|
|
94
|
+
}
|
|
90
95
|
})
|
|
91
96
|
function baseProcess(msg){
|
|
92
97
|
const sourceIn=node.getSource(msg);
|
|
@@ -99,14 +104,15 @@ module.exports = function (RED) {
|
|
|
99
104
|
node.setData.apply(node,[result,msg]);
|
|
100
105
|
}
|
|
101
106
|
function createProcess(msg){
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
if(logger.active) logger.sendInfo({label:"create",arg:{rowsMax:node.row,columns:node.column}});
|
|
108
|
+
const sourceMatrix=new Matrix({rowsMax:node.rows,columns:node.columns,dataType:node.dataType});
|
|
109
|
+
if(!(node.initialState in sourceMatrix)) throw Error("Invalid initial state "+node.initialState);
|
|
110
|
+
sourceMatrix[node.initialState]()
|
|
105
111
|
node.setData.apply(node,[sourceMatrix,msg]);
|
|
106
112
|
}
|
|
107
113
|
function defineProcess(msg){
|
|
108
114
|
if(logger.active) logger.sendInfo({label:"define",arg:{rows:node.row,columns:node.column}});
|
|
109
|
-
const sourceMatrix=new Matrix({rows:node.rows,columns:node.columns});
|
|
115
|
+
const sourceMatrix=new Matrix({rows:node.rows,columns:node.columns,dataType:node.dataType});
|
|
110
116
|
node.setData.apply(node,[sourceMatrix,msg]);
|
|
111
117
|
}
|
|
112
118
|
function defineEmptyProcess(msg){
|
|
@@ -152,6 +158,7 @@ module.exports = function (RED) {
|
|
|
152
158
|
node.msgProcess(msg);
|
|
153
159
|
node.send(msg);
|
|
154
160
|
} catch(ex) {
|
|
161
|
+
error(node,ex,"Invalid "+ex.message)
|
|
155
162
|
msg.error=ex.message;
|
|
156
163
|
node.send([null,msg]);
|
|
157
164
|
if(logger.active) logger.send({label:"error",node:node.id,action:node.action,exception:ex.message,stack:ex.stack});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function Dataset(settings) {
|
|
2
|
+
Object.assign(this,{values:[]},settings)
|
|
3
|
+
}
|
|
4
|
+
Dataset.prototype.addValue=function(v){
|
|
5
|
+
if(this.min==null) {
|
|
6
|
+
this.max=v
|
|
7
|
+
this.min=v
|
|
8
|
+
this.range=0
|
|
9
|
+
this.average=v
|
|
10
|
+
} else {
|
|
11
|
+
if(this.min>v){
|
|
12
|
+
this.min=v
|
|
13
|
+
this.range=this.max-this.min
|
|
14
|
+
} else if(this.max<v){
|
|
15
|
+
this.max=v
|
|
16
|
+
this.range=this.max-this.min
|
|
17
|
+
}
|
|
18
|
+
this.average+=(v-this.average)/(this.values.length+1)
|
|
19
|
+
}
|
|
20
|
+
this.values.push(v)
|
|
21
|
+
}
|
|
22
|
+
Dataset.prototype.getMax=function(){return this.max}
|
|
23
|
+
Dataset.prototype.getMin=function(){return this.min}
|
|
24
|
+
Dataset.prototype.getAverage=function(){return this.average}
|
|
25
|
+
Dataset.prototype.getFirst=function(){return this.values[0]}
|
|
26
|
+
Dataset.prototype.getRange=function(){return this.range}
|
|
27
|
+
Dataset.prototype.getLast=function(){return this.value.slice(-1)}
|
|
28
|
+
|
|
29
|
+
module.exports=Dataset
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const defs=require("./defs.js")
|
|
2
|
+
const DialNeedle=require("./DialNeedle.js")
|
|
3
|
+
const boundValue=(v,max=100,min=0)=>Math.min(Math.max(v, min), max)
|
|
4
|
+
const pi2=2 * Math.PI
|
|
5
|
+
const pi2DegreeFactor=180 / Math.PI
|
|
6
|
+
const toRadians=(degrees)=> degrees / pi2DegreeFactor
|
|
7
|
+
const toDegrees=(radians)=> radians * pi2DegreeFactor
|
|
8
|
+
function DialGauge(settings) {
|
|
9
|
+
Object.assign(this,{radius:100,value:0,gapAngle:80,color:"gray",min:0,max:100,title:"%"},settings)
|
|
10
|
+
this.range=this.max-this.min
|
|
11
|
+
if(this.range<=0) throw Error("invalid range, min>=max")
|
|
12
|
+
this.strokeWidth = this.radius * 0.3;
|
|
13
|
+
this.circumference = this.radius * pi2
|
|
14
|
+
this.dashOffset = this.circumference * this.gapAngle/380;
|
|
15
|
+
this.gaugeAngleArea=360-this.gapAngle
|
|
16
|
+
this.angleFactor=this.gaugeAngleArea/this.range
|
|
17
|
+
this.halfStrokeGap=(this.circumference-this.dashOffset)/2
|
|
18
|
+
this.strokeInnerRadius=this.radius - this.strokeWidth / 2
|
|
19
|
+
this.strokeInnerCircumference= this.strokeInnerRadius * pi2
|
|
20
|
+
this.strokeDashOffset = this.strokeInnerCircumference * this.gaugeAngleArea/360;
|
|
21
|
+
this.gauge={action:"circle",fill:"transparent",
|
|
22
|
+
cx:this.radius,cy:this.radius,r:this.strokeInnerRadius,stroke:"lightgray","stroke-width":this.strokeWidth,
|
|
23
|
+
"stroke-dasharray":this.getDashArray(this.max),
|
|
24
|
+
transform:{rotate:{angle:90+parseInt(this.gapAngle/2),x:this.radius,y:this.radius}}}
|
|
25
|
+
this.needle=new DialNeedle({radius:this.radius,startAngle:-this.gaugeAngleArea/2})
|
|
26
|
+
this.svg=this.getSvg()
|
|
27
|
+
}
|
|
28
|
+
DialGauge.prototype.get=function(value){
|
|
29
|
+
return this.svg
|
|
30
|
+
}
|
|
31
|
+
DialGauge.prototype.getSvg=function(){
|
|
32
|
+
const group=[]
|
|
33
|
+
group.push(Object.assign({},this.gauge,{stroke:"red"}))
|
|
34
|
+
group.push(Object.assign({},this.gauge,{stroke:"orange","stroke-dasharray":this.getDashArray(80)}))
|
|
35
|
+
group.push(Object.assign({},this.gauge,{stroke:"yellow","stroke-dasharray":this.getDashArray(60)}))
|
|
36
|
+
group.push(Object.assign({},this.gauge,{stroke:"lightgreen","stroke-dasharray":this.getDashArray(40)}))
|
|
37
|
+
group.push(Object.assign({},this.gauge,{stroke:"green","stroke-dasharray":this.getDashArray(20)}))
|
|
38
|
+
group.push(Object.assign({},this.gauge,{id:"dialColor",stroke:"lightgray","stroke-dasharray":this.getDashArrayReverse(0)}))
|
|
39
|
+
/*
|
|
40
|
+
group.push({action:"clipPath",id:"clipGauge",children:[
|
|
41
|
+
Object.assign({},this.gauge,{id:"dialColor1","stroke-dasharray":this.getDashArray(0),"stroke-miterlimit":"10",stroke:"none",class:"heatGrad"})
|
|
42
|
+
]})
|
|
43
|
+
group.push({action:"style",children:["circle.heatGrad {background: conic-gradient(red, orange, yellow, green); }"]})
|
|
44
|
+
group.push({action:"use",href:{id:"clipGauge"}})
|
|
45
|
+
*/
|
|
46
|
+
group.push(this.getScale())
|
|
47
|
+
group.push({action:"text",x:this.radius,y:this.radius*1.5,"dominant-baseline":"middle","text-anchor":"middle",children:[this.title]})
|
|
48
|
+
group.push(this.needle.get(0))
|
|
49
|
+
return {action:"g",height:2*this.radius,children:[group]}
|
|
50
|
+
/*
|
|
51
|
+
{action:"clipPath",children:[
|
|
52
|
+
Object.assign({},this.gauge,{id:"dialColor","stroke-dasharray":this.getDashArray(0),stroke:"none",class:"grad"})
|
|
53
|
+
]},
|
|
54
|
+
{action:"style",children:["circle.grad {background: conic-gradient(red, orange, yellow, green); }"]},
|
|
55
|
+
{action:"setConicGradient",id:"clip"},
|
|
56
|
+
*/
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
DialGauge.prototype.getUpdate=function(value){
|
|
60
|
+
return [this.needle.getUpdate((value-this.min)*this.angleFactor),{action:"update",id:"dialColor","stroke-dasharray":this.getDashArrayReverse(value)}]
|
|
61
|
+
}
|
|
62
|
+
DialGauge.prototype.setMax=function(value){
|
|
63
|
+
this.max = value
|
|
64
|
+
this.range=this.max-this.min
|
|
65
|
+
if(this.range<=0) throw Error("invalid range, min>=max")
|
|
66
|
+
this.angleFactor=this.gaugeAngleArea/this.range
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
DialGauge.prototype.getDashArray=function(value){
|
|
70
|
+
const ratio=(value-this.min)/this.range
|
|
71
|
+
const dash=this.strokeDashOffset*ratio
|
|
72
|
+
const gap=this.strokeInnerCircumference-dash
|
|
73
|
+
return dash+","+gap
|
|
74
|
+
}
|
|
75
|
+
DialGauge.prototype.getDashArrayReverse=function(value){
|
|
76
|
+
const ratio=(value-this.min)/this.range
|
|
77
|
+
const gap=this.strokeDashOffset*ratio
|
|
78
|
+
const dash=this.strokeDashOffset*(1-ratio)
|
|
79
|
+
return "0,"+gap+","+dash+","+this.strokeDashOffset
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
DialGauge.prototype.getScale=function() {
|
|
83
|
+
const sr1 = this.radius;
|
|
84
|
+
const sr2 = this.radius - this.strokeWidth-5;
|
|
85
|
+
const srT = sr2 - 10;
|
|
86
|
+
const objDef=[]
|
|
87
|
+
let n = 0;
|
|
88
|
+
const increment=toRadians(this.gaugeAngleArea/10)
|
|
89
|
+
for (let sr = toRadians(-this.gaugeAngleArea); sr <= 0; sr += increment) {
|
|
90
|
+
const sra=sr + toRadians(90 - this.gapAngle/2)
|
|
91
|
+
const saCos=Math.cos(sra)
|
|
92
|
+
const saSin=Math.sin(sra)
|
|
93
|
+
objDef.push({action:"line",
|
|
94
|
+
x1:this.radius + sr1 * saCos,
|
|
95
|
+
y1:this.radius + sr1 * saSin,
|
|
96
|
+
x2:this.radius + sr2 * saCos,
|
|
97
|
+
y2:this.radius + sr2 * saSin}
|
|
98
|
+
)
|
|
99
|
+
objDef.push({action:"text",
|
|
100
|
+
x:this.radius + srT * saCos,
|
|
101
|
+
y:this.radius + srT * saSin,
|
|
102
|
+
children:[String(n*10)]
|
|
103
|
+
})
|
|
104
|
+
n++
|
|
105
|
+
}
|
|
106
|
+
return objDef;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports=DialGauge
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function DialNeedle(settings) {
|
|
2
|
+
Object.assign(this,{
|
|
3
|
+
radius:100,
|
|
4
|
+
startAngle:0,
|
|
5
|
+
id:"needle",
|
|
6
|
+
baseDialSize:20,
|
|
7
|
+
value:{min:0,max:100}
|
|
8
|
+
},settings)
|
|
9
|
+
Object.assign(this,{
|
|
10
|
+
endAngle:this.endAngle??360-this.startAngle,
|
|
11
|
+
center:this.center??{x:this.radius,y:this.radius}
|
|
12
|
+
})
|
|
13
|
+
this.value.range=this.value.max-this.value.min
|
|
14
|
+
this.ratio=(this.endAngle-this.startAngle)/this.range,
|
|
15
|
+
this.svg=this.getSvg();
|
|
16
|
+
}
|
|
17
|
+
DialNeedle.prototype.get=function(value){
|
|
18
|
+
return this.svg
|
|
19
|
+
}
|
|
20
|
+
DialNeedle.prototype.getSvg=function(id=""){
|
|
21
|
+
return {action:"g",id:id+this.id,children:[
|
|
22
|
+
{action:"path",transform:{rotate:{angle:this.startAngle,x:this.radius,y:this.radius}},d:[
|
|
23
|
+
{action:"moveTo",x:this.radius,y:0},
|
|
24
|
+
{action:"deltaLineTo",x:-this.baseDialSize,y:this.radius},
|
|
25
|
+
{action:"deltaArc",radius:{x:this.baseDialSize,y:this.baseDialSize},x:this.baseDialSize*2,y:0},
|
|
26
|
+
{action:"Z"}
|
|
27
|
+
],
|
|
28
|
+
fill:this.color,stroke:this.color
|
|
29
|
+
}
|
|
30
|
+
]}
|
|
31
|
+
}
|
|
32
|
+
DialNeedle.prototype.getUpdate=function(angle){
|
|
33
|
+
if(angle>360 || angle < -360) throw Error("angle > 360 or < -360, angle: "+angle)
|
|
34
|
+
return {action:"update",id:this.id,transform:{rotate:{angle,x:this.radius,y:this.radius}}}
|
|
35
|
+
}
|
|
36
|
+
module.exports=DialNeedle
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const Format={
|
|
2
|
+
NumberToAbbreviated:(value)=>{
|
|
3
|
+
if(typeof value!='number') value=parseFloat(value);
|
|
4
|
+
if (value>Math.pow(10,16)) return Math.round(value/Math.pow(10,15)).toString()+'P'
|
|
5
|
+
if (value>Math.pow(10,13)) return Math.round(value/Math.pow(10,12)).toString()+'T'
|
|
6
|
+
if (value>Math.pow(10,10)) return Math.round(value/Math.pow(10,9)).toString()+'G'
|
|
7
|
+
if (value>Math.pow(10,7)) return Math.round(value/Math.pow(10,6)).toString()+'M'
|
|
8
|
+
if (value>Math.pow(10,4)) return Math.round(value/Math.pow(10,3)).toString()+'K'
|
|
9
|
+
if (value == Math.round(value)) return value.toString()
|
|
10
|
+
if (value>=10000) return value.toFixed(0).toString()
|
|
11
|
+
if (value>=1000) return value.toFixed(1).toString()
|
|
12
|
+
if (value>=100) return value.toFixed(2).toString()
|
|
13
|
+
if (value>=10) return value.toFixed(3).toString()
|
|
14
|
+
return value.toString()
|
|
15
|
+
},
|
|
16
|
+
HexToString: (value)=>{
|
|
17
|
+
if(value==null) return null;
|
|
18
|
+
let valueString = '';
|
|
19
|
+
for (let i = 0; i < value.length; i += 2)
|
|
20
|
+
valueString += String.fromCharCode(parseInt(value.substr(i, 2), 16));
|
|
21
|
+
return valueString;
|
|
22
|
+
},
|
|
23
|
+
padLeadZero:(value,size)=>"000000000000".substr(0,size-value.toString().length)+value,
|
|
24
|
+
toString:(type,value)=>{
|
|
25
|
+
switch (type) {
|
|
26
|
+
case 'timestamp' :
|
|
27
|
+
case 'datetime' :
|
|
28
|
+
case 'time' :
|
|
29
|
+
case 'date' :
|
|
30
|
+
var ts = new Date();
|
|
31
|
+
ts.setTime(parseInt(value));
|
|
32
|
+
var axisLabel='';
|
|
33
|
+
switch (this.dataType[0]) {
|
|
34
|
+
case 'timestamp' :
|
|
35
|
+
case 'date' :
|
|
36
|
+
case 'datetime' :
|
|
37
|
+
if (this.precision[0] >= 1440) axisLabel+=ts.getFullYear()+'-';
|
|
38
|
+
if (this.precision[0] >= 1440) axisLabel+=Format.padLeadZero(ts.getMonth()+1,2)+'-';
|
|
39
|
+
if (this.precision[0] >= 1440) axisLabel+=Format.padLeadZero(ts.getDate(),2);
|
|
40
|
+
if (this.precision[0] >= 1440) axisLabel+=' ';
|
|
41
|
+
case 'time' :
|
|
42
|
+
if (this.precision[0] >= 360) axisLabel+=Format.padLeadZero(ts.getHours(),2)+':';
|
|
43
|
+
if (this.precision[0] >= 60) axisLabel+=Format.padLeadZero(ts.getMinutes(),2)+':';
|
|
44
|
+
if (this.precision[0] >= 1) axisLabel+=Format.padLeadZero(ts.getSeconds(),2);
|
|
45
|
+
}
|
|
46
|
+
return axisLabel;
|
|
47
|
+
case 'int' :
|
|
48
|
+
case 'real' :
|
|
49
|
+
case 'number' :
|
|
50
|
+
return format.NumberToAbbreviated(value)
|
|
51
|
+
}
|
|
52
|
+
return value.toString();
|
|
53
|
+
},
|
|
54
|
+
StringToHex:(value)=>{
|
|
55
|
+
if(value==null) return null;
|
|
56
|
+
let hex = '';
|
|
57
|
+
for(let i=0;i<value.length;i++)
|
|
58
|
+
hex += ''+value.charCodeAt(i).toString(16);
|
|
59
|
+
return hex;
|
|
60
|
+
},
|
|
61
|
+
xmlEncodeString(value) {
|
|
62
|
+
if(value==null) return null;
|
|
63
|
+
return value.toString().replace(/([\&"<>])/g, function(str, item) {
|
|
64
|
+
return {
|
|
65
|
+
'&': '&',
|
|
66
|
+
'"': '"',
|
|
67
|
+
'<': '<',
|
|
68
|
+
'>': '>'
|
|
69
|
+
}[item];
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports=Format
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
function centerElement(elementIdToCenter) {
|
|
2
|
+
if(elementIdToCenter == null) return;
|
|
3
|
+
const toCenter = document.getElementById(elementIdToCenter);
|
|
4
|
+
const width = toCenter.getWidth();
|
|
5
|
+
const height = toCenter.getHeight();
|
|
6
|
+
const elementParent = toCenter.ancestors();
|
|
7
|
+
const Pwidth = elementParent[0].getWidth();
|
|
8
|
+
const Pheight = elementParent[0].getHeight();
|
|
9
|
+
width = parseInt(Pwidth/2, 10) - parseInt(width/2, 10);
|
|
10
|
+
height = parseInt(Pheight/2, 10) - parseInt(height/2, 10);
|
|
11
|
+
toCenter.setStyle({'top': height + 'px'});
|
|
12
|
+
toCenter.setStyle({'left': width + 'px'});
|
|
13
|
+
}
|
|
14
|
+
module.exports=centerElement
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
function compareNodes(oldNode, newNode, compare) { // this function under construction
|
|
2
|
+
if( compare==null)
|
|
3
|
+
var compare= {
|
|
4
|
+
attribute: {
|
|
5
|
+
match: function(attribute) {
|
|
6
|
+
}
|
|
7
|
+
,mismatch: function(oldAttribute,newAttribute) {
|
|
8
|
+
return '<attribute key="'+oldAttribute.nodeName+'" old="'+oldAttribute.nodeValue+'" new="'+newAttribute.nodeValue+'"/>';
|
|
9
|
+
}
|
|
10
|
+
,missingNew: function(attribute) {
|
|
11
|
+
return '<attribute key="'+attribute.nodeName+'" new="'+attribute.nodeValue+'"/>';
|
|
12
|
+
}
|
|
13
|
+
,missingOld : function(attribute) {
|
|
14
|
+
return '<attribute key="'+attribute.nodeName+'" old="'+attribute.nodeValue+'"/>';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
,node: {
|
|
18
|
+
isSameElement: function(oldNode,newNode) {
|
|
19
|
+
if(oldNode.nodeType != newNode.nodeType) return false;
|
|
20
|
+
if(oldNode.nodeType != 1) return true;
|
|
21
|
+
return (oldNode.nodeName = newNode.nodeName);
|
|
22
|
+
}
|
|
23
|
+
,match: function(node) {
|
|
24
|
+
}
|
|
25
|
+
,mismatch: function(oldNode,newNode) {
|
|
26
|
+
return '<pair><new th>"'+node.nodeValue+'</new></node>'
|
|
27
|
+
}
|
|
28
|
+
,missingNew: function(node) {
|
|
29
|
+
return '<node key="'+node.nodeName+'"><new>"'+node.nodeValue+'</new></node>'
|
|
30
|
+
}
|
|
31
|
+
,missingOld : function(node) {
|
|
32
|
+
return '<node key="'+node.nodeName+'"><old>"'+node.nodeValue+'</old></node>'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var diff="";
|
|
37
|
+
if(oldNode == null)
|
|
38
|
+
var oldAttributes=[] , oldNodes=[];
|
|
39
|
+
else
|
|
40
|
+
var oldAttributes=oldNode.attributes , oldNodes=oldNode.childNodes;
|
|
41
|
+
if(newNode == null)
|
|
42
|
+
var newAttributes=[] , newNodes=[];
|
|
43
|
+
else
|
|
44
|
+
var newAttributes=newNode.attributes , newNodes=oldNode.childNodes;
|
|
45
|
+
if( !compare.node.isSameElement(oldNode,newNode)
|
|
46
|
+
|| oldNode.nodeValue != newNode.nodeValue )
|
|
47
|
+
diff += compare.node.mismatch(oldNode,newNode);
|
|
48
|
+
else
|
|
49
|
+
diff += compare.node.match(oldNode,newNode);
|
|
50
|
+
var o=0;n=0;
|
|
51
|
+
while (o<oldAttributes.length || n<newAttributes.length) {
|
|
52
|
+
var oldAttribute=oldAttributes[o],newAttribute=newAttributes[n];
|
|
53
|
+
if(oldAttributes.nodeName==newAttribute.nodeName) {
|
|
54
|
+
if(oldAttribute.nodeValue==newAttribute.nodeValue)
|
|
55
|
+
diff += compare.attribute.match(oldAttribute);
|
|
56
|
+
else
|
|
57
|
+
diff += compare.attribute.mismatch(oldAttribute,newAttribute);
|
|
58
|
+
o++;n++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if(oldAttribute.nodeName>newAttribute.nodeName) {
|
|
62
|
+
diff += compare.attribute.missingNew(newAttribute);
|
|
63
|
+
n++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
diff+= compare.attribute.missingOld(oldAttribute);
|
|
67
|
+
o++;
|
|
68
|
+
}
|
|
69
|
+
for (o=o;oldAttributes.length;o++) diff += compare.attribute.missingOld(oldAttributes[o]);
|
|
70
|
+
for (n=n;newAttributes.length;n++) diff += compare.attribute.missingANew(newAttributes[n]);
|
|
71
|
+
o=0;n=0;
|
|
72
|
+
while (o<oldNodes.length || n<newNodes.length) {
|
|
73
|
+
var oldNode=oldNodes[o]; newNode=newNodes[n];
|
|
74
|
+
if(compare.node.isSameElement(oldNode,newNode)) {
|
|
75
|
+
diff+=compareNodes(oldNode,newNode,compare);
|
|
76
|
+
n++;o++;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
for (i=o;i<oldNodes.length;i++) // search for same element
|
|
80
|
+
if(compare.node.isSameElement(oldNodes[i],newNode)) break;
|
|
81
|
+
for (j=n;j<newNodes.length;j++) // search for same element
|
|
82
|
+
if(compare.node.isSameElement(oldNode,newNodes[j])) break;
|
|
83
|
+
|
|
84
|
+
if(i>=oldNodes.length) i=9999;
|
|
85
|
+
if(j>=newNodes.length) j=9999;
|
|
86
|
+
if((i-o)>(j-n))
|
|
87
|
+
for (n=n;n<j;n++) compare.node.missingNew(newNodes[n]);
|
|
88
|
+
else
|
|
89
|
+
for (o=o;o<i;o++) compare.node.missingOld(oldNodes[o]);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
for (o=o;o<oldNodes.length;o++) compare.node.missingOld(oldNodes[o]);
|
|
93
|
+
for (n=n;n<newNodes.length;n++) compare.node.missingNew(newNodes[n]);
|
|
94
|
+
}
|
|
95
|
+
|