@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,569 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.bess-control-editor {
|
|
3
|
+
--bess-border: #d7dde5;
|
|
4
|
+
--bess-muted: #667085;
|
|
5
|
+
--bess-surface: #f7faf8;
|
|
6
|
+
--bess-panel: #ffffff;
|
|
7
|
+
--bess-accent-soft: #e9f6f2;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.bess-control-editor .bess-section {
|
|
11
|
+
margin: 0 0 18px;
|
|
12
|
+
padding: 14px 16px 16px;
|
|
13
|
+
border: 1px solid var(--bess-border);
|
|
14
|
+
border-radius: 10px;
|
|
15
|
+
background: var(--bess-surface);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.bess-control-editor .bess-hero {
|
|
19
|
+
margin: 0 0 18px;
|
|
20
|
+
padding: 18px 20px;
|
|
21
|
+
border: 1px solid #cfe4dd;
|
|
22
|
+
border-radius: 14px;
|
|
23
|
+
background: linear-gradient(135deg, var(--bess-accent-soft), #f7fbfa);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.bess-control-editor .bess-hero-title {
|
|
27
|
+
margin: 0 0 6px;
|
|
28
|
+
font-size: 18px;
|
|
29
|
+
font-weight: 700;
|
|
30
|
+
color: #1f2a37;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.bess-control-editor .bess-hero-copy {
|
|
34
|
+
margin: 0;
|
|
35
|
+
color: #475467;
|
|
36
|
+
line-height: 1.5;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.bess-control-editor .bess-section-title {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: 8px;
|
|
43
|
+
margin: 0 0 4px;
|
|
44
|
+
font-size: 15px;
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
color: #243447;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.bess-control-editor .bess-section-note {
|
|
50
|
+
margin: 0 0 14px;
|
|
51
|
+
color: var(--bess-muted);
|
|
52
|
+
font-size: 12px;
|
|
53
|
+
line-height: 1.45;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.bess-control-editor .bess-grid {
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
59
|
+
gap: 12px 16px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.bess-control-editor .form-row {
|
|
63
|
+
margin-bottom: 12px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.bess-control-editor .bess-grid .form-row,
|
|
67
|
+
.bess-control-editor .form-row:last-child {
|
|
68
|
+
margin-bottom: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.bess-control-editor .form-row > label {
|
|
72
|
+
width: 160px;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.bess-control-editor .form-row > input[type="text"],
|
|
77
|
+
.bess-control-editor .form-row > select {
|
|
78
|
+
width: calc(100% - 170px);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.bess-control-editor .bess-checkbox-row > input[type="checkbox"] {
|
|
82
|
+
display: inline-block;
|
|
83
|
+
width: auto;
|
|
84
|
+
vertical-align: top;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.bess-control-editor .bess-inline-note {
|
|
88
|
+
margin-left: 8px;
|
|
89
|
+
color: var(--bess-muted);
|
|
90
|
+
line-height: 1.4;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.bess-control-editor .bess-summary {
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
gap: 8px;
|
|
97
|
+
padding: 8px 12px;
|
|
98
|
+
border: 1px solid var(--bess-border);
|
|
99
|
+
border-radius: 999px;
|
|
100
|
+
background: #fff;
|
|
101
|
+
font-weight: 600;
|
|
102
|
+
color: #344054;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.bess-control-editor .bess-kpi-row {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-wrap: wrap;
|
|
108
|
+
gap: 10px;
|
|
109
|
+
margin-top: 14px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.bess-control-editor .bess-kpi {
|
|
113
|
+
min-width: 180px;
|
|
114
|
+
padding: 10px 12px;
|
|
115
|
+
border: 1px solid var(--bess-border);
|
|
116
|
+
border-radius: 12px;
|
|
117
|
+
background: var(--bess-panel);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.bess-control-editor .bess-kpi-label {
|
|
121
|
+
margin: 0 0 4px;
|
|
122
|
+
font-size: 11px;
|
|
123
|
+
font-weight: 700;
|
|
124
|
+
letter-spacing: 0.04em;
|
|
125
|
+
text-transform: uppercase;
|
|
126
|
+
color: var(--bess-muted);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.bess-control-editor .bess-kpi-value {
|
|
130
|
+
margin: 0;
|
|
131
|
+
font-size: 15px;
|
|
132
|
+
font-weight: 700;
|
|
133
|
+
color: #1f2a37;
|
|
134
|
+
}
|
|
135
|
+
</style>
|
|
136
|
+
|
|
137
|
+
<script type="text/javascript">
|
|
138
|
+
|
|
139
|
+
(function () {
|
|
140
|
+
|
|
141
|
+
RED.nodes.registerType("bess-control", {
|
|
142
|
+
|
|
143
|
+
category: "Atelierul de Tehnologii",
|
|
144
|
+
color: "#8fd19e",
|
|
145
|
+
|
|
146
|
+
defaults: {
|
|
147
|
+
license: { value: "", type: "atelier-license", required: true },
|
|
148
|
+
name: { value: "" },
|
|
149
|
+
controlMode: { value: "grid_setpoint" },
|
|
150
|
+
zeroFeedInMode: { value: "relative" },
|
|
151
|
+
expertMode: { value: false },
|
|
152
|
+
signConvention: { value: "positive_import" },
|
|
153
|
+
gridPowerPath: { value: "payload.power_w" },
|
|
154
|
+
gridSetpointW: { value: 0, validate: RED.validators.number() },
|
|
155
|
+
nominalPowerW: { value: 0, validate: RED.validators.number() },
|
|
156
|
+
kRel: { value: 0.3, validate: RED.validators.number() },
|
|
157
|
+
deadbandW: { value: 1000, validate: RED.validators.number() },
|
|
158
|
+
staleTimeoutMs: { value: 5000, validate: RED.validators.number() },
|
|
159
|
+
socMinPct: {
|
|
160
|
+
value: "",
|
|
161
|
+
validate: function (value) {
|
|
162
|
+
return value === "" || (Number.isFinite(Number(value)) && Number(value) >= 0 && Number(value) <= 100);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
socHystPct: {
|
|
166
|
+
value: "",
|
|
167
|
+
validate: function (value) {
|
|
168
|
+
return value === "" || (Number.isFinite(Number(value)) && Number(value) >= 0 && Number(value) <= 100);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
phasePowerPathL1: { value: "payload.power_l1_w" },
|
|
172
|
+
phasePowerPathL2: { value: "payload.power_l2_w" },
|
|
173
|
+
phasePowerPathL3: { value: "payload.power_l3_w" },
|
|
174
|
+
bessOff: { value: false },
|
|
175
|
+
outputTopic: { value: "bess/setpoint" },
|
|
176
|
+
enableDebugOutput: { value: true }
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
inputs: 1,
|
|
180
|
+
outputs: 1,
|
|
181
|
+
icon: "font-awesome/fa-sliders",
|
|
182
|
+
|
|
183
|
+
label: function () {
|
|
184
|
+
return this.name || "bess-control";
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
outputLabels: function (index) {
|
|
188
|
+
if (this.enableDebugOutput && index === 1) {
|
|
189
|
+
return "diagnostic";
|
|
190
|
+
}
|
|
191
|
+
return "total-command";
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
oneditprepare: function () {
|
|
195
|
+
|
|
196
|
+
const node = this;
|
|
197
|
+
const debugInput = $("#node-input-enableDebugOutput");
|
|
198
|
+
const controlModeInput = $("#node-input-controlMode");
|
|
199
|
+
const zeroModeInput = $("#node-input-zeroFeedInMode");
|
|
200
|
+
const expertModeInput = $("#node-input-expertMode");
|
|
201
|
+
|
|
202
|
+
function ensureDefaultValue(selector, value) {
|
|
203
|
+
const input = $(selector);
|
|
204
|
+
if (!String(input.val() || "").trim()) {
|
|
205
|
+
input.val(value);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function refreshOutputs() {
|
|
210
|
+
node.outputs = debugInput.prop("checked") ? 2 : 1;
|
|
211
|
+
$("#node-bess-control-outputs-info").text(String(node.outputs));
|
|
212
|
+
$("#node-bess-control-outputs-info-hero").text(String(node.outputs));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function refreshModeUI() {
|
|
216
|
+
|
|
217
|
+
const controlMode = controlModeInput.val();
|
|
218
|
+
const zeroMode = zeroModeInput.val();
|
|
219
|
+
const expertMode = expertModeInput.prop("checked");
|
|
220
|
+
|
|
221
|
+
$("#node-bess-control-expert-panel").toggle(expertMode);
|
|
222
|
+
$("#node-bess-control-grid-path-row").toggle(expertMode && (controlMode === "grid_setpoint" || (controlMode === "zero_feed_in" && zeroMode === "relative")));
|
|
223
|
+
$("#node-bess-control-grid-setpoint-row").toggle(controlMode === "grid_setpoint");
|
|
224
|
+
$("#node-bess-control-nominal-power-row").toggle(controlMode === "nominal_power");
|
|
225
|
+
$("#node-bess-control-zero-mode-row").toggle(controlMode === "zero_feed_in");
|
|
226
|
+
$("#node-bess-control-phase-paths").toggle(expertMode && controlMode === "zero_feed_in" && zeroMode === "absolute");
|
|
227
|
+
$(".bess-control-tracking-param").toggle(controlMode === "grid_setpoint" || controlMode === "zero_feed_in");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
ensureDefaultValue("#node-input-gridPowerPath", "payload.power_w");
|
|
231
|
+
ensureDefaultValue("#node-input-phasePowerPathL1", "payload.power_l1_w");
|
|
232
|
+
ensureDefaultValue("#node-input-phasePowerPathL2", "payload.power_l2_w");
|
|
233
|
+
ensureDefaultValue("#node-input-phasePowerPathL3", "payload.power_l3_w");
|
|
234
|
+
|
|
235
|
+
refreshOutputs();
|
|
236
|
+
refreshModeUI();
|
|
237
|
+
debugInput.off(".bessControl").on("change.bessControl", refreshOutputs);
|
|
238
|
+
controlModeInput.off(".bessControl").on("change.bessControl", refreshModeUI);
|
|
239
|
+
zeroModeInput.off(".bessControl").on("change.bessControl", refreshModeUI);
|
|
240
|
+
expertModeInput.off(".bessControl").on("change.bessControl", refreshModeUI);
|
|
241
|
+
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
oneditsave: function () {
|
|
245
|
+
this.outputs = $("#node-input-enableDebugOutput").prop("checked") ? 2 : 1;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
})();
|
|
251
|
+
|
|
252
|
+
</script>
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
<script type="text/html" data-template-name="bess-control">
|
|
256
|
+
<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>
|
|
257
|
+
|
|
258
|
+
<div class="bess-control-editor">
|
|
259
|
+
|
|
260
|
+
<div class="bess-hero">
|
|
261
|
+
<h3 class="bess-hero-title">Grid Tracking Controller</h3>
|
|
262
|
+
<p class="bess-hero-copy">Acest nod calculeaza doar setpoint-ul total de putere al BESS-ului. Configurarea pe baterii individuale si distribuirea pe mai multe iesiri exista exclusiv in <code>multi-battery</code>.</p>
|
|
263
|
+
<div class="bess-kpi-row">
|
|
264
|
+
<div class="bess-kpi">
|
|
265
|
+
<p class="bess-kpi-label">Role</p>
|
|
266
|
+
<p class="bess-kpi-value">Total power control</p>
|
|
267
|
+
</div>
|
|
268
|
+
<div class="bess-kpi">
|
|
269
|
+
<p class="bess-kpi-label">Next Node</p>
|
|
270
|
+
<p class="bess-kpi-value">multi-battery</p>
|
|
271
|
+
</div>
|
|
272
|
+
<div class="bess-kpi">
|
|
273
|
+
<p class="bess-kpi-label">Outputs</p>
|
|
274
|
+
<p class="bess-kpi-value"><span id="node-bess-control-outputs-info-hero">1</span> active</p>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<div class="bess-section">
|
|
280
|
+
<div class="bess-section-title"><i class="fa fa-sliders"></i> Control Settings</div>
|
|
281
|
+
<p class="bess-section-note">Sunt afisati doar parametrii de urmarire a retelei si iesirea totala. Pragurile SOC sunt optionale: daca le completezi aici, ele sunt trimise catre <code>multi-battery</code> si suprascriu temporar valorile locale ale bateriilor. Pentru modurile de tracking si zero feed-in, <code>K rel</code> controleaza agresivitatea, iar <code>Deadband</code> defineste zona de toleranta.</p>
|
|
282
|
+
|
|
283
|
+
<div class="bess-grid">
|
|
284
|
+
<div class="form-row">
|
|
285
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
286
|
+
<input type="text" id="node-input-name" placeholder="bess-control">
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
<div class="form-row">
|
|
290
|
+
<label for="node-input-outputTopic"><i class="fa fa-sign-out"></i> Output topic</label>
|
|
291
|
+
<input type="text" id="node-input-outputTopic" placeholder="bess/setpoint">
|
|
292
|
+
</div>
|
|
293
|
+
|
|
294
|
+
<div class="form-row">
|
|
295
|
+
<label for="node-input-controlMode"><i class="fa fa-compass"></i> Control mode</label>
|
|
296
|
+
<select id="node-input-controlMode">
|
|
297
|
+
<option value="grid_setpoint">Grid setpoint</option>
|
|
298
|
+
<option value="nominal_power">Nominal power</option>
|
|
299
|
+
<option value="zero_feed_in">Zero feed-in</option>
|
|
300
|
+
</select>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div class="form-row">
|
|
304
|
+
<label for="node-input-signConvention"><i class="fa fa-random"></i> Sign convention</label>
|
|
305
|
+
<select id="node-input-signConvention">
|
|
306
|
+
<option value="positive_import">+ = import, - = export</option>
|
|
307
|
+
<option value="positive_export">+ = export, - = import</option>
|
|
308
|
+
</select>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<div class="form-row" id="node-bess-control-grid-setpoint-row">
|
|
312
|
+
<label for="node-input-gridSetpointW"><i class="fa fa-bullseye"></i> Grid setpoint (W)</label>
|
|
313
|
+
<input type="text" id="node-input-gridSetpointW" placeholder="0">
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
<div class="form-row" id="node-bess-control-nominal-power-row" style="display:none;">
|
|
317
|
+
<label for="node-input-nominalPowerW"><i class="fa fa-flash"></i> Nominal power (W)</label>
|
|
318
|
+
<input type="text" id="node-input-nominalPowerW" placeholder="5000 or -5000">
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<div class="form-row" id="node-bess-control-zero-mode-row" style="display:none;">
|
|
322
|
+
<label for="node-input-zeroFeedInMode"><i class="fa fa-crosshairs"></i> Zero feed-in mode</label>
|
|
323
|
+
<select id="node-input-zeroFeedInMode">
|
|
324
|
+
<option value="relative">0 relativ</option>
|
|
325
|
+
<option value="absolute">0 absolut</option>
|
|
326
|
+
</select>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<div class="form-row bess-control-tracking-param">
|
|
330
|
+
<label for="node-input-kRel"><i class="fa fa-line-chart"></i> K rel</label>
|
|
331
|
+
<input type="text" id="node-input-kRel" placeholder="0.3">
|
|
332
|
+
</div>
|
|
333
|
+
|
|
334
|
+
<div class="form-row bess-control-tracking-param">
|
|
335
|
+
<label for="node-input-deadbandW"><i class="fa fa-arrows-h"></i> Deadband (W)</label>
|
|
336
|
+
<input type="text" id="node-input-deadbandW" placeholder="1000">
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<div class="form-row bess-control-tracking-param">
|
|
340
|
+
<label for="node-input-staleTimeoutMs"><i class="fa fa-shield"></i> Stale timeout (ms)</label>
|
|
341
|
+
<input type="text" id="node-input-staleTimeoutMs" placeholder="5000">
|
|
342
|
+
</div>
|
|
343
|
+
|
|
344
|
+
<div class="form-row">
|
|
345
|
+
<label for="node-input-socMinPct"><i class="fa fa-battery-empty"></i> SOC min (%)</label>
|
|
346
|
+
<input type="text" id="node-input-socMinPct" placeholder="optional, ex 30">
|
|
347
|
+
</div>
|
|
348
|
+
|
|
349
|
+
<div class="form-row">
|
|
350
|
+
<label for="node-input-socHystPct"><i class="fa fa-level-up"></i> SOC hyst + (%)</label>
|
|
351
|
+
<input type="text" id="node-input-socHystPct" placeholder="optional, ex 5">
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
|
|
355
|
+
<div class="form-row bess-checkbox-row">
|
|
356
|
+
<label for="node-input-bessOff"><i class="fa fa-stop-circle"></i> BESS off</label>
|
|
357
|
+
<input type="checkbox" id="node-input-bessOff">
|
|
358
|
+
<span class="bess-inline-note">Forteaza comanda totala la 0 W si dezactiveaza controlul extern.</span>
|
|
359
|
+
</div>
|
|
360
|
+
|
|
361
|
+
<div class="form-row bess-checkbox-row">
|
|
362
|
+
<label for="node-input-enableDebugOutput"><i class="fa fa-bug"></i> Debug output</label>
|
|
363
|
+
<input type="checkbox" id="node-input-enableDebugOutput">
|
|
364
|
+
<span class="bess-inline-note">Adauga o a doua iesire cu diagnostic intern.</span>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
<div class="form-row bess-checkbox-row">
|
|
368
|
+
<label for="node-input-expertMode"><i class="fa fa-wrench"></i> Custom fields</label>
|
|
369
|
+
<input type="checkbox" id="node-input-expertMode">
|
|
370
|
+
<span class="bess-inline-note">Afiseaza maparea de path doar cand vrei sa schimbi valorile implicite.</span>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<div id="node-bess-control-expert-panel" style="display:none;">
|
|
374
|
+
<div class="bess-section-title"><i class="fa fa-code-fork"></i> Expert Mapping</div>
|
|
375
|
+
<p class="bess-section-note">Valorile sunt precompletate pentru mesajele standard venite din <code>carlo-gavazzi</code> sau <code>multi-grid</code>. Modifica-le doar daca folosesti alta structura de payload.</p>
|
|
376
|
+
|
|
377
|
+
<div class="form-row" id="node-bess-control-grid-path-row" style="display:none;">
|
|
378
|
+
<label for="node-input-gridPowerPath"><i class="fa fa-plug"></i> Grid power path</label>
|
|
379
|
+
<input type="text" id="node-input-gridPowerPath" placeholder="payload.power_w">
|
|
380
|
+
</div>
|
|
381
|
+
|
|
382
|
+
<div id="node-bess-control-phase-paths" style="display:none;">
|
|
383
|
+
<div class="form-row">
|
|
384
|
+
<label for="node-input-phasePowerPathL1"><i class="fa fa-bolt"></i> L1 power path</label>
|
|
385
|
+
<input type="text" id="node-input-phasePowerPathL1" placeholder="payload.power_l1_w">
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<div class="form-row">
|
|
389
|
+
<label for="node-input-phasePowerPathL2"><i class="fa fa-bolt"></i> L2 power path</label>
|
|
390
|
+
<input type="text" id="node-input-phasePowerPathL2" placeholder="payload.power_l2_w">
|
|
391
|
+
</div>
|
|
392
|
+
|
|
393
|
+
<div class="form-row">
|
|
394
|
+
<label for="node-input-phasePowerPathL3"><i class="fa fa-bolt"></i> L3 power path</label>
|
|
395
|
+
<input type="text" id="node-input-phasePowerPathL3" placeholder="payload.power_l3_w">
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
|
|
400
|
+
<div class="form-row">
|
|
401
|
+
<label></label>
|
|
402
|
+
<div class="bess-summary">Iesiri active: <span id="node-bess-control-outputs-info">1</span></div>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
</div>
|
|
407
|
+
|
|
408
|
+
</script>
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
<script type="text/html" data-help-name="bess-control">
|
|
412
|
+
|
|
413
|
+
<p>
|
|
414
|
+
Nodul <b>bess-control</b> calculeaza doar comanda totala a BESS-ului pe baza referintei de retea.
|
|
415
|
+
</p>
|
|
416
|
+
|
|
417
|
+
<h3>Flux recomandat</h3>
|
|
418
|
+
<pre>carlo-gavazzi -> bess-control -> multi-battery -> pylontech-write (x N)</pre>
|
|
419
|
+
|
|
420
|
+
<h3>Moduri</h3>
|
|
421
|
+
<ul>
|
|
422
|
+
<li><b>Grid setpoint</b>: urmareste un setpoint scalar de retea</li>
|
|
423
|
+
<li><b>Nominal power</b>: trimite mai departe o putere fixa, independenta de retea</li>
|
|
424
|
+
<li><b>Zero feed-in relativ</b>: urmareste 0W pe suma fazelor</li>
|
|
425
|
+
<li><b>Zero feed-in absolut</b>: foloseste puterile L1/L2/L3 si limiteaza compensarea dupa faza cea mai apropiata de zero</li>
|
|
426
|
+
</ul>
|
|
427
|
+
|
|
428
|
+
<h3>Parametri</h3>
|
|
429
|
+
<ul>
|
|
430
|
+
<li><b>K rel</b>: factorul de reactie. <code>1.0</code> urmareste integral eroarea calculata, valori mai mici fac reglajul mai bland.</li>
|
|
431
|
+
<li><b>Deadband</b>: zona in jurul lui 0W in care nodul nu mai modifica setpoint-ul.</li>
|
|
432
|
+
<li><b>Nominal power</b>: putere fixa in W, pozitiva pentru descarcare si negativa pentru incarcare.</li>
|
|
433
|
+
<li><b>SOC min</b>: prag minim global optional trimis catre <code>multi-battery</code>. Daca este setat, toate bateriile folosesc acest minim in locul pragului local.</li>
|
|
434
|
+
<li><b>SOC hyst +</b>: histerezis global optional, exprimat ca diferenta peste <code>SOC min</code>. Exemplu: <code>SOC min = 30</code> si <code>SOC hyst + = 5</code> inseamna ca descarcarea se opreste la 30% si se repermite abia la 35%.</li>
|
|
435
|
+
<li><b>External control</b>: este trimis implicit pe iesirea principala pentru orice comanda valida. In utilizarea normala, nodul produce mereu <code>payload.external_control = true</code> impreuna cu <code>power_w</code>.</li>
|
|
436
|
+
<li><b>BESS off</b>: are prioritate peste toate celelalte setari. Forteaza <code>power_w = 0</code> si seteaza <code>external_control = false</code>.</li>
|
|
437
|
+
</ul>
|
|
438
|
+
|
|
439
|
+
<h3>External Control</h3>
|
|
440
|
+
<p>Nodul trimite implicit <code>payload.external_control = true</code> impreuna cu <code>power_w</code>. Asta este comportamentul corect pentru lantul <code>bess-control -> multi-battery -> pylontech-write</code>, pentru ca o comanda de putere fara control extern nu are efect practic asupra bateriei.</p>
|
|
441
|
+
|
|
442
|
+
<p>In regim normal, iesirea principala contine:</p>
|
|
443
|
+
<pre>{
|
|
444
|
+
"topic": "bess/setpoint",
|
|
445
|
+
"payload": {
|
|
446
|
+
"external_control": true,
|
|
447
|
+
"power_w": 18000
|
|
448
|
+
}
|
|
449
|
+
}</pre>
|
|
450
|
+
|
|
451
|
+
<p>Singula exceptie este cazul in care activezi <b>BESS off</b>. Atunci nodul trimite explicit oprirea BESS-ului:</p>
|
|
452
|
+
<pre>{
|
|
453
|
+
"topic": "bess/setpoint",
|
|
454
|
+
"payload": {
|
|
455
|
+
"external_control": false,
|
|
456
|
+
"power_w": 0
|
|
457
|
+
}
|
|
458
|
+
}</pre>
|
|
459
|
+
|
|
460
|
+
<p>Practic:</p>
|
|
461
|
+
<ul>
|
|
462
|
+
<li>pentru orice comanda normala, nodul cere control extern automat</li>
|
|
463
|
+
<li>nu mai exista riscul sa trimiti doar <code>power_w</code> fara <code>external_control</code></li>
|
|
464
|
+
<li><b>BESS off</b> este mecanismul explicit prin care dezactivezi controlul extern si fortezi 0W</li>
|
|
465
|
+
</ul>
|
|
466
|
+
|
|
467
|
+
<p>Asta este util din doua motive:</p>
|
|
468
|
+
<ul>
|
|
469
|
+
<li>elimina o configurare care in practica produce comenzi inutile daca este oprita accidental</li>
|
|
470
|
+
<li>face iesirea nodului coerenta cu modul real in care `pylontech-write` asteapta comenzile</li>
|
|
471
|
+
</ul>
|
|
472
|
+
|
|
473
|
+
<p><b>Important:</b> daca activezi <b>BESS off</b>, aceasta setare castiga intotdeauna. In acel caz nodul va trimite comanda de oprire, adica <code>power_w = 0</code> si <code>external_control = false</code>.</p>
|
|
474
|
+
|
|
475
|
+
<h3>Exemple</h3>
|
|
476
|
+
<p><b>Grid setpoint</b> cu <code>gridSetpointW = 5000</code>:</p>
|
|
477
|
+
<pre>{
|
|
478
|
+
"payload": {
|
|
479
|
+
"power_w": 8200
|
|
480
|
+
}
|
|
481
|
+
}</pre>
|
|
482
|
+
<p>Nodul va cere descarcare ca sa coboare consumul din retea spre <code>5000W</code>.</p>
|
|
483
|
+
|
|
484
|
+
<p><b>Nominal power</b> cu <code>nominalPowerW = -6000</code>:</p>
|
|
485
|
+
<pre>{
|
|
486
|
+
"payload": {
|
|
487
|
+
"power_w": -6000,
|
|
488
|
+
"external_control": true
|
|
489
|
+
}
|
|
490
|
+
}</pre>
|
|
491
|
+
<p>Nodul trimite constant comanda de incarcare la <code>6kW</code>, indiferent de meter.</p>
|
|
492
|
+
|
|
493
|
+
<p><b>Zero feed-in relativ</b>:</p>
|
|
494
|
+
<pre>{
|
|
495
|
+
"payload": {
|
|
496
|
+
"power_w": 1200,
|
|
497
|
+
"power_l1_w": 1000,
|
|
498
|
+
"power_l2_w": 3000,
|
|
499
|
+
"power_l3_w": -2800
|
|
500
|
+
}
|
|
501
|
+
}</pre>
|
|
502
|
+
<p>Urmarirea se face dupa suma fazelor, deci tinta este sa aduca <code>power_w</code> spre <code>0W</code>.</p>
|
|
503
|
+
|
|
504
|
+
<p><b>Zero feed-in absolut</b>:</p>
|
|
505
|
+
<pre>{
|
|
506
|
+
"payload": {
|
|
507
|
+
"power_w": 6000,
|
|
508
|
+
"power_l1_w": 1000,
|
|
509
|
+
"power_l2_w": 3000,
|
|
510
|
+
"power_l3_w": 2000
|
|
511
|
+
}
|
|
512
|
+
}</pre>
|
|
513
|
+
<p>Faza limitativa este <code>L1 = 1000W</code>. Cu <code>K rel = 1</code>, nodul cere aproximativ <code>3000W</code> descarcare, pentru a evita ca L1 sa treaca in export.</p>
|
|
514
|
+
|
|
515
|
+
<p>Regula in <b>0 absolut</b> este aceasta:</p>
|
|
516
|
+
<ul>
|
|
517
|
+
<li>daca bateria se descarca, nu este permis export pe nicio faza; daca apare export pe o faza, nodul reduce descarcarea</li>
|
|
518
|
+
<li>daca bateria se incarca, nu este permis import pe nicio faza; daca apare import pe o faza, nodul reduce incarcarea</li>
|
|
519
|
+
</ul>
|
|
520
|
+
|
|
521
|
+
<p>Exemplu pentru descarcare: daca bateria descarca cu <code>10kW</code> si una dintre faze intra pe export, chiar daca celelalte doua faze inca importa, nodul reduce descarcarea pana cand faza care exporta revine spre <code>0W</code>.</p>
|
|
522
|
+
|
|
523
|
+
<h3>Output</h3>
|
|
524
|
+
<p>Iesirea principala produce comanda totala pentru nodul <code>multi-battery</code>.</p>
|
|
525
|
+
|
|
526
|
+
<pre>{
|
|
527
|
+
"topic": "bess/setpoint",
|
|
528
|
+
"payload": {
|
|
529
|
+
"external_control": true,
|
|
530
|
+
"power_w": 18000
|
|
531
|
+
}
|
|
532
|
+
}</pre>
|
|
533
|
+
|
|
534
|
+
<p>Daca <b>Debug Output</b> este activ, nodul adauga o a doua iesire cu diagnostic.</p>
|
|
535
|
+
|
|
536
|
+
<p>Pe iesirea de debug poti vedea usor diferenta dintre puterea calculata si flag-ul de control. In mod normal:</p>
|
|
537
|
+
<ul>
|
|
538
|
+
<li><code>power_w</code> reprezinta comanda totala calculata de algoritm</li>
|
|
539
|
+
<li><code>external_control</code> este in mod normal <code>true</code> si devine <code>false</code> doar in mod de oprire fortata</li>
|
|
540
|
+
<li><code>bess_off</code> arata daca nodul a fortat oprirea BESS-ului</li>
|
|
541
|
+
</ul>
|
|
542
|
+
|
|
543
|
+
<p>Recomandarea practica este aceasta:</p>
|
|
544
|
+
<ul>
|
|
545
|
+
<li>foloseste nodul ca sursa unica de comanda si lasa <code>external_control</code> sa fie trimis automat</li>
|
|
546
|
+
<li>daca vrei oprire fortata, foloseste <b>BESS off</b></li>
|
|
547
|
+
<li>daca vrei doar monitorizare, separa flow-ul de debug de flow-ul care merge in <code>pylontech-write</code></li>
|
|
548
|
+
</ul>
|
|
549
|
+
|
|
550
|
+
<h3>Referinta completa parametri</h3>
|
|
551
|
+
<ul>
|
|
552
|
+
<li><code>controlMode</code>: alege algoritmul: grid setpoint, nominal power sau BESS off.</li>
|
|
553
|
+
<li><code>zeroFeedInMode</code>: stabileste daca zero feed-in este relativ pe suma fazelor sau absolut pe faza limitativa.</li>
|
|
554
|
+
<li><code>signConvention</code>: defineste semnul puterii de retea folosit de meter.</li>
|
|
555
|
+
<li><code>gridPowerPath</code>: calea din payload pentru puterea activa totala a retelei.</li>
|
|
556
|
+
<li><code>gridSetpointW</code>: tinta de import/export in W pentru modul grid setpoint.</li>
|
|
557
|
+
<li><code>nominalPowerW</code>: comanda fixa in W pentru modul nominal power.</li>
|
|
558
|
+
<li><code>kRel</code>: factorul proportional folosit la calculul comenzii relative.</li>
|
|
559
|
+
<li><code>deadbandW</code>: zona moarta in W in care nu se modifica comanda.</li>
|
|
560
|
+
<li><code>staleTimeoutMs</code>: varsta maxima acceptata pentru telemetrie.</li>
|
|
561
|
+
<li><code>socMinPct</code>: SOC minim sub care descarcarea este blocata.</li>
|
|
562
|
+
<li><code>socHystPct</code>: histerezis peste SOC minim pentru reluarea descarcarii.</li>
|
|
563
|
+
<li><code>phasePowerPathL1</code>, <code>phasePowerPathL2</code>, <code>phasePowerPathL3</code>: cai pentru puterea pe faze, folosite in zero feed-in absolut.</li>
|
|
564
|
+
<li><code>bessOff</code>: fortare oprire BESS, cu <code>power_w = 0</code> si control extern dezactivat.</li>
|
|
565
|
+
<li><code>outputTopic</code>: topic-ul mesajului emis catre <code>multi-battery</code>.</li>
|
|
566
|
+
<li><code>enableDebugOutput</code>: adauga iesire suplimentara de diagnostic.</li>
|
|
567
|
+
</ul>
|
|
568
|
+
|
|
569
|
+
</script>
|