@atelieruldetehnologii/node-red-custome-solutions 0.62.22
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/NOTICE +56 -0
- package/PROPRIETARY-LICENSE.txt +157 -0
- package/README.md +105 -0
- package/TERMS-AND-CONDITIONS.md +311 -0
- package/advantech-read/advantech-read.html +775 -0
- package/advantech-read/advantech-read.js +449 -0
- package/advantech-write/advantech-write.html +413 -0
- package/advantech-write/advantech-write.js +338 -0
- package/bess-control/bess-control.html +569 -0
- package/bess-control/bess-control.js +541 -0
- package/bess-control/lib/allocation.js +149 -0
- package/bess-control/lib/batteries.js +86 -0
- package/bess-control/lib/helpers.js +157 -0
- package/bess-control/lib/messages.js +131 -0
- package/bess-control/lib/runtime.js +156 -0
- package/carlo-gavazzi/carlo-gavazzi.html +4327 -0
- package/carlo-gavazzi/carlo-gavazzi.js +3081 -0
- package/control-export/control-export.html +3644 -0
- package/control-export/control-export.js +2192 -0
- package/control-reactive/control-reactive.html +3136 -0
- package/control-reactive/control-reactive.js +2124 -0
- package/fronius-emulator/README.md +258 -0
- package/fronius-emulator/fronius-emulator.html +170 -0
- package/fronius-emulator/fronius-emulator.js +520 -0
- package/fronius-emulator/lib/binary-codec.js +65 -0
- package/fronius-emulator/lib/fronius-register-map.js +185 -0
- package/fronius-emulator/lib/modbus-parser.js +61 -0
- package/fronius-emulator/lib/modbus-tcp-server.js +224 -0
- package/fronius-emulator/lib/validation.js +206 -0
- package/fronius-emulator/lib/virtual-meter.js +132 -0
- package/fronius-read/fronius-read.html +3944 -0
- package/fronius-read/fronius-read.js +1466 -0
- package/fronius-read/lib/inverter-profiles.js +711 -0
- package/fronius-read/lib/sunspec-core.js +303 -0
- package/fronius-read/lib/sunspec-model-parsers.js +845 -0
- package/fronius-write/fronius-write.html +1789 -0
- package/fronius-write/fronius-write.js +2531 -0
- package/influxdb/influxdb.html +1077 -0
- package/influxdb/influxdb.js +1487 -0
- package/janitza/janitza.html +2562 -0
- package/janitza/janitza.js +1500 -0
- package/janitza/lib/janitza-profiles.js +371 -0
- package/lib/a3-test-server.js +199 -0
- package/lib/adam-6000-profiles.js +173 -0
- package/lib/licensing/constants.js +103 -0
- package/lib/licensing/device-id.js +251 -0
- package/lib/licensing/errors.js +21 -0
- package/lib/licensing/license-client.js +377 -0
- package/lib/licensing/license-state.js +50 -0
- package/lib/licensing/node-guard.js +150 -0
- package/lib/licensing/package-integrity.js +167 -0
- package/lib/licensing/package-integrity.json +513 -0
- package/lib/licensing/public-key.pem +3 -0
- package/lib/licensing/public-key.pem.example +2 -0
- package/lib/licensing/public-keys.js +18 -0
- package/lib/licensing/storage.js +63 -0
- package/lib/licensing/token-verifier.js +84 -0
- package/lib/numbers.js +26 -0
- package/license/atelier-license.html +88 -0
- package/license/atelier-license.js +170 -0
- package/modbus-tcp-discover/modbus-tcp-discover.html +190 -0
- package/modbus-tcp-discover/modbus-tcp-discover.js +706 -0
- package/multi-battery/multi-battery.html +649 -0
- package/multi-battery/multi-battery.js +668 -0
- package/multi-grid/multi-grid.html +745 -0
- package/multi-grid/multi-grid.js +1392 -0
- package/multi-inverter/lib/engine-core.js +237 -0
- package/multi-inverter/multi-inverter.html +2674 -0
- package/multi-inverter/multi-inverter.js +1393 -0
- package/package.json +109 -0
- package/phoenix-contact/lib/eem-ma370-advanced.js +175 -0
- package/phoenix-contact/lib/eem-ma370.js +138 -0
- package/phoenix-contact/lib/integrations.js +149 -0
- package/phoenix-contact/lib/phoenix-contact-profile.js +35030 -0
- package/phoenix-contact/phoenix-contact.html +840 -0
- package/phoenix-contact/phoenix-contact.js +679 -0
- package/pv-generator/pv-generator.html +284 -0
- package/pv-generator/pv-generator.js +387 -0
- package/pylontech-read/pylontech-read.html +763 -0
- package/pylontech-read/pylontech-read.js +518 -0
- package/pylontech-write/pylontech-write.html +405 -0
- package/pylontech-write/pylontech-write.js +546 -0
- package/scada-aggregator/lib/aggregate.js +72 -0
- package/scada-aggregator/lib/groups.js +39 -0
- package/scada-aggregator/scada-aggregator.html +108 -0
- package/scada-aggregator/scada-aggregator.js +117 -0
- package/scada-server/lib/aggregator-map.js +58 -0
- package/scada-server/lib/encoding.js +235 -0
- package/scada-server/lib/modbus-server.js +492 -0
- package/scada-server/lib/object-path.js +18 -0
- package/scada-server/lib/register-map.js +288 -0
- package/scada-server/scada-server.html +1419 -0
- package/scada-server/scada-server.js +704 -0
- package/scripts/check-syntax.js +66 -0
- package/scripts/package-integrity.js +46 -0
- package/scripts/package-release.js +116 -0
- package/scripts/run-tests.js +2178 -0
- package/scripts/tgz-integrity.js +74 -0
- package/sma-read/lib/sunspec-core.js +83 -0
- package/sma-read/lib/sunspec-model-parsers.js +853 -0
- package/sma-read/sma-read.html +659 -0
- package/sma-read/sma-read.js +458 -0
- package/sma-write/sma-write.html +105 -0
- package/sma-write/sma-write.js +270 -0
- package/victron-read/lib/mqtt-state.js +176 -0
- package/victron-read/victron-read.html +1074 -0
- package/victron-read/victron-read.js +1222 -0
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.multi-grid-editor {
|
|
3
|
+
--mg-border: #d7dde5;
|
|
4
|
+
--mg-muted: #667085;
|
|
5
|
+
--mg-surface: #f8fbff;
|
|
6
|
+
--mg-head: #e8f2ff;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.multi-grid-editor .mg-hero,
|
|
10
|
+
.multi-grid-editor .mg-section {
|
|
11
|
+
margin: 0 0 18px;
|
|
12
|
+
padding: 14px 16px 16px;
|
|
13
|
+
border: 1px solid var(--mg-border);
|
|
14
|
+
border-radius: 12px;
|
|
15
|
+
background: var(--mg-surface);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.multi-grid-editor .mg-hero {
|
|
19
|
+
background: linear-gradient(135deg, var(--mg-head), #f8fbff);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.multi-grid-editor .mg-title {
|
|
23
|
+
margin: 0 0 4px;
|
|
24
|
+
font-size: 15px;
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
color: #243447;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.multi-grid-editor .mg-note {
|
|
30
|
+
margin: 0 0 14px;
|
|
31
|
+
color: var(--mg-muted);
|
|
32
|
+
font-size: 12px;
|
|
33
|
+
line-height: 1.45;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.multi-grid-editor .mg-grid {
|
|
37
|
+
display: grid;
|
|
38
|
+
grid-template-columns: repeat(2, minmax(320px, 1fr));
|
|
39
|
+
gap: 12px 16px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.multi-grid-editor .form-row {
|
|
43
|
+
margin-bottom: 12px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.multi-grid-editor .mg-grid .form-row,
|
|
47
|
+
.multi-grid-editor .form-row:last-child {
|
|
48
|
+
margin-bottom: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.multi-grid-editor .form-row > label {
|
|
52
|
+
width: 150px;
|
|
53
|
+
font-weight: 600;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.multi-grid-editor .form-row > input[type="text"],
|
|
57
|
+
.multi-grid-editor .form-row > input[type="number"],
|
|
58
|
+
.multi-grid-editor .form-row > select {
|
|
59
|
+
width: calc(100% - 160px);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.multi-grid-editor .mg-checkbox-row > input[type="checkbox"] {
|
|
63
|
+
display: inline-block;
|
|
64
|
+
width: auto;
|
|
65
|
+
vertical-align: top;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.multi-grid-editor .mg-inline-note {
|
|
69
|
+
margin-left: 8px;
|
|
70
|
+
color: var(--mg-muted);
|
|
71
|
+
line-height: 1.4;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media (max-width: 1100px) {
|
|
75
|
+
.multi-grid-editor .mg-grid {
|
|
76
|
+
grid-template-columns: 1fr;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
</style>
|
|
80
|
+
|
|
81
|
+
<script type="text/javascript">
|
|
82
|
+
(function () {
|
|
83
|
+
function toggleCustomMeterPath() {
|
|
84
|
+
const show = $("#node-input-meterIdSource").val() === "custom";
|
|
85
|
+
$("#node-row-customMeterPath").toggle(show);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function toggleOperationRows() {
|
|
89
|
+
const isExpression = $("#node-input-operation").val() === "expression";
|
|
90
|
+
const isPrimarySecondary = $("#node-input-operation").val() === "primary-secondary";
|
|
91
|
+
$("#node-row-expression").toggle(isExpression);
|
|
92
|
+
$("#node-row-meterOrder").toggle(!isExpression && !isPrimarySecondary);
|
|
93
|
+
$("#node-row-expectedMeterCount").toggle(!isPrimarySecondary);
|
|
94
|
+
$("#node-row-primarySecondaryTimeoutMs").toggle(isPrimarySecondary);
|
|
95
|
+
$("#node-row-primaryMeterId").toggle(isPrimarySecondary);
|
|
96
|
+
$("#node-row-secondaryMeterId").toggle(isPrimarySecondary);
|
|
97
|
+
$("#node-row-failSecureEnabled").toggle(isPrimarySecondary);
|
|
98
|
+
$("#node-row-failSecureTimeSec").toggle(isPrimarySecondary && $("#node-input-failSecureEnabled").is(":checked"));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function normalizeOutputCount(value) {
|
|
102
|
+
const parsed = Number(value);
|
|
103
|
+
if (Number.isFinite(parsed) && parsed >= 1) {
|
|
104
|
+
return Math.max(1, Math.floor(parsed));
|
|
105
|
+
}
|
|
106
|
+
return 4;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function toggleSplitOutputRows() {
|
|
110
|
+
$("#node-row-splitOutputCount").toggle($("#node-input-splitValueOutputs").is(":checked"));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function toggleInfluxRows() {
|
|
114
|
+
const enabled = $("#node-input-influxDb").is(":checked");
|
|
115
|
+
$("#node-row-influxMeasurement,#node-row-influxNode").toggle(enabled);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function populateInfluxNodes(selectedId) {
|
|
119
|
+
const select = $("#node-input-influxNode");
|
|
120
|
+
select.empty().append($("<option></option>").val("").text("Selecteaza adt-influxdb"));
|
|
121
|
+
RED.nodes.eachNode(function (candidate) {
|
|
122
|
+
if (candidate.type !== "adt-influxdb") {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
select.append($("<option></option>")
|
|
126
|
+
.val(candidate.id)
|
|
127
|
+
.text(candidate.name || candidate.label || "adt-influxdb"));
|
|
128
|
+
});
|
|
129
|
+
if (selectedId && !select.find('option[value="' + selectedId + '"]').length) {
|
|
130
|
+
select.append($("<option></option>").val(selectedId).text("InfluxDB indisponibil (" + selectedId + ")"));
|
|
131
|
+
}
|
|
132
|
+
select.val(selectedId || "");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
RED.nodes.registerType("multi-grid", {
|
|
136
|
+
category: "Atelierul de Tehnologii",
|
|
137
|
+
color: "#b7d8ff",
|
|
138
|
+
defaults: {
|
|
139
|
+
license: { value: "", type: "atelier-license", required: true },
|
|
140
|
+
name: { value: "" },
|
|
141
|
+
operation: { value: "sum", required: true },
|
|
142
|
+
expression: {
|
|
143
|
+
value: "",
|
|
144
|
+
validate: function (v) {
|
|
145
|
+
if ($("#node-input-operation").val() !== "expression") {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return !!String(v || "").trim();
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
meterIdSource: { value: "topic", required: true },
|
|
152
|
+
customMeterPath: {
|
|
153
|
+
value: "",
|
|
154
|
+
validate: function (v) {
|
|
155
|
+
if ($("#node-input-meterIdSource").val() !== "custom") {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
return !!String(v || "").trim();
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
meterOrder: {
|
|
162
|
+
value: "",
|
|
163
|
+
validate: function (v) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
primaryMeterId: {
|
|
168
|
+
value: "",
|
|
169
|
+
validate: function (v) {
|
|
170
|
+
if ($("#node-input-operation").val() !== "primary-secondary") {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return !!String(v || "").trim();
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
secondaryMeterId: {
|
|
177
|
+
value: "",
|
|
178
|
+
validate: function (v) {
|
|
179
|
+
if ($("#node-input-operation").val() !== "primary-secondary") {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
const secondary = String(v || "").trim();
|
|
183
|
+
const primary = String($("#node-input-primaryMeterId").val() || "").trim();
|
|
184
|
+
return !!secondary && secondary !== primary;
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
expectedMeterCount: {
|
|
188
|
+
value: 2,
|
|
189
|
+
validate: function (v) {
|
|
190
|
+
return Number(v) >= 0;
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
emitPartial: { value: true },
|
|
194
|
+
valueTimeoutMs: {
|
|
195
|
+
value: 0,
|
|
196
|
+
validate: function (v) {
|
|
197
|
+
return Number(v) >= 0;
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
roundDigits: {
|
|
201
|
+
value: 3,
|
|
202
|
+
validate: function (v) {
|
|
203
|
+
const n = Number(v);
|
|
204
|
+
return Number.isFinite(n) && n >= 0 && n <= 8;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
strictCategoryCheck: { value: true },
|
|
208
|
+
groupByCategory: { value: false },
|
|
209
|
+
missingDataStrategy: { value: "skip", required: true },
|
|
210
|
+
primarySecondaryTimeoutMs: {
|
|
211
|
+
value: 10000,
|
|
212
|
+
validate: function (v) {
|
|
213
|
+
return Number(v) >= 0;
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
failSecureEnabled: { value: false },
|
|
217
|
+
failSecureTimeSec: {
|
|
218
|
+
value: 10,
|
|
219
|
+
validate: function (v) {
|
|
220
|
+
if (!$("#node-input-failSecureEnabled").is(":checked")) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
return Number(v) >= 1;
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
scadaServer: { value: false },
|
|
227
|
+
controlExportReactive: { value: false },
|
|
228
|
+
influxDb: { value: false },
|
|
229
|
+
influxMeasurement: {
|
|
230
|
+
value: "multi_grid",
|
|
231
|
+
validate: function (v) {
|
|
232
|
+
return !$("#node-input-influxDb").is(":checked") || !!String(v || "").trim();
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
influxNode: {
|
|
236
|
+
value: "",
|
|
237
|
+
validate: function (v) {
|
|
238
|
+
return !$("#node-input-influxDb").is(":checked") || !!String(v || "").trim();
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
splitValueOutputs: { value: false },
|
|
242
|
+
splitOutputCount: {
|
|
243
|
+
value: 4,
|
|
244
|
+
validate: function (v) {
|
|
245
|
+
if (!$("#node-input-splitValueOutputs").is(":checked")) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
return normalizeOutputCount(v) >= 1;
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
preserveOriginalMsg: { value: true },
|
|
252
|
+
outputs: { value: 1 }
|
|
253
|
+
},
|
|
254
|
+
inputs: 1,
|
|
255
|
+
outputs: 1,
|
|
256
|
+
icon: "bridge.svg",
|
|
257
|
+
label: function () {
|
|
258
|
+
return this.name || "multi-grid";
|
|
259
|
+
},
|
|
260
|
+
paletteLabel: "multi-grid",
|
|
261
|
+
outputLabels: function (index) {
|
|
262
|
+
const splitOutputs = this.splitValueOutputs === true;
|
|
263
|
+
const count = normalizeOutputCount(this.splitOutputCount);
|
|
264
|
+
const isFailSecure = this.operation === "primary-secondary" && this.failSecureEnabled === true;
|
|
265
|
+
if (splitOutputs && index < count) {
|
|
266
|
+
return "valoare " + (index + 1);
|
|
267
|
+
}
|
|
268
|
+
if (isFailSecure && index === (splitOutputs ? count : 1)) {
|
|
269
|
+
return "fail secure";
|
|
270
|
+
}
|
|
271
|
+
return "payload";
|
|
272
|
+
},
|
|
273
|
+
oneditprepare: function () {
|
|
274
|
+
const node = this;
|
|
275
|
+
function syncOutputs() {
|
|
276
|
+
const isPrimarySecondary = $("#node-input-operation").val() === "primary-secondary";
|
|
277
|
+
const failSecureEnabled = $("#node-input-failSecureEnabled").is(":checked");
|
|
278
|
+
const splitOutputs = $("#node-input-splitValueOutputs").is(":checked");
|
|
279
|
+
const valueOutputCount = splitOutputs ? normalizeOutputCount($("#node-input-splitOutputCount").val()) : 1;
|
|
280
|
+
node.outputs = valueOutputCount + (isPrimarySecondary && failSecureEnabled ? 1 : 0);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
toggleCustomMeterPath();
|
|
284
|
+
toggleOperationRows();
|
|
285
|
+
toggleSplitOutputRows();
|
|
286
|
+
populateInfluxNodes(node.influxNode);
|
|
287
|
+
toggleInfluxRows();
|
|
288
|
+
syncOutputs();
|
|
289
|
+
|
|
290
|
+
$("#node-input-meterIdSource")
|
|
291
|
+
.off(".multiGrid")
|
|
292
|
+
.on("change.multiGrid", function () {
|
|
293
|
+
toggleCustomMeterPath();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
$("#node-input-operation")
|
|
297
|
+
.off(".multiGrid")
|
|
298
|
+
.on("change.multiGrid", function () {
|
|
299
|
+
toggleOperationRows();
|
|
300
|
+
syncOutputs();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
$("#node-input-failSecureEnabled")
|
|
304
|
+
.off(".multiGrid")
|
|
305
|
+
.on("change.multiGrid", function () {
|
|
306
|
+
toggleOperationRows();
|
|
307
|
+
syncOutputs();
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
$("#node-input-splitValueOutputs")
|
|
311
|
+
.off(".multiGrid")
|
|
312
|
+
.on("change.multiGrid", function () {
|
|
313
|
+
toggleSplitOutputRows();
|
|
314
|
+
syncOutputs();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
$("#node-input-splitOutputCount")
|
|
318
|
+
.off(".multiGrid")
|
|
319
|
+
.on("input.multiGrid change.multiGrid", function () {
|
|
320
|
+
syncOutputs();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
$("#node-input-influxDb")
|
|
324
|
+
.off(".multiGrid")
|
|
325
|
+
.on("change.multiGrid", toggleInfluxRows);
|
|
326
|
+
},
|
|
327
|
+
oneditsave: function () {
|
|
328
|
+
const isPrimarySecondary = $("#node-input-operation").val() === "primary-secondary";
|
|
329
|
+
const failSecureEnabled = $("#node-input-failSecureEnabled").is(":checked");
|
|
330
|
+
const splitOutputs = $("#node-input-splitValueOutputs").is(":checked");
|
|
331
|
+
const valueOutputCount = splitOutputs ? normalizeOutputCount($("#node-input-splitOutputCount").val()) : 1;
|
|
332
|
+
this.outputs = valueOutputCount + (isPrimarySecondary && failSecureEnabled ? 1 : 0);
|
|
333
|
+
$("#node-input-meterIdSource").off(".multiGrid");
|
|
334
|
+
$("#node-input-operation").off(".multiGrid");
|
|
335
|
+
$("#node-input-failSecureEnabled").off(".multiGrid");
|
|
336
|
+
$("#node-input-splitValueOutputs").off(".multiGrid");
|
|
337
|
+
$("#node-input-splitOutputCount").off(".multiGrid");
|
|
338
|
+
$("#node-input-influxDb").off(".multiGrid");
|
|
339
|
+
},
|
|
340
|
+
oneditcancel: function () {
|
|
341
|
+
$("#node-input-meterIdSource").off(".multiGrid");
|
|
342
|
+
$("#node-input-operation").off(".multiGrid");
|
|
343
|
+
$("#node-input-failSecureEnabled").off(".multiGrid");
|
|
344
|
+
$("#node-input-splitValueOutputs").off(".multiGrid");
|
|
345
|
+
$("#node-input-splitOutputCount").off(".multiGrid");
|
|
346
|
+
$("#node-input-influxDb").off(".multiGrid");
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
})();
|
|
350
|
+
</script>
|
|
351
|
+
|
|
352
|
+
<script type="text/html" data-template-name="multi-grid">
|
|
353
|
+
<div class="form-row"><label for="node-input-license"><i class="fa fa-key"></i> License</label><input type="text" id="node-input-license"></div>
|
|
354
|
+
<div class="multi-grid-editor">
|
|
355
|
+
<div class="mg-hero">
|
|
356
|
+
<p class="mg-title">Grid Aggregator</p>
|
|
357
|
+
<p class="mg-note">Agrega mesaje compacte numerice de la mai multe metere si livreaza un singur <code>payload</code> usor de folosit in <code>bess-control</code>. Functioneaza cel mai bine cu noduri <code>carlo-gavazzi</code> configurate in modul <code>Multi-grid</code>.</p>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<div class="mg-section">
|
|
361
|
+
<p class="mg-title">Aggregation</p>
|
|
362
|
+
<p class="mg-note">Alege operatia, expresia optionala si cate metere astepti in calcul.</p>
|
|
363
|
+
<div class="mg-grid">
|
|
364
|
+
<div class="form-row">
|
|
365
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
366
|
+
<input type="text" id="node-input-name" placeholder="multi-grid">
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<div class="form-row">
|
|
370
|
+
<label for="node-input-operation"><i class="fa fa-calculator"></i> Operație</label>
|
|
371
|
+
<select id="node-input-operation">
|
|
372
|
+
<option value="sum">Adunare</option>
|
|
373
|
+
<option value="subtract">Scădere</option>
|
|
374
|
+
<option value="min">Minim</option>
|
|
375
|
+
<option value="max">Maxim</option>
|
|
376
|
+
<option value="avg">Medie</option>
|
|
377
|
+
<option value="expression">Expresie</option>
|
|
378
|
+
<option value="primary-secondary">Principal / secundar</option>
|
|
379
|
+
</select>
|
|
380
|
+
</div>
|
|
381
|
+
|
|
382
|
+
<div class="form-row" id="node-row-expression">
|
|
383
|
+
<label for="node-input-expression"><i class="fa fa-code"></i> Expresie</label>
|
|
384
|
+
<input type="text" id="node-input-expression" placeholder="meter1+meter2-meter3">
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
<div class="form-row" id="node-row-expectedMeterCount">
|
|
388
|
+
<label for="node-input-expectedMeterCount"><i class="fa fa-hashtag"></i> Nr. metere</label>
|
|
389
|
+
<input type="number" id="node-input-expectedMeterCount" min="0">
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
<div class="form-row" id="node-row-meterOrder">
|
|
393
|
+
<label for="node-input-meterOrder"><i class="fa fa-sort"></i> Ordine metere</label>
|
|
394
|
+
<input type="text" id="node-input-meterOrder" placeholder="meter1,meter2,meter3">
|
|
395
|
+
</div>
|
|
396
|
+
|
|
397
|
+
<div class="form-row" id="node-row-primaryMeterId">
|
|
398
|
+
<label for="node-input-primaryMeterId"><i class="fa fa-star"></i> Meter principal</label>
|
|
399
|
+
<input type="text" id="node-input-primaryMeterId" placeholder="meter-main">
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
<div class="form-row" id="node-row-secondaryMeterId">
|
|
403
|
+
<label for="node-input-secondaryMeterId"><i class="fa fa-life-ring"></i> Meter secundar</label>
|
|
404
|
+
<input type="text" id="node-input-secondaryMeterId" placeholder="meter-backup">
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<div class="form-row" id="node-row-primarySecondaryTimeoutMs">
|
|
408
|
+
<label for="node-input-primarySecondaryTimeoutMs"><i class="fa fa-random"></i> Timeout principal ms</label>
|
|
409
|
+
<input type="number" id="node-input-primarySecondaryTimeoutMs" min="0" placeholder="10000">
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<div class="form-row mg-checkbox-row" id="node-row-failSecureEnabled">
|
|
413
|
+
<label for="node-input-failSecureEnabled"><i class="fa fa-exclamation-triangle"></i> Fail Secure</label>
|
|
414
|
+
<input type="checkbox" id="node-input-failSecureEnabled">
|
|
415
|
+
<span class="mg-inline-note">Activeaza iesirea 2 pentru semnalizarea indisponibilitatii principale.</span>
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
<div class="form-row" id="node-row-failSecureTimeSec">
|
|
419
|
+
<label for="node-input-failSecureTimeSec"><i class="fa fa-clock-o"></i> Fail Secure Time (s)</label>
|
|
420
|
+
<input type="number" id="node-input-failSecureTimeSec" min="1" placeholder="10">
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div class="form-row">
|
|
424
|
+
<label for="node-input-roundDigits"><i class="fa fa-bullseye"></i> Zecimale</label>
|
|
425
|
+
<input type="number" id="node-input-roundDigits" min="0" max="8">
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
<div class="mg-section">
|
|
431
|
+
<p class="mg-title">Meter Identification</p>
|
|
432
|
+
<p class="mg-note">Configureaza de unde citeste nodul identitatea fiecarui meter.</p>
|
|
433
|
+
<div class="mg-grid">
|
|
434
|
+
<div class="form-row">
|
|
435
|
+
<label for="node-input-meterIdSource"><i class="fa fa-id-badge"></i> Meter ID din</label>
|
|
436
|
+
<select id="node-input-meterIdSource">
|
|
437
|
+
<option value="topic">msg.topic</option>
|
|
438
|
+
<option value="meterId">msg.meterId</option>
|
|
439
|
+
<option value="meter_id">msg.meter_id</option>
|
|
440
|
+
<option value="payload.meterId">msg.payload.meterId</option>
|
|
441
|
+
<option value="custom">Cale custom</option>
|
|
442
|
+
</select>
|
|
443
|
+
</div>
|
|
444
|
+
|
|
445
|
+
<div class="form-row" id="node-row-customMeterPath">
|
|
446
|
+
<label for="node-input-customMeterPath"><i class="fa fa-code"></i> Cale custom</label>
|
|
447
|
+
<input type="text" id="node-input-customMeterPath" placeholder="data.meter.id">
|
|
448
|
+
</div>
|
|
449
|
+
|
|
450
|
+
<div class="form-row">
|
|
451
|
+
<label for="node-input-missingDataStrategy"><i class="fa fa-life-ring"></i> Date lipsă</label>
|
|
452
|
+
<select id="node-input-missingDataStrategy">
|
|
453
|
+
<option value="skip">Skip</option>
|
|
454
|
+
<option value="zero-fill">Zero-fill</option>
|
|
455
|
+
<option value="use-last">Use-last</option>
|
|
456
|
+
</select>
|
|
457
|
+
</div>
|
|
458
|
+
</div>
|
|
459
|
+
</div>
|
|
460
|
+
|
|
461
|
+
<div class="mg-section">
|
|
462
|
+
<p class="mg-title">Behavior</p>
|
|
463
|
+
<p class="mg-note">Aici controlezi cat de strict este agregatorul si cat context pastreaza din mesajele originale.</p>
|
|
464
|
+
|
|
465
|
+
<div class="form-row mg-checkbox-row">
|
|
466
|
+
<label for="node-input-emitPartial"><i class="fa fa-check-square-o"></i> Emitere parțială</label>
|
|
467
|
+
<input type="checkbox" id="node-input-emitPartial">
|
|
468
|
+
<span class="mg-inline-note">Permite iesire chiar daca nu au sosit toate meterele asteptate.</span>
|
|
469
|
+
</div>
|
|
470
|
+
|
|
471
|
+
<div class="form-row mg-checkbox-row">
|
|
472
|
+
<label for="node-input-strictCategoryCheck"><i class="fa fa-exclamation-triangle"></i> Check categorii</label>
|
|
473
|
+
<input type="checkbox" id="node-input-strictCategoryCheck">
|
|
474
|
+
<span class="mg-inline-note">Blocheaza combinarea payload-urilor din categorii incompatibile.</span>
|
|
475
|
+
</div>
|
|
476
|
+
|
|
477
|
+
<div class="form-row mg-checkbox-row">
|
|
478
|
+
<label for="node-input-groupByCategory"><i class="fa fa-object-group"></i> Agregare categorii</label>
|
|
479
|
+
<input type="checkbox" id="node-input-groupByCategory">
|
|
480
|
+
<span class="mg-inline-note">Grupeaza rezultatele pe categorii, nu pe fiecare cheie numerica.</span>
|
|
481
|
+
</div>
|
|
482
|
+
|
|
483
|
+
<div class="form-row mg-checkbox-row">
|
|
484
|
+
<label for="node-input-scadaServer"><i class="fa fa-server"></i> SCADA server</label>
|
|
485
|
+
<input type="checkbox" id="node-input-scadaServer">
|
|
486
|
+
<span class="mg-inline-note">Formateaza topic-ul si cheile de iesire pentru integrarea directa cu nodul <code>scada-server</code>.</span>
|
|
487
|
+
</div>
|
|
488
|
+
|
|
489
|
+
<div class="form-row mg-checkbox-row">
|
|
490
|
+
<label for="node-input-controlExportReactive"><i class="fa fa-bolt"></i> Control export/reactive</label>
|
|
491
|
+
<input type="checkbox" id="node-input-controlExportReactive">
|
|
492
|
+
<span class="mg-inline-note">Adauga aliasuri de payload compatibile cu nodurile <code>control-export</code> si <code>control-reactive</code>.</span>
|
|
493
|
+
</div>
|
|
494
|
+
|
|
495
|
+
<div class="form-row mg-checkbox-row">
|
|
496
|
+
<label for="node-input-influxDb"><i class="fa fa-database"></i> InfluxDB</label>
|
|
497
|
+
<input type="checkbox" id="node-input-influxDb">
|
|
498
|
+
<span class="mg-inline-note">Pregateste valorile agregate in <code>msg.influx</code> pentru nodul <code>adt-influxdb</code>.</span>
|
|
499
|
+
</div>
|
|
500
|
+
|
|
501
|
+
<div class="form-row" id="node-row-influxMeasurement">
|
|
502
|
+
<label for="node-input-influxMeasurement"><i class="fa fa-line-chart"></i> Measurement</label>
|
|
503
|
+
<input type="text" id="node-input-influxMeasurement" placeholder="multi_grid">
|
|
504
|
+
</div>
|
|
505
|
+
|
|
506
|
+
<div class="form-row" id="node-row-influxNode">
|
|
507
|
+
<label for="node-input-influxNode"><i class="fa fa-plug"></i> Nod InfluxDB</label>
|
|
508
|
+
<select id="node-input-influxNode"></select>
|
|
509
|
+
</div>
|
|
510
|
+
|
|
511
|
+
<div class="form-row mg-checkbox-row">
|
|
512
|
+
<label for="node-input-splitValueOutputs"><i class="fa fa-share-alt"></i> Iesiri separate</label>
|
|
513
|
+
<input type="checkbox" id="node-input-splitValueOutputs">
|
|
514
|
+
<span class="mg-inline-note">Trimite fiecare valoare agregata pe iesirea ei, in loc de un singur obiect.</span>
|
|
515
|
+
</div>
|
|
516
|
+
|
|
517
|
+
<div class="form-row" id="node-row-splitOutputCount">
|
|
518
|
+
<label for="node-input-splitOutputCount"><i class="fa fa-list-ol"></i> Numar iesiri</label>
|
|
519
|
+
<input type="number" id="node-input-splitOutputCount" min="1" step="1" placeholder="4">
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
<div class="form-row mg-checkbox-row">
|
|
523
|
+
<label for="node-input-preserveOriginalMsg"><i class="fa fa-clone"></i> Păstrează msg</label>
|
|
524
|
+
<input type="checkbox" id="node-input-preserveOriginalMsg">
|
|
525
|
+
<span class="mg-inline-note">Pastreaza campurile originale si adauga peste ele rezultatul agregat.</span>
|
|
526
|
+
</div>
|
|
527
|
+
|
|
528
|
+
<div class="mg-grid" style="margin-top:12px;">
|
|
529
|
+
<div class="form-row">
|
|
530
|
+
<label for="node-input-valueTimeoutMs"><i class="fa fa-clock-o"></i> Timeout ms</label>
|
|
531
|
+
<input type="number" id="node-input-valueTimeoutMs" min="0" placeholder="0">
|
|
532
|
+
</div>
|
|
533
|
+
</div>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
</script>
|
|
537
|
+
|
|
538
|
+
<script type="text/html" data-help-name="multi-grid">
|
|
539
|
+
<p>Nod pentru agregarea valorilor numerice primite de la mai multe metere într-un singur obiect <code>msg.payload</code>.</p>
|
|
540
|
+
<p>Flux recomandat: <code>carlo-gavazzi (Multi-grid) -> multi-grid -> bess-control</code>.</p>
|
|
541
|
+
|
|
542
|
+
<h3>Parametri</h3>
|
|
543
|
+
|
|
544
|
+
<p><b>Name</b><br>
|
|
545
|
+
Numele afișat sub nod în editorul Node-RED. Dacă îl lași gol, nodul va afișa numele implicit <code>multi-grid</code>.</p>
|
|
546
|
+
|
|
547
|
+
<p><b>Operație</b><br>
|
|
548
|
+
Definește modul în care sunt combinate valorile primite de la metere.</p>
|
|
549
|
+
<ul>
|
|
550
|
+
<li><code>Adunare</code> – adună valorile.</li>
|
|
551
|
+
<li><code>Scădere</code> – scade valorile în ordinea meterelor.</li>
|
|
552
|
+
<li><code>Minim</code> – alege valoarea minimă.</li>
|
|
553
|
+
<li><code>Maxim</code> – alege valoarea maximă.</li>
|
|
554
|
+
<li><code>Medie</code> – calculează media.</li>
|
|
555
|
+
<li><code>Expresie</code> – permite o formulă explicită, de exemplu <code>meter1+meter2-meter3</code>.</li>
|
|
556
|
+
<li><code>Principal / secundar</code> – folosește valorile meterului principal, iar dacă principalul nu mai trimite date (timeout), comută automat pe secundar.</li>
|
|
557
|
+
</ul>
|
|
558
|
+
|
|
559
|
+
<p><b>Expresie</b><br>
|
|
560
|
+
Este folosită doar când la <code>Operație</code> este selectat <code>Expresie</code>.<br>
|
|
561
|
+
Exemplu: <code>meter1+meter2-meter3</code>.</p>
|
|
562
|
+
|
|
563
|
+
<p><b>Meter ID din</b><br>
|
|
564
|
+
Spune nodului de unde citește identificatorul fiecărui meter.</p>
|
|
565
|
+
|
|
566
|
+
<p><b>Cale custom</b><br>
|
|
567
|
+
Este folosită doar când la <code>Meter ID din</code> alegi <code>Cale custom</code>.</p>
|
|
568
|
+
|
|
569
|
+
<p><b>Nr. metere</b><br>
|
|
570
|
+
Numărul de metere așteptate în calcul.</p>
|
|
571
|
+
|
|
572
|
+
<p><b>Emitere parțială</b><br>
|
|
573
|
+
Dacă este activă, nodul poate emite rezultat chiar dacă nu au sosit încă toate meterele configurate.</p>
|
|
574
|
+
|
|
575
|
+
<p><b>Ordine metere</b><br>
|
|
576
|
+
Definește ordinea meterelor. Este importantă în special la operația <code>Scădere</code>.</p>
|
|
577
|
+
|
|
578
|
+
<p><b>Meter principal / Meter secundar</b><br>
|
|
579
|
+
Câmpuri dedicate pentru modul <code>Principal / secundar</code>. Aceste ID-uri sunt folosite cu prioritate.</p>
|
|
580
|
+
|
|
581
|
+
<p><b>Timeout principal ms</b><br>
|
|
582
|
+
Este folosit doar la <code>Principal / secundar</code>. Dacă principalul nu mai trimite date în acest interval, nodul transmite valorile din secundar.</p>
|
|
583
|
+
|
|
584
|
+
<p><b>Fail Secure</b><br>
|
|
585
|
+
Activează ieșirea 2 doar în modul <code>Principal / secundar</code>.</p>
|
|
586
|
+
|
|
587
|
+
<p><b>Fail Secure Time (s)</b><br>
|
|
588
|
+
Intervalul minim cât principalul trebuie să rămână inactiv înainte ca ieșirea 2 să trimită <code>payload=1</code>.</p>
|
|
589
|
+
|
|
590
|
+
<p><b>Timeout ms</b><br>
|
|
591
|
+
Timpul maxim în milisecunde cât este păstrată ultima valoare a unui meter în memorie.</p>
|
|
592
|
+
|
|
593
|
+
<p><b>Zecimale</b><br>
|
|
594
|
+
Numărul de zecimale folosit la rotunjirea valorilor de ieșire.</p>
|
|
595
|
+
|
|
596
|
+
<p><b>Check categorii</b><br>
|
|
597
|
+
Verifică dacă meterele folosite în calcul trimit date din aceeași categorie.</p>
|
|
598
|
+
|
|
599
|
+
<p><b>Agregare categorii</b><br>
|
|
600
|
+
Dacă este dezactivată, nodul face agregarea pe fiecare cheie în parte, de exemplu <code>voltage_l1_n_v</code> cu <code>voltage_l1_n_v</code>.<br>
|
|
601
|
+
Dacă este activată, nodul grupează valorile pe categorii și întoarce un singur rezultat pe categorie, de exemplu <code>voltage</code>, <code>current</code>, <code>power</code>.</p>
|
|
602
|
+
|
|
603
|
+
<p><b>Date lipsă</b><br>
|
|
604
|
+
Alege cum tratează nodul valorile lipsă din payload:</p>
|
|
605
|
+
<ul>
|
|
606
|
+
<li><code>Skip</code> – ignoră valorile lipsă și agregă doar valorile existente.</li>
|
|
607
|
+
<li><code>Zero-fill</code> – completează valorile lipsă cu <code>0</code> înainte de agregare.</li>
|
|
608
|
+
<li><code>Use-last</code> – păstrează ultima valoare numerică validă pe fiecare cheie și meter.</li>
|
|
609
|
+
</ul>
|
|
610
|
+
|
|
611
|
+
<p><b>SCADA server</b><br>
|
|
612
|
+
Dacă este activată, nodul setează <code>msg.topic = "scada-server"</code> și normalizează câmpurile agregate pentru maparea implicită din <code>scada-server</code> (de exemplu <code>active_power_w</code>, <code>reactive_power_var</code>, <code>frequency_hz</code>, <code>voltage_l1_l2_v</code>, <code>voltage_l2_l3_v</code>, <code>voltage_l1_l3_v</code>).</p>
|
|
613
|
+
|
|
614
|
+
<p><b>Control export/reactive</b><br>
|
|
615
|
+
Daca este activata, nodul pastreaza valorile originale si adauga aliasuri compatibile cu <code>control-export</code> si <code>control-reactive</code>. De exemplu, <code>power_total_w</code> este expus si ca <code>power_w</code>, <code>active_power_w</code> si <code>grid_reference_w</code>, iar <code>reactive_total_var</code> este expus si ca <code>reactive_power_var</code> si <code>grid_reactive_power_var</code>.</p>
|
|
616
|
+
|
|
617
|
+
<p><b>InfluxDB</b><br>
|
|
618
|
+
Cand este activat, nodul trimite intern o copie separata catre nodul <code>adt-influxdb</code> selectat, cu tag-uri filtrabile pentru <code>meter_ids</code>, <code>meter_ips</code>, <code>unit_ids</code>, <code>device_types</code>, <code>meter_models</code>, numarul de metere si operatie. Iesirea principala ramane neschimbata si nu contine <code>msg.influx</code>.</p>
|
|
619
|
+
|
|
620
|
+
<p><b>Iesiri separate</b><br>
|
|
621
|
+
Daca este dezactivata, nodul trimite toate valorile agregate intr-un singur obiect <code>msg.payload</code>, pe iesirea 1.<br>
|
|
622
|
+
Daca este activata, nodul trimite fiecare valoare pe iesirea ei separata. Implicit sunt configurate 4 iesiri.</p>
|
|
623
|
+
|
|
624
|
+
<p><b>Numar iesiri</b><br>
|
|
625
|
+
Seteaza cate valori vrei trimise pe iesiri separate. Numele valorilor raman cheile din mesajul agregat, in ordinea in care apar in payload. In modul <code>Principal / secundar</code> cu <b>Fail Secure</b> activ, iesirea de fail secure este adaugata dupa iesirile de valori.</p>
|
|
626
|
+
|
|
627
|
+
<p><b>Compatibilitate</b><br>
|
|
628
|
+
Pentru integrarea cu <code>bess-control</code>, este recomandat ca fiecare meter sursă să trimită valori compacte precum <code>power_w</code>, <code>power_l1_w</code>, <code>power_l2_w</code>, <code>power_l3_w</code>.</p>
|
|
629
|
+
|
|
630
|
+
<p>Exemple cu <code>Agregare categorii</code> activă:</p>
|
|
631
|
+
<ul>
|
|
632
|
+
<li>la <code>max</code> pentru <code>voltage_l1_n_v</code>, <code>voltage_l2_n_v</code>, <code>voltage_l3_n_v</code> rezultatul poate fi <code>{ "voltage": 241.2 }</code></li>
|
|
633
|
+
<li>la <code>sum</code> va aduna toate valorile din categoria respectivă, inclusiv între metere</li>
|
|
634
|
+
</ul>
|
|
635
|
+
|
|
636
|
+
<p><b>Păstrează msg</b><br>
|
|
637
|
+
Dacă este activă, nodul păstrează celelalte proprietăți existente din <code>msg</code> și înlocuiește doar câmpurile relevante pentru rezultat.</p>
|
|
638
|
+
|
|
639
|
+
<h3>Intrare</h3>
|
|
640
|
+
<pre>{
|
|
641
|
+
"topic": "meter1",
|
|
642
|
+
"payload": {
|
|
643
|
+
"voltage_l1_n_v": 230.1,
|
|
644
|
+
"voltage_l2_n_v": 231.4,
|
|
645
|
+
"voltage_l3_n_v": 229.8
|
|
646
|
+
}
|
|
647
|
+
}</pre>
|
|
648
|
+
|
|
649
|
+
<h3>Ieșire</h3>
|
|
650
|
+
<p>Rezultatul este emis în <code>msg.payload</code>.</p>
|
|
651
|
+
<p>În modul <code>Principal / secundar</code>, nodul are 2 ieșiri:</p>
|
|
652
|
+
<ul>
|
|
653
|
+
<li>ieșirea 1: payload-ul meterului selectat (principal sau fallback secundar)</li>
|
|
654
|
+
<li>ieșirea 2 (doar cu <code>Fail Secure</code> activ): semnal stare principal, cu <code>payload=1</code> după timpul de declanșare și <code>payload=0</code> când principalul este activ</li>
|
|
655
|
+
</ul>
|
|
656
|
+
<p>În plus, nodul mai adaugă:</p>
|
|
657
|
+
<ul>
|
|
658
|
+
<li><code>msg.topic</code></li>
|
|
659
|
+
<li><code>msg.operation</code></li>
|
|
660
|
+
<li><code>msg.expression</code></li>
|
|
661
|
+
<li><code>msg.meter_count</code></li>
|
|
662
|
+
<li><code>msg.meter_ids</code></li>
|
|
663
|
+
<li><code>msg.parts</code></li>
|
|
664
|
+
<li><code>msg.updated_meter_id</code></li>
|
|
665
|
+
<li><code>msg.categories</code></li>
|
|
666
|
+
<li><code>msg.group_by_category</code></li>
|
|
667
|
+
</ul>
|
|
668
|
+
|
|
669
|
+
<h3>Referinta completa parametri</h3>
|
|
670
|
+
<ul>
|
|
671
|
+
<li><code>operation</code>: selecteaza calculul: suma, diferenta, medie, expresie sau principal/secundar.</li>
|
|
672
|
+
<li><code>expression</code>: formula custom folosita in modul expresie.</li>
|
|
673
|
+
<li><code>meterIdSource</code>: sursa ID-ului de meter: topic, camp standard sau cale custom.</li>
|
|
674
|
+
<li><code>customMeterPath</code>: calea custom pentru ID-ul de meter.</li>
|
|
675
|
+
<li><code>meterOrder</code>: ordinea meterelor in calcule si expresii.</li>
|
|
676
|
+
<li><code>primaryMeterId</code> si <code>secondaryMeterId</code>: meterul principal si fallback-ul din modul principal/secundar.</li>
|
|
677
|
+
<li><code>expectedMeterCount</code>: cate metere sunt asteptate pentru un snapshot complet.</li>
|
|
678
|
+
<li><code>emitPartial</code>: permite emiterea rezultatului chiar daca nu toate meterele sunt prezente.</li>
|
|
679
|
+
<li><code>valueTimeoutMs</code>: varsta maxima a unei valori in calculul agregat.</li>
|
|
680
|
+
<li><code>roundDigits</code>: rotunjirea valorilor numerice emise.</li>
|
|
681
|
+
<li><code>strictCategoryCheck</code>: cere categorii compatibile intre metere.</li>
|
|
682
|
+
<li><code>groupByCategory</code>: grupeaza rezultatele pe categorii de masura.</li>
|
|
683
|
+
<li><code>missingDataStrategy</code>: decide ce se intampla cand lipsesc date.</li>
|
|
684
|
+
<li><code>primarySecondaryTimeoutMs</code>: timpul dupa care se trece pe meterul secundar.</li>
|
|
685
|
+
<li><code>failSecureEnabled</code> si <code>failSecureTimeSec</code>: activeaza iesirea de fail secure pentru pierderea meterului principal.</li>
|
|
686
|
+
<li><code>scadaServer</code>: pregateste payload compatibil cu <code>scada-server</code>.</li>
|
|
687
|
+
<li><code>controlExportReactive</code>: adauga aliasuri compatibile cu <code>control-export</code> si <code>control-reactive</code>.</li>
|
|
688
|
+
<li><code>influxDb</code>, <code>influxMeasurement</code> si <code>influxNode</code>: activeaza formatul <code>msg.influx</code>, seteaza measurement-ul si optional nodul InfluxDB destinatie.</li>
|
|
689
|
+
<li><code>splitValueOutputs</code> si <code>splitOutputCount</code>: trimit valorile agregate pe iesiri separate.</li>
|
|
690
|
+
<li><code>preserveOriginalMsg</code>: pastreaza campurile originale din <code>msg</code>.</li>
|
|
691
|
+
<li><code>outputs</code>: numarul de iesiri calculat in functie de iesiri separate si fail secure.</li>
|
|
692
|
+
</ul>
|
|
693
|
+
|
|
694
|
+
<h3>Model principal/secundar</h3>
|
|
695
|
+
<pre>meter principal -> multi-grid -> control-export
|
|
696
|
+
meter secundar ---^</pre>
|
|
697
|
+
</script>
|
|
698
|
+
|
|
699
|
+
<style>
|
|
700
|
+
.multi-grid-form {
|
|
701
|
+
padding-top: 4px;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.multi-grid-form .form-row {
|
|
705
|
+
margin-bottom: 12px;
|
|
706
|
+
display: flex;
|
|
707
|
+
align-items: center;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.multi-grid-form label {
|
|
711
|
+
width: 180px !important;
|
|
712
|
+
font-weight: 400;
|
|
713
|
+
color: #444;
|
|
714
|
+
line-height: 1.35;
|
|
715
|
+
margin-bottom: 0;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.multi-grid-form input[type="text"],
|
|
719
|
+
.multi-grid-form input[type="number"],
|
|
720
|
+
.multi-grid-form select {
|
|
721
|
+
width: calc(100% - 190px) !important;
|
|
722
|
+
min-height: 38px;
|
|
723
|
+
box-sizing: border-box;
|
|
724
|
+
border-radius: 8px;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.multi-grid-form input[type="checkbox"] {
|
|
728
|
+
width: auto !important;
|
|
729
|
+
transform: scale(1.12);
|
|
730
|
+
margin-left: 0;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.multi-grid-form .form-row i.fa {
|
|
734
|
+
width: 16px;
|
|
735
|
+
text-align: center;
|
|
736
|
+
margin-right: 4px;
|
|
737
|
+
color: #4d4d4d;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
#node-row-expression input,
|
|
741
|
+
#node-row-meterOrder input,
|
|
742
|
+
#node-row-customMeterPath input {
|
|
743
|
+
font-family: monospace;
|
|
744
|
+
}
|
|
745
|
+
</style>
|