@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,1789 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
|
|
3
|
+
const FRONIUS_WRITE_MAX_NOMINAL_POWER_W = 125000;
|
|
4
|
+
|
|
5
|
+
function froniusWriteIsBlank(value) {
|
|
6
|
+
return value === undefined || value === null || String(value).trim() === "";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function froniusWriteOptionalNumber(value, min, max) {
|
|
10
|
+
if (froniusWriteIsBlank(value)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const n = Number(value);
|
|
15
|
+
|
|
16
|
+
if (!Number.isFinite(n) || n < min) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return max === undefined || n <= max;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
RED.nodes.registerType("fronius-write", {
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
category: "Atelierul de Tehnologii",
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
color: "#e67700",
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
defaults: {
|
|
33
|
+
license: { value: "", type: "atelier-license", required: true },
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
name: { value: "" },
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
host: { value: "", required: true },
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
port: { value: 502, required: true, validate: RED.validators.number() },
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
unitId: { value: 1, required: true, validate: RED.validators.number() },
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
powerType: { value: "active" },
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
mode: { value: "watts" },
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
maxPower: {
|
|
55
|
+
value: 25000,
|
|
56
|
+
validate: function (v) {
|
|
57
|
+
if (froniusWriteIsBlank(v)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const n = Number(v);
|
|
62
|
+
return Number.isFinite(n) && n > 0 && n <= FRONIUS_WRITE_MAX_NOMINAL_POWER_W;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
latencyTargetMs: {
|
|
67
|
+
value: 200,
|
|
68
|
+
validate: function (v) {
|
|
69
|
+
return froniusWriteOptionalNumber(v, 1);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
maxCommandAgeMs: {
|
|
74
|
+
value: 1000,
|
|
75
|
+
validate: function (v) {
|
|
76
|
+
return froniusWriteOptionalNumber(v, 50);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
disableReadbackVerification: { value: false },
|
|
81
|
+
|
|
82
|
+
nominalPower: {
|
|
83
|
+
|
|
84
|
+
value: 25000,
|
|
85
|
+
|
|
86
|
+
validate: function (v) {
|
|
87
|
+
|
|
88
|
+
if (froniusWriteIsBlank(v)) {
|
|
89
|
+
|
|
90
|
+
return true;
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const nominal = Number(v);
|
|
95
|
+
|
|
96
|
+
const maxPower = Number($("#node-input-maxPower").val());
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if (!Number.isFinite(nominal) || nominal <= 0) {
|
|
100
|
+
|
|
101
|
+
return false;
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (nominal > FRONIUS_WRITE_MAX_NOMINAL_POWER_W) {
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
return true;
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
nominalReactivePower: {
|
|
120
|
+
value: 25000,
|
|
121
|
+
validate: function (v) {
|
|
122
|
+
if (froniusWriteIsBlank(v)) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const n = Number(v);
|
|
127
|
+
return Number.isFinite(n) && n > 0 && n <= FRONIUS_WRITE_MAX_NOMINAL_POWER_W;
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
rampType: { value: "none" },
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
rampTime: {
|
|
136
|
+
value: 0,
|
|
137
|
+
validate: function (v) {
|
|
138
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
rampGradientPct: {
|
|
144
|
+
value: 10,
|
|
145
|
+
validate: function (v) {
|
|
146
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
rampGradientWatts: {
|
|
152
|
+
value: 2500,
|
|
153
|
+
validate: function (v) {
|
|
154
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
rampGradientVars: {
|
|
160
|
+
value: 2500,
|
|
161
|
+
validate: function (v) {
|
|
162
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
rampUpValue: {
|
|
168
|
+
value: 0,
|
|
169
|
+
validate: function (v) {
|
|
170
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
rampDownValue: {
|
|
176
|
+
value: 0,
|
|
177
|
+
validate: function (v) {
|
|
178
|
+
return froniusWriteOptionalNumber(v, 0);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
multiInverter: { value: false },
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
inverterId: {
|
|
187
|
+
|
|
188
|
+
value: "",
|
|
189
|
+
|
|
190
|
+
validate: function (v) {
|
|
191
|
+
|
|
192
|
+
const isMulti = $("#node-input-multiInverter").is(":checked");
|
|
193
|
+
|
|
194
|
+
return !isMulti || !!String(v || "").trim();
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
inputs: 1,
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
outputs: 1,
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
icon: "font-awesome/fa-sliders",
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
label: function () {
|
|
214
|
+
|
|
215
|
+
const baseLabel = this.name || this.host || "fronius-write";
|
|
216
|
+
|
|
217
|
+
if (this.multiInverter && this.inverterId) {
|
|
218
|
+
|
|
219
|
+
const suffix = " [" + this.inverterId + "]";
|
|
220
|
+
|
|
221
|
+
if (baseLabel.indexOf(suffix) !== -1) {
|
|
222
|
+
|
|
223
|
+
return baseLabel;
|
|
224
|
+
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return baseLabel + " [" + this.inverterId + "]";
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return baseLabel;
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
oneditprepare: function () {
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
const node = this;
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
function normalizePowerType(value) {
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
return value === "reactive" ? "reactive" : "active";
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
function normalizeMode(powerType, mode) {
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
if (powerType === "reactive") {
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if (mode === "vars" || mode === "percent") return mode;
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
return "vars";
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
if (mode === "watts" || mode === "percent") return mode;
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
return "watts";
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
function normalizeInverterId(value) {
|
|
280
|
+
|
|
281
|
+
return String(value || "").trim();
|
|
282
|
+
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
function ensureNumberInput(selector, fallback) {
|
|
287
|
+
|
|
288
|
+
const value = String($(selector).val() || "").trim();
|
|
289
|
+
|
|
290
|
+
if (!Number.isFinite(Number(value))) {
|
|
291
|
+
|
|
292
|
+
$(selector).val(fallback);
|
|
293
|
+
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
function buildAutoName() {
|
|
300
|
+
|
|
301
|
+
const host = ($("#node-input-host").val() || "").trim();
|
|
302
|
+
|
|
303
|
+
const isMulti = $("#node-input-multiInverter").is(":checked");
|
|
304
|
+
|
|
305
|
+
const inverterId = normalizeInverterId($("#node-input-inverterId").val());
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
if (!isMulti || !inverterId) {
|
|
309
|
+
|
|
310
|
+
return host;
|
|
311
|
+
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
return host ? (host + " [" + inverterId + "]") : inverterId;
|
|
316
|
+
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const savedAutoName = node.host && node.inverterId
|
|
320
|
+
? node.host + " [" + node.inverterId + "]"
|
|
321
|
+
: "";
|
|
322
|
+
let autoNameEnabled = !node.name || node.name === node.host || node.name === savedAutoName || node.name === "fronius-write";
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
function toggleMultiInverterFields() {
|
|
326
|
+
|
|
327
|
+
const enabled = $("#node-input-multiInverter").is(":checked");
|
|
328
|
+
|
|
329
|
+
$("#row-inverter-id").toggle(enabled);
|
|
330
|
+
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
function applyRuntimeDefaults(state) {
|
|
335
|
+
|
|
336
|
+
if (!state || state.status !== "ok") return;
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
const runtimePowerType = normalizePowerType(state.power_type);
|
|
340
|
+
|
|
341
|
+
const runtimeMode = normalizeMode(runtimePowerType, state.mode);
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
$("#node-input-powerType").val(runtimePowerType);
|
|
345
|
+
|
|
346
|
+
rebuildModeOptions(runtimeMode);
|
|
347
|
+
|
|
348
|
+
toggleFields();
|
|
349
|
+
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
function loadRuntimeState() {
|
|
354
|
+
|
|
355
|
+
if (!node.id) return;
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
$.getJSON("fronius-write/state/" + encodeURIComponent(node.id))
|
|
359
|
+
|
|
360
|
+
.done(function (res) {
|
|
361
|
+
|
|
362
|
+
if (res && res.ok && res.state) {
|
|
363
|
+
|
|
364
|
+
applyRuntimeDefaults(res.state);
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
function rebuildModeOptions(preferredMode) {
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
const powerType = normalizePowerType($("#node-input-powerType").val());
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
const $mode = $("#node-input-mode");
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
const modeToApply = normalizeMode(powerType, preferredMode || $mode.val());
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
$mode.empty();
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
if (powerType === "reactive") {
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
$mode.append('<option value="vars">Fixed Reactive Power (VAr)</option>');
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
$mode.append('<option value="percent">Percent (%)</option>');
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
} else {
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
$mode.append('<option value="watts">Fixed Power (W)</option>');
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
$mode.append('<option value="percent">Percent (%)</option>');
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
$mode.val(modeToApply);
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
function toggleFields() {
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
const powerType = normalizePowerType($("#node-input-powerType").val());
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
const rampType = $("#node-input-rampType").val();
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
const showNominalForRamp = rampType === "gradient_pct" || rampType === "gradient_w";
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
const showMaxPower = powerType === "active";
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
const showNominalPower =
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
powerType === "active" && showNominalForRamp;
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
const showNominalReactivePower =
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
powerType === "reactive" && showNominalForRamp;
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
$("#row-nominal-power").toggle(showMaxPower);
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
$("#row-ramp-nominal-power").toggle(showNominalPower);
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
$("#row-nominal-reactive-power").toggle(showNominalReactivePower);
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
$("#row-ramp-up-value").hide();
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
$("#row-ramp-down-value").hide();
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
if (rampType !== "none") {
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
let rampLabel = "Ramp Value";
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
if (rampType === "time") {
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
rampLabel = "Ramp Time (s)";
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
} else if (rampType === "gradient_pct") {
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
rampLabel = "Ramp Gradient (%/s)";
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
} else if (rampType === "gradient_w") {
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
rampLabel = powerType === "reactive" ? "Ramp Gradient (VAr/s)" : "Ramp Gradient (W/s)";
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
$("#node-label-rampUpValue").text(rampLabel.replace("Ramp ", "Ramp Up "));
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
$("#node-label-rampDownValue").text(rampLabel.replace("Ramp ", "Ramp Down "));
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
$("#row-ramp-up-value").show();
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
$("#row-ramp-down-value").show();
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
refreshValidationMessage();
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
function refreshValidationMessage() {
|
|
518
|
+
|
|
519
|
+
const maxPower = Number($("#node-input-maxPower").val());
|
|
520
|
+
|
|
521
|
+
const nominalPower = Number($("#node-input-nominalPower").val());
|
|
522
|
+
|
|
523
|
+
const showNominalPower = $("#row-ramp-nominal-power").is(":visible");
|
|
524
|
+
|
|
525
|
+
const invalidNominal = showNominalPower &&
|
|
526
|
+
|
|
527
|
+
Number.isFinite(maxPower) &&
|
|
528
|
+
|
|
529
|
+
maxPower > 0 &&
|
|
530
|
+
|
|
531
|
+
Number.isFinite(nominalPower) &&
|
|
532
|
+
|
|
533
|
+
nominalPower > 0 &&
|
|
534
|
+
|
|
535
|
+
nominalPower < maxPower;
|
|
536
|
+
|
|
537
|
+
const invalidPowerLimit = showNominalPower &&
|
|
538
|
+
|
|
539
|
+
Number.isFinite(nominalPower) &&
|
|
540
|
+
|
|
541
|
+
nominalPower > FRONIUS_WRITE_MAX_NOMINAL_POWER_W;
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
$("#node-fronius-write-validation")
|
|
545
|
+
|
|
546
|
+
.toggle(invalidNominal || invalidPowerLimit)
|
|
547
|
+
|
|
548
|
+
.html(invalidPowerLimit
|
|
549
|
+
|
|
550
|
+
? '<div class="fw-validation-block"><i class="fa fa-warning"></i> Nominal Power (W) trebuie sa fie cel mult 125000 W.</div>'
|
|
551
|
+
|
|
552
|
+
: invalidNominal
|
|
553
|
+
|
|
554
|
+
? '<div class="fw-validation-block"><i class="fa fa-warning"></i> Nominal Power (W) trebuie sa fie mai mare sau egal cu Max Power (W).</div>'
|
|
555
|
+
|
|
556
|
+
: "");
|
|
557
|
+
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
const savedPowerType = normalizePowerType(node.powerType || "active");
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
const savedMode = normalizeMode(savedPowerType, node.mode || "watts");
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
const savedRampType = node.rampType || "none";
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
$("#node-input-powerType").val(savedPowerType);
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
$("#node-input-rampType").val(savedRampType);
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
ensureNumberInput("#node-input-port", 502);
|
|
579
|
+
|
|
580
|
+
ensureNumberInput("#node-input-unitId", 1);
|
|
581
|
+
|
|
582
|
+
ensureNumberInput("#node-input-maxPower", node.maxPower || node.nominalPower || 25000);
|
|
583
|
+
|
|
584
|
+
ensureNumberInput("#node-input-nominalPower", node.nominalPower || node.maxPower || 25000);
|
|
585
|
+
|
|
586
|
+
ensureNumberInput("#node-input-nominalReactivePower", node.nominalReactivePower || node.nominalPower || 25000);
|
|
587
|
+
|
|
588
|
+
ensureNumberInput("#node-input-rampTime", 0);
|
|
589
|
+
|
|
590
|
+
ensureNumberInput("#node-input-rampGradientPct", 10);
|
|
591
|
+
|
|
592
|
+
ensureNumberInput("#node-input-rampGradientWatts", 2500);
|
|
593
|
+
|
|
594
|
+
ensureNumberInput("#node-input-rampGradientVars", 2500);
|
|
595
|
+
|
|
596
|
+
ensureNumberInput("#node-input-rampUpValue", 0);
|
|
597
|
+
|
|
598
|
+
ensureNumberInput("#node-input-rampDownValue", 0);
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
rebuildModeOptions(savedMode);
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
toggleFields();
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
if (!$("#node-input-name").val().trim()) {
|
|
609
|
+
|
|
610
|
+
const autoName = buildAutoName();
|
|
611
|
+
|
|
612
|
+
if (autoName) {
|
|
613
|
+
|
|
614
|
+
$("#node-input-name").val(autoName);
|
|
615
|
+
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
$("#node-input-host")
|
|
622
|
+
|
|
623
|
+
.off(".froniusWriteNameSync")
|
|
624
|
+
|
|
625
|
+
.on("input.froniusWriteNameSync change.froniusWriteNameSync", function () {
|
|
626
|
+
|
|
627
|
+
autoNameEnabled = true;
|
|
628
|
+
$("#node-input-name").val(buildAutoName());
|
|
629
|
+
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
$("#node-input-inverterId")
|
|
634
|
+
|
|
635
|
+
.off(".froniusWriteNameSync")
|
|
636
|
+
|
|
637
|
+
.on("input.froniusWriteNameSync change.froniusWriteNameSync", function () {
|
|
638
|
+
|
|
639
|
+
if (autoNameEnabled) {
|
|
640
|
+
$("#node-input-name").val(buildAutoName());
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
$("#node-input-name")
|
|
646
|
+
.off(".froniusWriteNameSync")
|
|
647
|
+
.on("input.froniusWriteNameSync", function () {
|
|
648
|
+
const value = String($(this).val() || "").trim();
|
|
649
|
+
autoNameEnabled = !value || value === buildAutoName();
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
$("#node-input-multiInverter")
|
|
654
|
+
|
|
655
|
+
.off(".froniusWriteMulti")
|
|
656
|
+
|
|
657
|
+
.on("change.froniusWriteMulti", function () {
|
|
658
|
+
|
|
659
|
+
toggleMultiInverterFields();
|
|
660
|
+
|
|
661
|
+
if (autoNameEnabled) {
|
|
662
|
+
$("#node-input-name").val(buildAutoName());
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
$("#node-input-inverterId").trigger("change");
|
|
666
|
+
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
$("#node-input-powerType").off(".froniusWrite").on("change.froniusWrite", function () {
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
const powerType = normalizePowerType($(this).val());
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
if (powerType === "reactive") {
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
rebuildModeOptions("vars");
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
} else {
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
rebuildModeOptions("watts");
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
toggleFields();
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
$("#node-input-mode").off(".froniusWrite").on("change.froniusWrite", function () {
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
toggleFields();
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
$("#node-input-rampType").off(".froniusWrite").on("change.froniusWrite", function () {
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
toggleFields();
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
$("#node-input-maxPower").off(".froniusWrite").on("input.froniusWrite change.froniusWrite", function () {
|
|
721
|
+
|
|
722
|
+
$("#node-input-nominalPower").trigger("change");
|
|
723
|
+
|
|
724
|
+
refreshValidationMessage();
|
|
725
|
+
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
$("#node-input-nominalPower").off(".froniusWrite").on("input.froniusWrite change.froniusWrite", function () {
|
|
730
|
+
|
|
731
|
+
refreshValidationMessage();
|
|
732
|
+
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
toggleMultiInverterFields();
|
|
737
|
+
|
|
738
|
+
loadRuntimeState();
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
},
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
oneditsave: function () {
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
const powerType = $("#node-input-powerType").val() === "reactive" ? "reactive" : "active";
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
let mode = $("#node-input-mode").val();
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
if (powerType === "reactive") {
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
if (mode !== "vars" && mode !== "percent") {
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
mode = "vars";
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
} else {
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
if (mode !== "watts" && mode !== "percent") {
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
mode = "watts";
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
this.powerType = powerType;
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
this.mode = mode;
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
this.rampType = $("#node-input-rampType").val() || "none";
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
const maxPowerInput = String($("#node-input-maxPower").val() || "").trim();
|
|
793
|
+
|
|
794
|
+
const nominalPowerInput = String($("#node-input-nominalPower").val() || "").trim();
|
|
795
|
+
|
|
796
|
+
const nominalReactivePowerInput = String($("#node-input-nominalReactivePower").val() || "").trim();
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
const previousMaxPower = Number(this.maxPower);
|
|
800
|
+
|
|
801
|
+
const previousNominalPower = Number(this.nominalPower);
|
|
802
|
+
|
|
803
|
+
const previousNominalReactivePower = Number(this.nominalReactivePower);
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
function clampConfiguredPower(value, fallback) {
|
|
807
|
+
|
|
808
|
+
const n = Number(value);
|
|
809
|
+
|
|
810
|
+
const safeFallback = Number.isFinite(Number(fallback)) && Number(fallback) > 0 ? Number(fallback) : 25000;
|
|
811
|
+
|
|
812
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
813
|
+
|
|
814
|
+
return Math.min(safeFallback, FRONIUS_WRITE_MAX_NOMINAL_POWER_W);
|
|
815
|
+
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return Math.min(n, FRONIUS_WRITE_MAX_NOMINAL_POWER_W);
|
|
819
|
+
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
this.maxPower = maxPowerInput
|
|
824
|
+
|
|
825
|
+
? clampConfiguredPower(maxPowerInput, 25000)
|
|
826
|
+
|
|
827
|
+
: clampConfiguredPower(
|
|
828
|
+
Number.isFinite(previousMaxPower) && previousMaxPower > 0
|
|
829
|
+
? previousMaxPower
|
|
830
|
+
: (Number.isFinite(previousNominalPower) && previousNominalPower > 0 ? previousNominalPower : 25000),
|
|
831
|
+
25000
|
|
832
|
+
);
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
this.nominalPower = nominalPowerInput
|
|
836
|
+
|
|
837
|
+
? clampConfiguredPower(nominalPowerInput, this.maxPower)
|
|
838
|
+
|
|
839
|
+
: clampConfiguredPower(
|
|
840
|
+
Number.isFinite(previousNominalPower) && previousNominalPower > 0 ? previousNominalPower : 25000,
|
|
841
|
+
this.maxPower
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
if (Number.isFinite(this.maxPower) && this.maxPower > 0 && this.nominalPower < this.maxPower) {
|
|
846
|
+
|
|
847
|
+
this.nominalPower = this.maxPower;
|
|
848
|
+
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
this.nominalReactivePower = nominalReactivePowerInput
|
|
853
|
+
|
|
854
|
+
? clampConfiguredPower(nominalReactivePowerInput, this.nominalPower)
|
|
855
|
+
|
|
856
|
+
: clampConfiguredPower(
|
|
857
|
+
Number.isFinite(previousNominalReactivePower) && previousNominalReactivePower > 0 ? previousNominalReactivePower : this.nominalPower,
|
|
858
|
+
this.nominalPower
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
this.rampTime = Number($("#node-input-rampTime").val() || 0);
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
this.rampGradientPct = Number($("#node-input-rampGradientPct").val() || 0);
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
this.rampGradientWatts = Number($("#node-input-rampGradientWatts").val() || 0);
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
this.rampGradientVars = Number($("#node-input-rampGradientVars").val() || 0);
|
|
873
|
+
|
|
874
|
+
this.rampUpValue = Number($("#node-input-rampUpValue").val() || 0);
|
|
875
|
+
|
|
876
|
+
this.rampDownValue = Number($("#node-input-rampDownValue").val() || 0);
|
|
877
|
+
|
|
878
|
+
this.latencyTargetMs = Number(this.latencyTargetMs || 200);
|
|
879
|
+
|
|
880
|
+
this.maxCommandAgeMs = Number(this.maxCommandAgeMs || 1000);
|
|
881
|
+
|
|
882
|
+
this.disableReadbackVerification = $("#node-input-disableReadbackVerification").is(":checked");
|
|
883
|
+
|
|
884
|
+
this.multiInverter = $("#node-input-multiInverter").is(":checked");
|
|
885
|
+
|
|
886
|
+
this.inverterId = String($("#node-input-inverterId").val() || "").trim();
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
if (!$("#node-input-name").val().trim()) {
|
|
891
|
+
|
|
892
|
+
const host = ($("#node-input-host").val() || "").trim();
|
|
893
|
+
|
|
894
|
+
if (this.multiInverter && this.inverterId) {
|
|
895
|
+
|
|
896
|
+
$("#node-input-name").val(host ? (host + " [" + this.inverterId + "]") : this.inverterId);
|
|
897
|
+
|
|
898
|
+
} else {
|
|
899
|
+
|
|
900
|
+
$("#node-input-name").val(host);
|
|
901
|
+
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
$("#node-input-host").off(".froniusWriteNameSync");
|
|
908
|
+
|
|
909
|
+
$("#node-input-inverterId").off(".froniusWriteNameSync");
|
|
910
|
+
$("#node-input-name").off(".froniusWriteNameSync");
|
|
911
|
+
|
|
912
|
+
$("#node-input-powerType").off(".froniusWrite");
|
|
913
|
+
|
|
914
|
+
$("#node-input-mode").off(".froniusWrite");
|
|
915
|
+
|
|
916
|
+
$("#node-input-rampType").off(".froniusWrite");
|
|
917
|
+
|
|
918
|
+
$("#node-input-multiInverter").off(".froniusWriteMulti");
|
|
919
|
+
|
|
920
|
+
$("#node-input-maxPower").off(".froniusWrite");
|
|
921
|
+
|
|
922
|
+
$("#node-input-nominalPower").off(".froniusWrite");
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
},
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
oneditcancel: function () {
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
$("#node-input-host").off(".froniusWriteNameSync");
|
|
932
|
+
|
|
933
|
+
$("#node-input-inverterId").off(".froniusWriteNameSync");
|
|
934
|
+
$("#node-input-name").off(".froniusWriteNameSync");
|
|
935
|
+
|
|
936
|
+
$("#node-input-powerType").off(".froniusWrite");
|
|
937
|
+
|
|
938
|
+
$("#node-input-mode").off(".froniusWrite");
|
|
939
|
+
|
|
940
|
+
$("#node-input-rampType").off(".froniusWrite");
|
|
941
|
+
|
|
942
|
+
$("#node-input-multiInverter").off(".froniusWriteMulti");
|
|
943
|
+
|
|
944
|
+
$("#node-input-maxPower").off(".froniusWrite");
|
|
945
|
+
|
|
946
|
+
$("#node-input-nominalPower").off(".froniusWrite");
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
</script>
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
<script type="text/html" data-template-name="fronius-write">
|
|
960
|
+
<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>
|
|
961
|
+
|
|
962
|
+
<div class="fronius-write-editor">
|
|
963
|
+
|
|
964
|
+
<div class="pr-section">
|
|
965
|
+
|
|
966
|
+
<div class="pr-section-title"><i class="fa fa-plug"></i> Connection</div>
|
|
967
|
+
|
|
968
|
+
<p class="pr-section-note">Configuratia de scriere SunSpec (Modbus TCP) pentru invertor Fronius.</p>
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
<div class="pr-grid pr-grid-2">
|
|
972
|
+
|
|
973
|
+
<div class="form-row">
|
|
974
|
+
|
|
975
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
976
|
+
|
|
977
|
+
<input type="text" id="node-input-name" placeholder="192.168.0.101">
|
|
978
|
+
|
|
979
|
+
</div>
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
<div class="form-row">
|
|
983
|
+
|
|
984
|
+
<label for="node-input-host"><i class="fa fa-globe"></i> IP</label>
|
|
985
|
+
|
|
986
|
+
<input type="text" id="node-input-host" placeholder="192.168.0.xxx">
|
|
987
|
+
|
|
988
|
+
</div>
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
<div class="form-row">
|
|
992
|
+
|
|
993
|
+
<label for="node-input-port"><i class="fa fa-plug"></i> Port</label>
|
|
994
|
+
|
|
995
|
+
<input type="text" id="node-input-port" placeholder="502">
|
|
996
|
+
|
|
997
|
+
</div>
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
<div class="form-row">
|
|
1001
|
+
|
|
1002
|
+
<label for="node-input-unitId"><i class="fa fa-hashtag"></i> Unit ID</label>
|
|
1003
|
+
|
|
1004
|
+
<input type="text" id="node-input-unitId" placeholder="1">
|
|
1005
|
+
|
|
1006
|
+
</div>
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
<div class="form-row pr-checkbox-row">
|
|
1010
|
+
|
|
1011
|
+
<label for="node-input-multiInverter"><i class="fa fa-sitemap"></i> Multi-inverter</label>
|
|
1012
|
+
|
|
1013
|
+
<input type="checkbox" id="node-input-multiInverter">
|
|
1014
|
+
|
|
1015
|
+
</div>
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
<div class="form-row" id="row-inverter-id" style="display:none;">
|
|
1019
|
+
|
|
1020
|
+
<label for="node-input-inverterId"><i class="fa fa-id-badge"></i> Inverter ID</label>
|
|
1021
|
+
|
|
1022
|
+
<input type="text" id="node-input-inverterId" placeholder="inv1">
|
|
1023
|
+
|
|
1024
|
+
</div>
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
</div>
|
|
1028
|
+
|
|
1029
|
+
</div>
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
<div class="pr-section">
|
|
1033
|
+
|
|
1034
|
+
<div class="pr-section-title"><i class="fa fa-bolt"></i> Power Control</div>
|
|
1035
|
+
|
|
1036
|
+
<p class="pr-section-note">Alege tipul limitei si modul de lucru. Campurile necesare apar automat in functie de selectie.</p>
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
<div class="pr-grid pr-grid-2">
|
|
1040
|
+
|
|
1041
|
+
<div class="form-row">
|
|
1042
|
+
|
|
1043
|
+
<label for="node-input-powerType"><i class="fa fa-exchange"></i> Power type</label>
|
|
1044
|
+
|
|
1045
|
+
<select id="node-input-powerType">
|
|
1046
|
+
|
|
1047
|
+
<option value="active">Active Power</option>
|
|
1048
|
+
|
|
1049
|
+
<option value="reactive">Reactive Power</option>
|
|
1050
|
+
|
|
1051
|
+
</select>
|
|
1052
|
+
|
|
1053
|
+
</div>
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
<div class="form-row">
|
|
1057
|
+
|
|
1058
|
+
<label for="node-input-mode"><i class="fa fa-cogs"></i> Mode</label>
|
|
1059
|
+
|
|
1060
|
+
<select id="node-input-mode"></select>
|
|
1061
|
+
|
|
1062
|
+
</div>
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
<div class="form-row" id="row-nominal-power">
|
|
1066
|
+
|
|
1067
|
+
<label for="node-input-maxPower"><i class="fa fa-line-chart"></i> Max Power (W)</label>
|
|
1068
|
+
|
|
1069
|
+
<input type="text" id="node-input-maxPower" placeholder="125000">
|
|
1070
|
+
|
|
1071
|
+
</div>
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
<div class="form-row pr-checkbox-row pr-span-2">
|
|
1075
|
+
|
|
1076
|
+
<label for="node-input-disableReadbackVerification"><i class="fa fa-check-square-o"></i> Disable read-back verification</label>
|
|
1077
|
+
|
|
1078
|
+
<input type="checkbox" id="node-input-disableReadbackVerification">
|
|
1079
|
+
|
|
1080
|
+
<span class="pr-inline-note">Foloseste cand alt controller, de exemplu Victron, rescrie aceleasi registre SunSpec.</span>
|
|
1081
|
+
|
|
1082
|
+
</div>
|
|
1083
|
+
|
|
1084
|
+
</div>
|
|
1085
|
+
|
|
1086
|
+
</div>
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
<div class="pr-section">
|
|
1090
|
+
|
|
1091
|
+
<div class="pr-section-title"><i class="fa fa-tachometer"></i> Ramp</div>
|
|
1092
|
+
|
|
1093
|
+
<p class="pr-section-note">Defineste dinamica aplicarii comenzii: timp fix, gradient procentual sau gradient in unitati absolute.</p>
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
<div class="pr-grid pr-grid-2">
|
|
1097
|
+
|
|
1098
|
+
<div class="form-row pr-span-2">
|
|
1099
|
+
|
|
1100
|
+
<label for="node-input-rampType"><i class="fa fa-sliders"></i> Ramp Type</label>
|
|
1101
|
+
|
|
1102
|
+
<select id="node-input-rampType">
|
|
1103
|
+
|
|
1104
|
+
<option value="none">No ramp</option>
|
|
1105
|
+
|
|
1106
|
+
<option value="time">Ramp Time (s)</option>
|
|
1107
|
+
|
|
1108
|
+
<option value="gradient_pct">Gradient (%/s)</option>
|
|
1109
|
+
|
|
1110
|
+
<option value="gradient_w">Gradient (W/s / VAr/s)</option>
|
|
1111
|
+
|
|
1112
|
+
</select>
|
|
1113
|
+
|
|
1114
|
+
</div>
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
<div class="form-row" id="row-ramp-nominal-power">
|
|
1118
|
+
|
|
1119
|
+
<label for="node-input-nominalPower"><i class="fa fa-line-chart"></i> Nominal Power (W)</label>
|
|
1120
|
+
|
|
1121
|
+
<input type="text" id="node-input-nominalPower" placeholder="125000">
|
|
1122
|
+
|
|
1123
|
+
</div>
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
<div class="form-row" id="row-nominal-reactive-power">
|
|
1127
|
+
|
|
1128
|
+
<label for="node-input-nominalReactivePower"><i class="fa fa-area-chart"></i> Nominal Reactive Power (VAr)</label>
|
|
1129
|
+
|
|
1130
|
+
<input type="text" id="node-input-nominalReactivePower" placeholder="125000">
|
|
1131
|
+
|
|
1132
|
+
</div>
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
<input type="hidden" id="node-input-rampTime">
|
|
1136
|
+
|
|
1137
|
+
<input type="hidden" id="node-input-rampGradientPct">
|
|
1138
|
+
|
|
1139
|
+
<input type="hidden" id="node-input-rampGradientWatts">
|
|
1140
|
+
|
|
1141
|
+
<input type="hidden" id="node-input-rampGradientVars">
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
<div class="form-row" id="row-ramp-up-value">
|
|
1145
|
+
|
|
1146
|
+
<label for="node-input-rampUpValue"><i class="fa fa-level-up"></i> <span id="node-label-rampUpValue">Ramp Up Value</span></label>
|
|
1147
|
+
|
|
1148
|
+
<input type="text" id="node-input-rampUpValue" placeholder="0 = no ramp on up">
|
|
1149
|
+
|
|
1150
|
+
</div>
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
<div class="form-row" id="row-ramp-down-value">
|
|
1154
|
+
|
|
1155
|
+
<label for="node-input-rampDownValue"><i class="fa fa-level-down"></i> <span id="node-label-rampDownValue">Ramp Down Value</span></label>
|
|
1156
|
+
|
|
1157
|
+
<input type="text" id="node-input-rampDownValue" placeholder="0 = no ramp on down">
|
|
1158
|
+
|
|
1159
|
+
</div>
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
<div class="form-row pr-span-2" id="node-fronius-write-validation" style="display:none;"></div>
|
|
1163
|
+
|
|
1164
|
+
</div>
|
|
1165
|
+
|
|
1166
|
+
</div>
|
|
1167
|
+
|
|
1168
|
+
</div>
|
|
1169
|
+
|
|
1170
|
+
</script>
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
<script type="text/html" data-help-name="fronius-write">
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
<p>
|
|
1178
|
+
|
|
1179
|
+
Nodul <b>fronius-write</b> trimite comenzi de limitare catre un invertor Fronius prin <b>SunSpec (Modbus TCP)</b>.
|
|
1180
|
+
|
|
1181
|
+
Nodul cauta automat modelul SunSpec de control al invertorului si scrie registrii necesari pentru putere activa sau reactiva.
|
|
1182
|
+
|
|
1183
|
+
</p>
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
<h3>Cerinte</h3>
|
|
1187
|
+
|
|
1188
|
+
<ul>
|
|
1189
|
+
|
|
1190
|
+
<li>Invertorul trebuie sa fie accesibil in retea prin IP.</li>
|
|
1191
|
+
|
|
1192
|
+
<li>Modbus TCP / SunSpec trebuie sa fie activ pe invertor.</li>
|
|
1193
|
+
|
|
1194
|
+
<li>Invertorul trebuie sa expuna un model SunSpec de control: <code>120</code>, <code>121</code>, <code>122</code> sau <code>123</code>.</li>
|
|
1195
|
+
|
|
1196
|
+
<li>Portul uzual pentru Modbus TCP este <code>502</code>.</li>
|
|
1197
|
+
|
|
1198
|
+
</ul>
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
<h3>Conexiune</h3>
|
|
1202
|
+
|
|
1203
|
+
<ul>
|
|
1204
|
+
|
|
1205
|
+
<li><b>Name</b> - numele afisat in flow. Daca este gol, nodul foloseste IP-ul. In modul Multi-inverter adauga si <b>Inverter ID</b>.</li>
|
|
1206
|
+
|
|
1207
|
+
<li><b>IP</b> - adresa invertorului Fronius, de exemplu <code>192.168.0.101</code>.</li>
|
|
1208
|
+
|
|
1209
|
+
<li><b>Port</b> - portul Modbus TCP; de obicei <code>502</code>.</li>
|
|
1210
|
+
|
|
1211
|
+
<li><b>Unit ID</b> - adresa Modbus a invertorului; in multe instalatii este <code>1</code>.</li>
|
|
1212
|
+
|
|
1213
|
+
</ul>
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
<h3>Power type</h3>
|
|
1217
|
+
|
|
1218
|
+
<ul>
|
|
1219
|
+
|
|
1220
|
+
<li><b>Active Power</b> - controleaza puterea activa a invertorului. Comanda poate fi in <b>W</b> sau in <b>%</b>.</li>
|
|
1221
|
+
|
|
1222
|
+
<li><b>Reactive Power</b> - controleaza puterea reactiva. Comanda poate fi in <b>VAr</b> sau in <b>%</b>.</li>
|
|
1223
|
+
|
|
1224
|
+
<li>Cand se aplica o comanda activa, nodul dezactiveaza controlul reactiv scris anterior.</li>
|
|
1225
|
+
|
|
1226
|
+
<li>Cand se aplica o comanda reactiva, nodul dezactiveaza controlul activ scris anterior.</li>
|
|
1227
|
+
|
|
1228
|
+
</ul>
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
<h3>Mode</h3>
|
|
1232
|
+
|
|
1233
|
+
<ul>
|
|
1234
|
+
|
|
1235
|
+
<li><b>Watts</b> - disponibil pentru <b>Active Power</b>. Valoarea este limitata intre <code>0</code> si <b>Max Power (W)</b>.</li>
|
|
1236
|
+
|
|
1237
|
+
<li><b>Percent</b> - disponibil pentru putere activa si reactiva. Valoarea este limitata intre <code>-100</code> si <code>100</code>.</li>
|
|
1238
|
+
|
|
1239
|
+
<li><b>VAr</b> - disponibil pentru <b>Reactive Power</b>. Valoarea este limitata intre minus si plus <b>Nominal Reactive Power (VAr)</b>.</li>
|
|
1240
|
+
|
|
1241
|
+
</ul>
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
<h3>Max Power</h3>
|
|
1245
|
+
|
|
1246
|
+
<ul>
|
|
1247
|
+
|
|
1248
|
+
<li><b>Max Power (W)</b> este limita maxima acceptata pentru comenzile active in W.</li>
|
|
1249
|
+
|
|
1250
|
+
<li>Daca intrarea cere o valoare mai mare decat <b>Max Power (W)</b>, nodul respinge comanda si trimite <code>fronius/error</code>.</li>
|
|
1251
|
+
|
|
1252
|
+
<li><b>Nominal Power (W)</b> este folosit pentru conversia comenzilor active din W in procent SunSpec si trebuie sa fie mai mare sau egal cu <b>Max Power (W)</b>.</li>
|
|
1253
|
+
|
|
1254
|
+
<li><b>Nominal Reactive Power (VAr)</b> este folosit pentru conversia comenzilor reactive din VAr in procent SunSpec.</li>
|
|
1255
|
+
|
|
1256
|
+
<li>Valorile trebuie sa corespunda invertorului real. O valoare gresita produce o limita procentuala gresita.</li>
|
|
1257
|
+
|
|
1258
|
+
</ul>
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
<h3>Ramp</h3>
|
|
1262
|
+
|
|
1263
|
+
<ul>
|
|
1264
|
+
|
|
1265
|
+
<li><b>No ramp</b> - scrie comanda fara timp de rampa.</li>
|
|
1266
|
+
|
|
1267
|
+
<li><b>Ramp Time (s)</b> - aplica limita intr-un numar fix de secunde.</li>
|
|
1268
|
+
|
|
1269
|
+
<li><b>Gradient (%/s)</b> - nodul calculeaza automat timpul de rampa din procentul comandat si gradient.</li>
|
|
1270
|
+
|
|
1271
|
+
<li><b>Gradient (W/s)</b> - pentru putere activa, nodul calculeaza timpul de rampa din W si <b>Nominal Power</b>.</li>
|
|
1272
|
+
|
|
1273
|
+
<li><b>Gradient (VAr/s)</b> - pentru putere reactiva, nodul calculeaza timpul de rampa din VAr si <b>Nominal Reactive Power</b>.</li>
|
|
1274
|
+
|
|
1275
|
+
<li><b>Ramp Up Value</b> suprascrie valoarea de baza cand limita creste fata de ultima comanda aplicata.</li>
|
|
1276
|
+
|
|
1277
|
+
<li><b>Ramp Down Value</b> suprascrie valoarea de baza cand limita scade fata de ultima comanda aplicata.</li>
|
|
1278
|
+
|
|
1279
|
+
<li>O rampa trimisa in <code>msg.payload.ramp</code> suprascrie rampa configurata in editor pentru acel mesaj.</li>
|
|
1280
|
+
|
|
1281
|
+
</ul>
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
<h3>Input simplu</h3>
|
|
1285
|
+
|
|
1286
|
+
<p>
|
|
1287
|
+
|
|
1288
|
+
Daca <code>msg.payload</code> este numar sau string numeric, valoarea este interpretata folosind <b>Power type</b> si <b>Mode</b> configurate in nod.
|
|
1289
|
+
|
|
1290
|
+
</p>
|
|
1291
|
+
|
|
1292
|
+
<pre>
|
|
1293
|
+
|
|
1294
|
+
msg.payload = 3500
|
|
1295
|
+
|
|
1296
|
+
</pre>
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
<h3>Input obiect</h3>
|
|
1300
|
+
|
|
1301
|
+
<p>
|
|
1302
|
+
|
|
1303
|
+
Daca <code>msg.payload</code> este obiect, mesajul poate seta direct tipul puterii, modul, valoarea si rampa.
|
|
1304
|
+
|
|
1305
|
+
</p>
|
|
1306
|
+
|
|
1307
|
+
<ul>
|
|
1308
|
+
|
|
1309
|
+
<li><code>payload.value</code> - valoarea comenzii, interpretata cu <code>payload.powerType</code>/<code>payload.power_type</code> si <code>payload.mode</code>.</li>
|
|
1310
|
+
|
|
1311
|
+
<li><code>payload.site_limit_w</code>, <code>payload.limit_w</code> sau <code>payload.watts</code> - comanda activa in W.</li>
|
|
1312
|
+
|
|
1313
|
+
<li><code>payload.limit_pct</code> sau <code>payload.percent</code> - comanda in procent.</li>
|
|
1314
|
+
|
|
1315
|
+
<li><code>payload.limit_var</code>, <code>payload.vars</code> sau <code>payload.var</code> - comanda reactiva in VAr.</li>
|
|
1316
|
+
|
|
1317
|
+
<li><code>payload.limit_var_pct</code> - comanda reactiva in procent.</li>
|
|
1318
|
+
|
|
1319
|
+
<li><code>payload.ramp.type</code> - <code>none</code>, <code>time</code>, <code>gradient_pct</code> sau <code>gradient_w</code>.</li>
|
|
1320
|
+
|
|
1321
|
+
<li><code>payload.ramp.value</code> - valoarea rampei pentru tipul ales.</li>
|
|
1322
|
+
|
|
1323
|
+
</ul>
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
<h3>Exemple input</h3>
|
|
1327
|
+
|
|
1328
|
+
<pre>
|
|
1329
|
+
|
|
1330
|
+
msg.payload = {
|
|
1331
|
+
|
|
1332
|
+
limit_w: 5000,
|
|
1333
|
+
|
|
1334
|
+
ramp: { type: "time", value: 10 }
|
|
1335
|
+
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
</pre>
|
|
1339
|
+
|
|
1340
|
+
<pre>
|
|
1341
|
+
|
|
1342
|
+
msg.payload = {
|
|
1343
|
+
|
|
1344
|
+
power_type: "reactive",
|
|
1345
|
+
|
|
1346
|
+
mode: "vars",
|
|
1347
|
+
|
|
1348
|
+
value: -1200,
|
|
1349
|
+
|
|
1350
|
+
ramp: { type: "gradient_w", value: 600 }
|
|
1351
|
+
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
</pre>
|
|
1355
|
+
|
|
1356
|
+
<pre>
|
|
1357
|
+
|
|
1358
|
+
msg.payload = {
|
|
1359
|
+
|
|
1360
|
+
percent: 40
|
|
1361
|
+
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
</pre>
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
<h3>Multi-inverter</h3>
|
|
1368
|
+
|
|
1369
|
+
<p>
|
|
1370
|
+
|
|
1371
|
+
Cand <b>Multi-inverter</b> este activ, nodul nu aplica tot payload-ul primit. El cauta limita pentru propriul <b>Inverter ID</b>
|
|
1372
|
+
|
|
1373
|
+
si rescrie mesajul intern ca si cum ar fi primit doar comanda acelui invertor.
|
|
1374
|
+
|
|
1375
|
+
</p>
|
|
1376
|
+
|
|
1377
|
+
<ul>
|
|
1378
|
+
|
|
1379
|
+
<li><b>Inverter ID</b> devine obligatoriu.</li>
|
|
1380
|
+
|
|
1381
|
+
<li>ID-ul trebuie sa corespunda cu ID-ul generat de nodul <code>multi-inverter</code>.</li>
|
|
1382
|
+
|
|
1383
|
+
<li>Payload-ul acceptat poate fi un array direct sau un obiect cu <code>payload.limits[]</code> ori <code>payload.inverters[]</code>.</li>
|
|
1384
|
+
|
|
1385
|
+
<li>Fiecare element poate avea <code>id</code>, <code>inverter_id</code> sau <code>topic</code>.</li>
|
|
1386
|
+
|
|
1387
|
+
<li>Comanda pentru invertor poate fi in <code>item.payload</code> sau direct in campurile <code>limit_w</code>, <code>limit_var</code>, <code>limit_var_pct</code> si <code>ramp</code>.</li>
|
|
1388
|
+
|
|
1389
|
+
</ul>
|
|
1390
|
+
|
|
1391
|
+
<pre>
|
|
1392
|
+
|
|
1393
|
+
msg.payload = {
|
|
1394
|
+
|
|
1395
|
+
limits: [
|
|
1396
|
+
|
|
1397
|
+
{ id: "inv1", payload: { limit_w: 3200 } },
|
|
1398
|
+
|
|
1399
|
+
{ id: "inv2", payload: { limit_w: 2800 } }
|
|
1400
|
+
|
|
1401
|
+
]
|
|
1402
|
+
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
</pre>
|
|
1406
|
+
|
|
1407
|
+
<p>
|
|
1408
|
+
|
|
1409
|
+
Un nod <code>fronius-write</code> configurat cu <b>Inverter ID</b> = <code>inv1</code> va aplica doar limita pentru <code>inv1</code>.
|
|
1410
|
+
|
|
1411
|
+
</p>
|
|
1412
|
+
|
|
1413
|
+
|
|
1414
|
+
<h3>Ce scrie in invertor</h3>
|
|
1415
|
+
|
|
1416
|
+
<ul>
|
|
1417
|
+
|
|
1418
|
+
<li>Scrie timpul de rampa in registrul SunSpec corespunzator.</li>
|
|
1419
|
+
|
|
1420
|
+
<li>Scrie valoarea procentuala scalata in registrul de limita activa sau reactiva.</li>
|
|
1421
|
+
|
|
1422
|
+
<li>Activeaza controlul selectat prin registrul <code>enable</code>.</li>
|
|
1423
|
+
|
|
1424
|
+
<li>Incearca sa dezactiveze celalalt tip de control, pentru a evita comenzi active si reactive ramase simultan.</li>
|
|
1425
|
+
|
|
1426
|
+
</ul>
|
|
1427
|
+
|
|
1428
|
+
<h3>Read-back verification</h3>
|
|
1429
|
+
|
|
1430
|
+
<p>
|
|
1431
|
+
|
|
1432
|
+
Implicit, nodul citeste inapoi registrele scrise si raporteaza eroare daca invertorul intoarce alta valoare.
|
|
1433
|
+
|
|
1434
|
+
Bifa <b>Disable read-back verification</b> pastreaza scrierea Modbus, dar sare peste aceasta confirmare.
|
|
1435
|
+
|
|
1436
|
+
Este utila cand invertorul este controlat in paralel de un alt sistem, de exemplu Victron, care poate rescrie rapid limita la <code>100%</code>.
|
|
1437
|
+
|
|
1438
|
+
</p>
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
<h3>Output</h3>
|
|
1442
|
+
|
|
1443
|
+
<p>
|
|
1444
|
+
|
|
1445
|
+
La succes, nodul emite <code>msg.topic = "fronius/write"</code>. Payload-ul contine ce s-a aplicat efectiv:
|
|
1446
|
+
|
|
1447
|
+
</p>
|
|
1448
|
+
|
|
1449
|
+
<ul>
|
|
1450
|
+
|
|
1451
|
+
<li><code>status</code> - <code>ok</code>.</li>
|
|
1452
|
+
|
|
1453
|
+
<li><code>power_type</code> - <code>active</code> sau <code>reactive</code>.</li>
|
|
1454
|
+
|
|
1455
|
+
<li><code>mode</code> - <code>watts</code>, <code>vars</code> sau <code>percent</code>.</li>
|
|
1456
|
+
|
|
1457
|
+
<li><code>input_value</code> - valoarea primita dupa parsare.</li>
|
|
1458
|
+
|
|
1459
|
+
<li><code>applied_percent</code> - procentul SunSpec calculat si aplicat.</li>
|
|
1460
|
+
|
|
1461
|
+
<li><code>ramp_type</code>, <code>ramp_time_seconds</code> si <code>ramp_input</code> - detalii despre rampa folosita.</li>
|
|
1462
|
+
|
|
1463
|
+
<li><code>control_model_id</code> si adresele aferente - modelul SunSpec folosit pentru scriere.</li>
|
|
1464
|
+
|
|
1465
|
+
<li><code>raw_written</code> si <code>scale_factor</code> - valoarea bruta scrisa in registru si factorul de scala.</li>
|
|
1466
|
+
|
|
1467
|
+
<li><code>readback_verification_disabled</code> - <code>true</code> cand nodul nu a mai citit registrele inapoi pentru confirmare.</li>
|
|
1468
|
+
|
|
1469
|
+
</ul>
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
<h3>Erori</h3>
|
|
1473
|
+
|
|
1474
|
+
<p>
|
|
1475
|
+
|
|
1476
|
+
Daca apare o problema de conexiune, de detectare SunSpec, de validare a valorii sau de payload multi-inverter,
|
|
1477
|
+
|
|
1478
|
+
nodul seteaza status rosu si emite <code>msg.topic = "fronius/error"</code>.
|
|
1479
|
+
|
|
1480
|
+
</p>
|
|
1481
|
+
|
|
1482
|
+
<p>
|
|
1483
|
+
|
|
1484
|
+
Payload-ul de eroare contine <code>status = "error"</code>, mesajul din <code>error</code> si timestamp-ul <code>ts</code>.
|
|
1485
|
+
|
|
1486
|
+
Pentru erori Modbus temporare, nodul incearca automat retry si reconectare inainte sa raporteze eroarea.
|
|
1487
|
+
|
|
1488
|
+
</p>
|
|
1489
|
+
|
|
1490
|
+
<h3>Referinta completa parametri</h3>
|
|
1491
|
+
|
|
1492
|
+
<ul>
|
|
1493
|
+
|
|
1494
|
+
<li><code>host</code>, <code>port</code>, <code>unitId</code>: conexiunea Modbus TCP catre invertor.</li>
|
|
1495
|
+
|
|
1496
|
+
<li><code>powerType</code>: <code>active</code> pentru W/% sau <code>reactive</code> pentru VAr/%.</li>
|
|
1497
|
+
|
|
1498
|
+
<li><code>mode</code>: <code>watts</code>, <code>percent</code> sau <code>vars</code>.</li>
|
|
1499
|
+
|
|
1500
|
+
<li><code>maxPower</code>: limita maxima acceptata pentru comenzi active in W.</li>
|
|
1501
|
+
|
|
1502
|
+
<li><code>latencyTargetMs</code>: tinta informativa pentru latenta raportata in payload, nu modifica secventa Modbus.</li>
|
|
1503
|
+
|
|
1504
|
+
<li><code>maxCommandAgeMs</code>: respinge comenzi mai vechi decat pragul, pe baza timestamp-ului din mesaj.</li>
|
|
1505
|
+
|
|
1506
|
+
<li><code>disableReadbackVerification</code>: dezactiveaza compararea valorilor citite inapoi dupa scriere.</li>
|
|
1507
|
+
|
|
1508
|
+
<li><code>nominalPower</code>: puterea nominala a invertorului folosita la conversia W in procent SunSpec.</li>
|
|
1509
|
+
|
|
1510
|
+
<li><code>nominalReactivePower</code>: puterea reactiva nominala folosita la conversia VAr in procent SunSpec.</li>
|
|
1511
|
+
|
|
1512
|
+
<li><code>rampType</code>: <code>none</code>, <code>time</code>, <code>gradient_pct</code>, <code>gradient_w</code> sau <code>gradient_var</code>.</li>
|
|
1513
|
+
|
|
1514
|
+
<li><code>rampTime</code>: durata fixa in secunde pentru <code>rampType = time</code>.</li>
|
|
1515
|
+
|
|
1516
|
+
<li><code>rampGradientPct</code>, <code>rampGradientWatts</code>, <code>rampGradientVars</code>: gradientele folosite pentru calculul timpului de rampa.</li>
|
|
1517
|
+
|
|
1518
|
+
<li><code>rampUpValue</code> si <code>rampDownValue</code>: valori directionale pentru crestere/scadere, in aceeasi unitate ca tipul de rampa selectat.</li>
|
|
1519
|
+
|
|
1520
|
+
<li><code>multiInverter</code>: activeaza filtrarea comenzii dupa ID din payload-ul <code>multi-inverter</code>.</li>
|
|
1521
|
+
|
|
1522
|
+
<li><code>inverterId</code>: ID-ul local cautat in mesajele multi-inverter.</li>
|
|
1523
|
+
|
|
1524
|
+
</ul>
|
|
1525
|
+
|
|
1526
|
+
<h3>Model recomandat pentru control-export</h3>
|
|
1527
|
+
|
|
1528
|
+
<pre>
|
|
1529
|
+
control-export -> fronius-write
|
|
1530
|
+
|
|
1531
|
+
msg.payload = {
|
|
1532
|
+
site_limit_w: 10000,
|
|
1533
|
+
grid_reference_w: -500,
|
|
1534
|
+
timestamp_ms: 1776692400000
|
|
1535
|
+
}
|
|
1536
|
+
</pre>
|
|
1537
|
+
|
|
1538
|
+
<p>Seteaza <code>maxPower</code> ca limita operationala maxima permisa si <code>nominalPower</code> ca puterea reala nominala a invertorului. Aceste doua valori nu trebuie confundate.</p>
|
|
1539
|
+
|
|
1540
|
+
|
|
1541
|
+
</script>
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
<style>
|
|
1545
|
+
|
|
1546
|
+
.fronius-write-editor {
|
|
1547
|
+
|
|
1548
|
+
--pr-border: #d7dde5;
|
|
1549
|
+
|
|
1550
|
+
--pr-muted: #667085;
|
|
1551
|
+
|
|
1552
|
+
--pr-surface: #f8fafc;
|
|
1553
|
+
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
.fronius-write-editor .pr-section {
|
|
1558
|
+
|
|
1559
|
+
margin: 0 0 18px;
|
|
1560
|
+
|
|
1561
|
+
padding: 14px 16px 16px;
|
|
1562
|
+
|
|
1563
|
+
border: 1px solid var(--pr-border);
|
|
1564
|
+
|
|
1565
|
+
border-radius: 10px;
|
|
1566
|
+
|
|
1567
|
+
background: var(--pr-surface);
|
|
1568
|
+
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
.fronius-write-editor .pr-section-title {
|
|
1573
|
+
|
|
1574
|
+
display: flex;
|
|
1575
|
+
|
|
1576
|
+
align-items: center;
|
|
1577
|
+
|
|
1578
|
+
gap: 8px;
|
|
1579
|
+
|
|
1580
|
+
margin: 0 0 4px;
|
|
1581
|
+
|
|
1582
|
+
font-size: 15px;
|
|
1583
|
+
|
|
1584
|
+
font-weight: 600;
|
|
1585
|
+
|
|
1586
|
+
color: #243447;
|
|
1587
|
+
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
.fronius-write-editor .pr-section-note {
|
|
1592
|
+
|
|
1593
|
+
margin: 0 0 14px;
|
|
1594
|
+
|
|
1595
|
+
color: var(--pr-muted);
|
|
1596
|
+
|
|
1597
|
+
font-size: 12px;
|
|
1598
|
+
|
|
1599
|
+
line-height: 1.45;
|
|
1600
|
+
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
.fronius-write-editor .pr-grid {
|
|
1605
|
+
|
|
1606
|
+
display: grid;
|
|
1607
|
+
|
|
1608
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
1609
|
+
|
|
1610
|
+
gap: 12px 16px;
|
|
1611
|
+
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
.fronius-write-editor .pr-grid-2 {
|
|
1616
|
+
|
|
1617
|
+
grid-template-columns: repeat(2, minmax(320px, 1fr));
|
|
1618
|
+
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
.fronius-write-editor .pr-span-2 {
|
|
1623
|
+
|
|
1624
|
+
grid-column: 1 / -1;
|
|
1625
|
+
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
.fronius-write-editor .form-row {
|
|
1630
|
+
|
|
1631
|
+
margin-bottom: 12px;
|
|
1632
|
+
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
.fronius-write-editor .pr-grid .form-row,
|
|
1637
|
+
|
|
1638
|
+
.fronius-write-editor .form-row:last-child {
|
|
1639
|
+
|
|
1640
|
+
margin-bottom: 0;
|
|
1641
|
+
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
.fronius-write-editor .form-row > label {
|
|
1646
|
+
|
|
1647
|
+
width: 150px;
|
|
1648
|
+
|
|
1649
|
+
font-weight: 600;
|
|
1650
|
+
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
.fronius-write-editor .form-row > input[type="text"],
|
|
1655
|
+
|
|
1656
|
+
.fronius-write-editor .form-row > input[type="number"],
|
|
1657
|
+
|
|
1658
|
+
.fronius-write-editor .form-row > select {
|
|
1659
|
+
|
|
1660
|
+
width: calc(100% - 160px);
|
|
1661
|
+
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
.fronius-write-editor .pr-grid-2 .form-row > label {
|
|
1666
|
+
|
|
1667
|
+
width: 130px;
|
|
1668
|
+
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
.fronius-write-editor .pr-grid-2 .form-row > input[type="text"],
|
|
1673
|
+
|
|
1674
|
+
.fronius-write-editor .pr-grid-2 .form-row > input[type="number"],
|
|
1675
|
+
|
|
1676
|
+
.fronius-write-editor .pr-grid-2 .form-row > select {
|
|
1677
|
+
|
|
1678
|
+
width: calc(100% - 140px);
|
|
1679
|
+
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
.fronius-write-editor #row-ramp-nominal-power > label {
|
|
1684
|
+
|
|
1685
|
+
width: 160px;
|
|
1686
|
+
|
|
1687
|
+
white-space: nowrap;
|
|
1688
|
+
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
.fronius-write-editor #row-nominal-reactive-power > label {
|
|
1693
|
+
|
|
1694
|
+
width: 210px;
|
|
1695
|
+
|
|
1696
|
+
white-space: nowrap;
|
|
1697
|
+
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
.fronius-write-editor #row-ramp-nominal-power {
|
|
1702
|
+
|
|
1703
|
+
display: flex;
|
|
1704
|
+
|
|
1705
|
+
align-items: center;
|
|
1706
|
+
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
.fronius-write-editor #row-ramp-nominal-power > input[type="text"] {
|
|
1711
|
+
|
|
1712
|
+
flex: 0 0 120px;
|
|
1713
|
+
|
|
1714
|
+
width: 120px;
|
|
1715
|
+
|
|
1716
|
+
margin-left: auto;
|
|
1717
|
+
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
|
|
1722
|
+
|
|
1723
|
+
.fronius-write-editor #row-nominal-reactive-power > input[type="text"] {
|
|
1724
|
+
|
|
1725
|
+
width: 120px;
|
|
1726
|
+
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
|
|
1730
|
+
.fronius-write-editor .fw-validation-block {
|
|
1731
|
+
|
|
1732
|
+
border: 1px solid #f3c2c2;
|
|
1733
|
+
|
|
1734
|
+
border-radius: 6px;
|
|
1735
|
+
|
|
1736
|
+
background: #fdf2f2;
|
|
1737
|
+
|
|
1738
|
+
color: #a12626;
|
|
1739
|
+
|
|
1740
|
+
padding: 8px 10px;
|
|
1741
|
+
|
|
1742
|
+
line-height: 1.35;
|
|
1743
|
+
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
.fronius-write-editor .fw-validation-block i {
|
|
1748
|
+
|
|
1749
|
+
margin-right: 6px;
|
|
1750
|
+
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
.fronius-write-editor .pr-checkbox-row > input[type="checkbox"] {
|
|
1755
|
+
|
|
1756
|
+
width: auto;
|
|
1757
|
+
|
|
1758
|
+
display: inline-block;
|
|
1759
|
+
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
.fronius-write-editor .pr-inline-note {
|
|
1764
|
+
|
|
1765
|
+
display: block;
|
|
1766
|
+
|
|
1767
|
+
margin-top: 5px;
|
|
1768
|
+
|
|
1769
|
+
color: var(--pr-muted);
|
|
1770
|
+
|
|
1771
|
+
font-size: 12px;
|
|
1772
|
+
|
|
1773
|
+
line-height: 1.35;
|
|
1774
|
+
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
@media (max-width: 1100px) {
|
|
1779
|
+
|
|
1780
|
+
.fronius-write-editor .pr-grid-2 {
|
|
1781
|
+
|
|
1782
|
+
grid-template-columns: 1fr;
|
|
1783
|
+
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
</style>
|