node-red-contrib-me-vplc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +42 -0
  2. package/me-vplc.html +64 -0
  3. package/me-vplc.js +603 -0
  4. package/package.json +26 -0
  5. package/project/README.md +1052 -0
  6. package/project/START_ME_VPLC.cmd +176 -0
  7. package/project/backend/active_project.json +3 -0
  8. package/project/backend/app.py +839 -0
  9. package/project/backend/connector_runtime.py +585 -0
  10. package/project/backend/requirements.txt +3 -0
  11. package/project/backend/st_compiler.py +1415 -0
  12. package/project/frontend/index.html +12 -0
  13. package/project/frontend/package.json +18 -0
  14. package/project/frontend/src/App.jsx +631 -0
  15. package/project/frontend/src/style.css +964 -0
  16. package/project/frontend/vite.config.js +14 -0
  17. package/wheelhouse/Flask_Cors-4.0.1-py2.py3-none-any.whl +0 -0
  18. package/wheelhouse/blinker-1.9.0-py3-none-any.whl +0 -0
  19. package/wheelhouse/click-8.3.3-py3-none-any.whl +0 -0
  20. package/wheelhouse/colorama-0.4.6-py2.py3-none-any.whl +0 -0
  21. package/wheelhouse/flask-3.0.3-py3-none-any.whl +0 -0
  22. package/wheelhouse/itsdangerous-2.2.0-py3-none-any.whl +0 -0
  23. package/wheelhouse/jinja2-3.1.6-py3-none-any.whl +0 -0
  24. package/wheelhouse/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl +0 -0
  25. package/wheelhouse/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +0 -0
  26. package/wheelhouse/markupsafe-3.0.3-cp310-cp310-win_amd64.whl +0 -0
  27. package/wheelhouse/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl +0 -0
  28. package/wheelhouse/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +0 -0
  29. package/wheelhouse/markupsafe-3.0.3-cp311-cp311-win_amd64.whl +0 -0
  30. package/wheelhouse/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl +0 -0
  31. package/wheelhouse/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +0 -0
  32. package/wheelhouse/markupsafe-3.0.3-cp312-cp312-win_amd64.whl +0 -0
  33. package/wheelhouse/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl +0 -0
  34. package/wheelhouse/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +0 -0
  35. package/wheelhouse/markupsafe-3.0.3-cp313-cp313-win_amd64.whl +0 -0
  36. package/wheelhouse/pymodbus-3.6.9-py3-none-any.whl +0 -0
  37. package/wheelhouse/werkzeug-3.1.8-py3-none-any.whl +0 -0
@@ -0,0 +1,1052 @@
1
+ # EFUSE Parallel-Fast-Path V3 - 2026-05-10
2
+
3
+ Diese Version optimiert `FB_EFuseControl.st` erneut, weil die bisherige Optimized-Variante trotz Stabilisierung weiterhin seriell über `ActiveChannel` gearbeitet hat. Dadurch konnten bei mehreren gleichzeitig angeforderten Kanälen weiterhin unnötige 650-ms-Schritte nacheinander entstehen.
4
+
5
+ ## Umsetzung
6
+
7
+ - `Optimized` und `Optimized_V2` enthalten jetzt die neue EFUSE-Parallel-Logik.
8
+ - `Original` bleibt unverändert als Referenz.
9
+ - Aktives Projekt ist auf `Optimized_V2` gesetzt.
10
+ - Die serielle `ActiveChannel`-Kaskade wurde entfernt.
11
+ - Die sieben verschachtelten `FB_EFuseChannel`-Instanzen wurden aus dem Laufzeitpfad entfernt.
12
+ - Jeder Kanal wird in jedem PLC-Zyklus direkt bewertet.
13
+ - Alle benötigten Kanäle erhalten im selben PLC-Zyklus ihr `CTLx`-/`ONx`-Signal.
14
+ - Jeder Kanal besitzt weiterhin eine eigene 650-ms-Impulsbegrenzung über `TON`.
15
+ - Sobald das jeweilige `PWR`-Feedback zum gewünschten Zustand passt, fällt `WAITx`, `CTLx` und `ONx` ohne zusätzlichen Zwischenzyklus ab.
16
+ - Vorherige unnötige Rückschreibungen `EFuseControl.WAITx := LDC.LDSCx.WAIT` vor dem FB-Aufruf wurden entfernt.
17
+
18
+ ## Erwarteter Effekt
19
+
20
+ Mehrere gleichzeitige EFUSE-Anforderungen werden nicht mehr nacheinander abgearbeitet. Statt bisher im schlechtesten Fall bis zu 7 × 650 ms laufen die Kanalimpulse parallel. Die reale Dauer wird damit im Wesentlichen durch den langsamsten Kanal bzw. dessen Feedback bestimmt, nicht mehr durch die Summe aller Kanäle.
21
+
22
+ ## Prüfung
23
+
24
+ - `Optimized` kompiliert und führt aus.
25
+ - `Optimized_V2` kompiliert und führt aus.
26
+ - Direkter EFUSE-Test mit sieben gleichzeitigen ON-Anforderungen setzt `CTL1..CTL7`, `ON1..ON7`, `WAIT1..WAIT7` und `CommonON` im ersten Zyklus parallel auf TRUE.
27
+ - Bei einzeln eintreffendem Feedback fallen die betroffenen Kanäle separat wieder ab, ohne andere Kanäle zu blockieren.
28
+
29
+ ---
30
+
31
+ # Optimized_V2
32
+
33
+ Dieses Projekt enthält jetzt eine dritte auswählbare Projektvariante:
34
+
35
+ 1. `Original`
36
+ 2. `Optimized`
37
+ 3. `Optimized_V2`
38
+
39
+ `Optimized_V2` wurde als neue Arbeitsbasis ergänzt, ohne `Original` oder `Optimized` zu verändern. Die Variante ist logisch am Original ausgerichtet und nutzt die bereits stabilisierte, modulare EFUSE-Struktur als Grundlage. Ziel ist, weitere Optimierungen am Gesamtprojekt nachvollziehbar und getrennt vom Original fortzuführen.
40
+
41
+ ## Umsetzung in Optimized_V2
42
+
43
+ - eigener Projektordner: `backend/projects/Optimized_V2/`
44
+ - eigenes ST-Projekt-ZIP: `backend/projects/Optimized_V2/st_project/example_project.zip`
45
+ - eigener PLC-Connector: `backend/projects/Optimized_V2/connector/example_connector.zip`
46
+ - `DEFAULT_PROJECT_NAMES` im Backend erweitert
47
+ - aktives Projekt auf `Optimized_V2` gesetzt
48
+ - ST-Projekt wurde gegen den aktuellen Compiler kompiliert und ausgeführt
49
+ - `Original` bleibt unverändert als Referenz
50
+ - `Optimized` bleibt unverändert als bisherige Zwischenstufe
51
+
52
+ ## Fachliche Leitlinie
53
+
54
+ Optimized_V2 soll keine fachlichen Zustandsbedingungen verändern. Optimierungen werden nur dann übernommen, wenn sie die Original-Logik funktional erhalten und die Ausführung robuster oder deterministischer machen. EFUSE ist deshalb modularisiert/stabilisiert, während die übrigen Bausteine zunächst als funktionale Referenzbasis erhalten bleiben.
55
+
56
+ ---
57
+
58
+ # Multiprojekt-Fähigkeit
59
+
60
+ Die Anwendung unterstützt jetzt mehrere übergeordnete Projektordner. Standardmäßig werden zwei Projektbereiche angelegt:
61
+
62
+ 1. `Original`
63
+ 2. `Optimized`
64
+
65
+ Die Projektdaten liegen unter:
66
+
67
+ ```text
68
+ backend/projects/Original/st_project/
69
+ backend/projects/Original/connector/
70
+ backend/projects/Optimized/st_project/
71
+ backend/projects/Optimized/connector/
72
+ ```
73
+
74
+ Über die Dropdownliste im Frontend kann das aktive Projekt ausgewählt werden. Ein Projektwechsel ist nur bei PLC STOP möglich. Beim Wechsel werden ST-Projekt und PLC Connector des gewählten Projektordners geladen und das ST-Projekt neu kompiliert.
75
+
76
+ ---
77
+
78
+ # ME vPLC Anwendung - Projektdokumentation
79
+
80
+ Diese Datei fasst alle bisherigen Markdown-Dokumentationen des Projekts zusammen.
81
+
82
+
83
+ ---
84
+
85
+ ## AUTO_ZYKLUS_README.md
86
+
87
+
88
+ # Auto-Zyklus
89
+
90
+ Der Dashboard-Schalter **Auto-Zyklus** ersetzt die ursprünglich angedachte Bezeichnung "Autoteach".
91
+
92
+ ## Funktion
93
+
94
+ Wenn Auto-Zyklus aktiv ist, stellt das Backend die `PLC Cycle Time [ms]` automatisch anhand der realen Bearbeitungszeit ein:
95
+
96
+ ```text
97
+ Ø reale PLC-Zeit = READ.avg + EXECUTE.avg + WRITE.avg
98
+ PLC Cycle Time = ceil(Ø reale PLC-Zeit * 1.20 + 2 ms)
99
+ ```
100
+
101
+ `SYNC` wird bewusst nicht eingerechnet, weil `SYNC` nur die Wartezeit bis zum Soll-Zyklus ist.
102
+
103
+ ## Manuelle Einstellung
104
+
105
+ Wenn Auto-Zyklus deaktiviert ist, kann `PLC Cycle Time [ms]` wieder manuell gesetzt werden. Beim manuellen Übernehmen wird Auto-Zyklus automatisch deaktiviert.
106
+
107
+ ## Dashboard
108
+
109
+ Die Beispielmeldung zum ST-Compiler wird nicht mehr im Dashboard angezeigt. Der Compiler-Log bleibt weiterhin als Datei erhalten:
110
+
111
+ ```text
112
+ backend/logs/st_compiler.log
113
+ ```
114
+
115
+
116
+ ---
117
+
118
+ ## COMPILER_FIX_CASE_ASSIGNMENT.md
119
+
120
+
121
+ # Compiler-Fix: CASE-Zuweisungen in FB_EFuseControl
122
+
123
+ ## Problem
124
+ Bei kompakten CASE-Zweigen mit mehreren Anweisungen, z. B.
125
+
126
+ ```st
127
+ 0: CTL1 := ctrl; WAIT1 := wait;
128
+ ```
129
+
130
+ wurde die zweite Anweisung `WAIT1 := wait` im CASE-Parser fälschlich als neues CASE-Label `WAIT1:` interpretiert, weil der Doppelpunkt aus `:=` erkannt wurde.
131
+
132
+ Dadurch entstand intern eine ungültige Rest-Anweisung:
133
+
134
+ ```text
135
+ = wait
136
+ ```
137
+
138
+ Sobald der EFuse-Zweig nach Ablauf des Timers aktiv wurde, brach die Runtime mit einem ST-Compilerfehler ab und die PLC ging auf STOP.
139
+
140
+ ## Korrektur
141
+ Der CASE-Parser erkennt Labels jetzt nur noch an Doppelpunkten, die nicht Teil des Zuweisungsoperators `:=` sind.
142
+
143
+ Zusätzlich werden kompakte CASE-ELSE-Zweige wie `ELSE CURRENT := 0;` korrekt als Default-Zweig verarbeitet.
144
+
145
+ ## Test
146
+ Das Example-Projekt wurde mit aktivem LDSC/EFuse-Zweig über mehrere Zyklen inkl. Timer-Ablauf getestet. Die Runtime bleibt im RUN.
147
+
148
+
149
+ ---
150
+
151
+ ## COMPILER_FIX_EFUSE.md
152
+
153
+
154
+ # Compiler-Fix: Example-Projekt / EFuse
155
+
156
+ ## Ursache
157
+
158
+ Im optimierten ST-Compiler gab es zwei relevante Probleme bei verschachtelten Function-Block-Instanzen:
159
+
160
+ 1. **CASE-Zweige mit Inline-Anweisungen wurden nicht korrekt erkannt**
161
+
162
+ Beispiel aus `FB_EFuseControl.st`:
163
+
164
+ ```st
165
+ CASE CURRENT OF
166
+ 0: req := IN1; pwr := P1; wait := WAIT1;
167
+ 1: req := IN2; pwr := P2; wait := WAIT2;
168
+ END_CASE
169
+ ```
170
+
171
+ Der Compiler hat bisher nur CASE-Labels erkannt, die allein auf einer Zeile standen, z. B. `0:`. Dadurch wurden `req`, `pwr` und `wait` für den aktuellen EFuse-Kanal nicht sauber übernommen.
172
+
173
+ 2. **FB-Eingänge wurden nach Attribut-Zuweisungen nicht immer in die Runtime-Umgebung synchronisiert**
174
+
175
+ Beispiel aus `FB_CSC.st`:
176
+
177
+ ```st
178
+ LDC.Enabled := TRUE;
179
+ EFuseControl.IN1 := LDC.LDSC1.EFuseControl;
180
+ EFuseControl.P1 := LDC.LDSC1.LineTripped;
181
+ ```
182
+
183
+ Die Werte wurden zwar am FB-Objekt gesetzt, aber eine bereits erzeugte interne Runtime-Umgebung des FB konnte noch alte Werte enthalten. Dadurch lief z. B. `LDC`, `LDSC` oder `EFuseControl` mit veralteten Eingängen weiter.
184
+
185
+ ## Umsetzung
186
+
187
+ - CASE-Parser erweitert für Inline-Labels wie `0: req := IN1` oder `BCC_OFF: ...`.
188
+ - `FunctionBlockInstance.__setattr__()` synchronisiert nun automatisch die Runtime-Umgebung.
189
+ - `STRuntime.set_target()` synchronisiert Attribut-Zuweisungen zusätzlich abgesichert.
190
+
191
+ ## Verifiziert
192
+
193
+ Getestet mit dem enthaltenen `example_project.zip`:
194
+
195
+ - `CSC` geht in Start-/Limited-State.
196
+ - `LDC.Enabled` wird korrekt in der LDC-Runtime wirksam.
197
+ - `LDSC1` geht bei PushButtonOn in `LDSC_CLOSING`.
198
+ - `LDSC1.EFuseControl = 3` wird korrekt an `EFuseControl.IN1` übergeben.
199
+ - `EFuseControl.CTL1` und `EFuseControl.CommonON` werden aktiv.
200
+
201
+
202
+ ---
203
+
204
+ ## COMPILER_LOG_README.md
205
+
206
+
207
+ # Compiler Log
208
+
209
+ Diese Version ergänzt einen sichtbaren Compiler-Log im Dashboard.
210
+
211
+ ## Enthaltene Informationen
212
+
213
+ - geladene ST-Quelldateien
214
+ - Anzahl Zeichen und Zeilen je Datei
215
+ - zusammengeführte Quellen
216
+ - entfernte Kommentare
217
+ - ausgewertete Datentypen, Aliase und Konstanten
218
+ - globale Deklarationen
219
+ - erkannte POUs: PROGRAM, FUNCTION_BLOCK, FUNCTION
220
+ - ausgewähltes Main-PROGRAM
221
+ - vorbereitete Variablen und Anweisungen je POU
222
+ - Abschlussmeldung der optimierten Runtime
223
+ - Runtime-Fehler im PLC-Zyklus werden ebenfalls in den Log geschrieben
224
+
225
+ ## Datei-Log
226
+
227
+ Zusätzlich zum Dashboard schreibt das Backend den Compiler-Log nach:
228
+
229
+ ```text
230
+ backend/logs/st_compiler.log
231
+ ```
232
+
233
+ Der API-Endpunkt ist:
234
+
235
+ ```text
236
+ GET /api/compiler-log
237
+ ```
238
+
239
+
240
+ ---
241
+
242
+ ## MODBUS_CONNECTOR_README.md
243
+
244
+
245
+ # Modbus TCP Connector Runtime
246
+
247
+ Diese Version interpretiert den importierten Connector `ModbusTCP_57108.json` funktional.
248
+
249
+ ## Ablauf im PLC-Zyklus
250
+
251
+ 1. **READ**
252
+ - Modbus TCP Verbindung zu `ip:port`, Unit-ID aus `unit.address`.
253
+ - READ-Variablen werden nach Registertyp und zusammenhängenden Adressen gebündelt.
254
+ - Werte werden in das ST-Prozessabbild geschrieben.
255
+ - Beispiel: `CSC_BCM_BatteryTemp1` wird automatisch auf `CSC.BCM.BatteryTemp1` gemappt.
256
+
257
+ 2. **EXECUTE**
258
+ - ST-Runtime verarbeitet das Programm mit den gelesenen Modbus-Werten.
259
+
260
+ 3. **WRITE**
261
+ - WRITE-Variablen werden aus dem ST-Prozessabbild gelesen.
262
+ - Beispiel: `CSC_LEDC_Line1Green` wird automatisch aus `CSC.LEDC.Line1Green` gelesen.
263
+ - Coils werden zusammenhängend gebündelt.
264
+ - Coils werden nur geschrieben, wenn sich Werte geändert haben.
265
+
266
+ ## Unterstützte Registertypen
267
+
268
+ - `DiscreteInput` lesen
269
+ - `Coil` lesen/schreiben
270
+ - `InputRegister` lesen
271
+ - `HoldingRegister` lesen/schreiben
272
+
273
+ ## Unterstützte Datentypen
274
+
275
+ - `BOOL`
276
+ - `BYTE`, `WORD`, `DWORD`
277
+ - `INT`, `UINT`, `DINT`, `UDINT`
278
+ - `REAL`
279
+
280
+ ## Kommunikationsverhalten
281
+
282
+ Bei Verbindungsfehlern stoppt die PLC nicht sofort. Der Connector wird als offline markiert und versucht nach einem kurzen Backoff erneut zu verbinden. Dadurch blockiert eine nicht erreichbare Modbus-Station nicht dauerhaft den PLC-Zyklus.
283
+
284
+ ## Dashboard
285
+
286
+ Im Importbereich wird nun zusätzlich angezeigt:
287
+
288
+ - Modbus Endpoint
289
+ - Verbindungsstatus
290
+ - Anzahl READ-/WRITE-Variablen
291
+ - Anzahl gebündelter READ-/WRITE-Requests
292
+ - letzter Connector-Fehler
293
+
294
+
295
+ ---
296
+
297
+ ## MODBUS_WRITE_FIX.md
298
+
299
+
300
+ # Modbus WRITE Fix / Verhalten
301
+
302
+ Das Dashboard zeigte bisher `WRITE Requests: 0`, weil dieser Wert nur den letzten PLC-Zyklus dargestellt hat und die Runtime aus Performance-Gründen nur bei Wertänderung schreibt.
303
+
304
+ Anpassung:
305
+
306
+ - Beim PLC-Start wird ein erster WRITE-Zyklus erzwungen.
307
+ - Nach Reconnect wird ein WRITE-Zyklus erzwungen.
308
+ - Zusätzlich wird standardmäßig alle 1000 ms ein WRITE-Resync ausgeführt (`writeResyncMs`).
309
+ - Das Dashboard zeigt jetzt getrennt:
310
+ - WRITE Requests letzter Zyklus
311
+ - WRITE Requests gesamt
312
+ - WRITE übersprungen letzter Zyklus
313
+ - WRITE Resync
314
+ - Letzter WRITE Grund (`changed` oder `resync`)
315
+
316
+ Damit ist erkennbar, ob tatsächlich Modbus-Schreibaktionen ausgeführt wurden, obwohl die Outputs stabil bleiben.
317
+
318
+
319
+ ---
320
+
321
+ ## PERFORMANCE_OPTIMIERUNGEN.md
322
+
323
+
324
+ # ME vPLC Performance-Optimierungen
325
+
326
+ Umgesetzt:
327
+
328
+ 1. **ST-Compiler / Runtime optimiert**
329
+ - ST-Ausdrücke werden beim ersten Auftreten in Python-Codeobjekte übersetzt und anschließend wiederverwendet.
330
+ - Die Runtime verwendet eine wiederverwendbare Ausführungsumgebung statt pro Ausdruck neue Dictionaries aufzubauen.
331
+ - PROGRAM- und FUNCTION_BLOCK-Runtimes werden wiederverwendet.
332
+
333
+ 2. **Variablenzugriff optimiert**
334
+ - Variablen werden intern synchron in Runtime-Maps geführt.
335
+ - Zuweisungen aktualisieren direkt die aktive Runtime-Umgebung.
336
+ - Keine wiederholte vollständige Environment-Erzeugung pro ST-Ausdruck.
337
+
338
+ 3. **Timer/FBs als native Runtime-Klassen**
339
+ - IEC-Bausteine wie TON, TOF, TP, R_TRIG, F_TRIG, RS, SR und CTU bleiben native Python-Klassen.
340
+ - FB-Instanzen behalten ihren Zustand über Zyklen.
341
+
342
+ 4. **Dashboard-Snapshot entkoppelt**
343
+ - Der PLC-Zyklus erzeugt fertige Status-Snapshots.
344
+ - `/api/status` liefert nur eine Kopie des letzten Snapshots zurück.
345
+ - Das Frontend kann den Status zyklisch lesen, ohne PLC-Phasen neu zu berechnen.
346
+
347
+ 5. **Trace/Debug im normalen Run deaktiviert**
348
+ - Flask startet mit `debug=False`.
349
+ - Im PLC-Zyklus werden keine Trace-Listen aufgebaut.
350
+
351
+ 6. **Statistiken ohne Listen**
352
+ - Min/Avg/Max werden laufend berechnet.
353
+ - Es werden keine wachsenden Cycle-Historien für die Phasenstatistik benötigt.
354
+
355
+ Erwarteter Effekt beim Beispielprojekt: EXECUTE reduziert sich gegenüber der interpretierenden Variante deutlich. Auf der Testumgebung sank die reine ST-Ausführungszeit des enthaltenen Beispielprojekts von ungefähr 60 ms auf ungefähr 7 ms pro Zyklus.
356
+
357
+
358
+ ---
359
+
360
+ ## README.md
361
+
362
+
363
+ # ME vPLC
364
+
365
+ Professionelle Flask + React Anwendung für eine ME vPLC Runtime.
366
+
367
+ ## Start
368
+
369
+ Unter Windows nur diese Datei ausführen:
370
+
371
+ ```bat
372
+ START_ME_VPLC.cmd
373
+ ```
374
+
375
+ Die CMD prüft/erstellt automatisch:
376
+
377
+ - Backend `.venv`
378
+ - Backend Dependencies
379
+ - Frontend Dependencies
380
+ - Backend auf `http://127.0.0.1:5000`
381
+ - Frontend auf `http://127.0.0.1:5173`
382
+
383
+ ## Funktionen
384
+
385
+ Dieses Paket enthält unter `examples/` zusätzlich die getesteten Importdateien `example_project.zip` und `example_connector.zip`.
386
+
387
+
388
+ - Start / Stop
389
+ - PLC Cycle Time
390
+ - PLC Phasen `READ`, `EXECUTE`, `WRITE`, `SYNC`
391
+ - Min / Avg / Max / Last je Phase
392
+ - Import ST Projekt
393
+ - Import Connector
394
+
395
+ ## Startlogik
396
+
397
+ - Kein ST-Projekt und kein Connector: Start gesperrt.
398
+ - ST-Projekt vorhanden, aber kein Connector: `READ = 0 ms`, `WRITE = 0 ms`, `EXECUTE = echte ST-Laufzeit`.
399
+ - Connector vorhanden, aber kein ST-Projekt: `READ`/`WRITE` aktiv, `EXECUTE = 0 ms`.
400
+ - ST-Projekt und Connector vorhanden: alle Phasen aktiv.
401
+
402
+ ## ST Compiler
403
+
404
+ Der ST Compiler wurde erweitert. Details siehe:
405
+
406
+ `ST_COMPILER_README.md`
407
+
408
+ ## Import-Test
409
+
410
+ Getestet mit dem bereitgestellten ST-Projekt inklusive `PROGRAMS`, `FUNCTION_BLOCKS`, `FUNCTIONS`, `DATATYPES` und `GLOBALS` sowie dem ModbusTCP-Connector-ZIP.
411
+
412
+
413
+ ---
414
+
415
+ ## RUNTIME_FIXES.md
416
+
417
+
418
+ # Runtime-Fixes
419
+
420
+ ## Behoben
421
+
422
+ - PLC stoppt nicht mehr direkt nach Start, wenn `example_project.zip` und `example_connector.zip` geladen sind.
423
+ - Ursache war die CASE/IF-Auswertung im ST-Compiler: `ELSE` innerhalb eines `IF` in einem `CASE`-Zweig wurde fälschlich als `CASE ELSE` interpretiert.
424
+ - Dadurch wurde der IF-Block im CASE-Zweig unvollständig ausgeführt und die Runtime meldete `IF ohne END_IF gefunden`.
425
+
426
+ ## Neues Verhalten
427
+
428
+ - ST-CASE-Blöcke können jetzt IF/ELSIF/ELSE/END_IF sauber innerhalb der CASE-Zweige enthalten.
429
+ - Offline-Modbus-Verbindung stoppt die vPLC nicht.
430
+ - Connector geht bei Verbindungsfehlern auf offline und versucht zyklisch erneut zu verbinden.
431
+ - ST-Ausführung läuft weiter, auch wenn die Modbus-Station gerade nicht erreichbar ist.
432
+
433
+ ## Test
434
+
435
+ Getestet mit:
436
+
437
+ - `example_project.zip`
438
+ - `example_connector.zip`
439
+
440
+ Ergebnis:
441
+
442
+ - Import ST-Projekt: OK
443
+ - Import Connector: OK
444
+ - Start PLC: OK
445
+ - PLC bleibt RUNNING
446
+ - Wenn Modbus TCP nicht erreichbar ist: Connector offline, PLC läuft weiter
447
+
448
+
449
+ ---
450
+
451
+ ## ST_CODE_AUDIT_REPORT.md
452
+
453
+
454
+ # ST-Code-Audit und Compiler-Abgleich
455
+
456
+ Basis: `example_project.zip` und aktueller ME-vPLC Compiler.
457
+
458
+ ## Ergebnis
459
+
460
+ Das Example-Projekt wird syntaktisch vollständig geladen und ausgeführt. Beim funktionellen Abgleich wurden jedoch drei relevante Punkte gefunden und korrigiert.
461
+
462
+ ## Gefundene Compiler-Abweichungen
463
+
464
+ ### 1. Positionsbasierte FB-Ausgänge wurden nicht zurückgeschrieben
465
+
466
+ Betroffene ST-Zeilen/Pattern:
467
+
468
+ ```st
469
+ HyUblock1BelowLowLimit(UBlock2-UBlock1, UBLOCK_HIGH_BAL_LIM, VOLTAGE_HYSTERESIS, CMP_Type#GT, Ublock1BelowLowLimit);
470
+ HYTempBelowOperRange(InternalTemperature, OPER_RANGE_LOW, TEMP_HYSTERESIS, CMP_Type#LT, TempBelowOperRange);
471
+ ```
472
+
473
+ Der letzte positionale Parameter ist hier funktionell als Ausgangsbindung zu verstehen, analog zu:
474
+
475
+ ```st
476
+ HyUblock1BelowLowLimit(
477
+ A := UBlock2-UBlock1,
478
+ B := UBLOCK_HIGH_BAL_LIM,
479
+ H := VOLTAGE_HYSTERESIS,
480
+ CMP := CMP_Type#GT,
481
+ Q => Ublock1BelowLowLimit
482
+ );
483
+ ```
484
+
485
+ Vorher wurde dieser letzte Parameter ignoriert. Dadurch waren mehrere Hysterese-/Latch-Ergebnisse in `FB_BSMSS` und `FB_TC` funktionell falsch.
486
+
487
+ Korrektur:
488
+
489
+ - Positionaler Aufruf erkennt jetzt Anzahl `VAR_INPUT` und `VAR_OUTPUT` des Ziel-FBs.
490
+ - Zusätzliche positionale Parameter werden nach dem FB-Aufruf auf die passenden `VAR_OUTPUT`-Variablen zurückgeschrieben.
491
+
492
+ Betroffene Bausteine:
493
+
494
+ - `FB_BSMSS.st`
495
+ - `FB_TC.st`
496
+ - indirekt `FB_BMS.st`, `FB_CSC.st`, LED-/EFuse-Logik
497
+
498
+ ### 2. `VAR_TEMP` wurde zyklusübergreifend gehalten
499
+
500
+ IEC-semantisch ist `VAR_TEMP` nur für den aktuellen Bausteinaufruf gültig. Der Compiler hatte `VAR_TEMP` bisher wie statische interne Variablen behandelt.
501
+
502
+ Korrektur:
503
+
504
+ - `VAR_TEMP` wird vor jedem FB-Aufruf auf Defaultwerte zurückgesetzt.
505
+ - `VAR`, `VAR_OUTPUT` und FB-Instanzen bleiben weiterhin zustandsbehaftet.
506
+
507
+ Betroffene Bausteine:
508
+
509
+ - `FB_EFuseControl.st`
510
+ - `FB_BSMSS.st`
511
+ - `FB_CompareWithLatch.st`
512
+
513
+ ### 3. Wiederverwendete Runtime-Umgebung konnte alte globale Werte behalten
514
+
515
+ Der optimierte Compiler verwendet wiederverwendete Runtime-Umgebungen. Dadurch konnten verschachtelte FBs nach HMI-/Global-Änderungen alte Werte in ihrer Eval-Umgebung behalten.
516
+
517
+ Korrektur:
518
+
519
+ - Vor jedem äußeren Program-/FB-Aufruf werden globale und lokale Werte in die Runtime-Umgebung gespiegelt.
520
+ - Dadurch sehen verschachtelte FBs aktuelle `VAR_GLOBAL`-/HMI-Werte.
521
+
522
+ ## Gefundene ST-Logik-Auffälligkeit in `FB_EFuseControl.st`
523
+
524
+ Original:
525
+
526
+ ```st
527
+ IF timer.Q THEN
528
+ ctrl := FALSE;
529
+ cmn := FALSE;
530
+ timer(IN := FALSE);
531
+ faulted := TRUE;
532
+ timerElapsed := TRUE;
533
+ END_IF
534
+
535
+ IF rst OR timer.Q THEN
536
+ wait := FALSE;
537
+ END_IF
538
+ ```
539
+
540
+ Auffälligkeit:
541
+
542
+ `timer(IN := FALSE)` setzt den TON im selben Zyklus zurück. Danach ist `timer.Q` wieder `FALSE`. Das nachfolgende `IF rst OR timer.Q THEN` setzt `wait` deshalb bei Timer-Ablauf nicht sicher zurück.
543
+
544
+ Korrektur im mitgelieferten Example-Projekt:
545
+
546
+ ```st
547
+ IF timer.Q THEN
548
+ ctrl := FALSE;
549
+ cmn := FALSE;
550
+ wait := FALSE;
551
+ timer(IN := FALSE);
552
+ faulted := TRUE;
553
+ timerElapsed := TRUE;
554
+ END_IF
555
+
556
+ IF rst OR timerElapsed THEN
557
+ wait := FALSE;
558
+ END_IF
559
+ ```
560
+
561
+ Damit wird `WAITx` bei Timer-Ablauf sauber gelöscht und in `LDC.LDSCx.WAIT` zurückgeschrieben.
562
+
563
+ ## Abgedeckte ST-Konstrukte im Example-Projekt
564
+
565
+ Im Example-Projekt wurden folgende Konstrukte erkannt und mit dem Compiler abgeglichen:
566
+
567
+ - `PROGRAM`
568
+ - `FUNCTION_BLOCK`
569
+ - `FUNCTION`
570
+ - `TYPE ... END_TYPE`
571
+ - ENUM-Typen mit und ohne expliziten Basistyp
572
+ - `VAR`, `VAR_INPUT`, `VAR_OUTPUT`, `VAR_EXTERNAL`, `VAR_GLOBAL`, `VAR_TEMP`
573
+ - Initialwerte
574
+ - HMI-Attribute `{ IN HMI }`, `{ OUT HMI }`, `{ IN INTERNAL HMI }`
575
+ - `IF`, `ELSIF`, `ELSE`, `END_IF`
576
+ - `CASE`, `ELSE`, `END_CASE`
577
+ - kompakte CASE-Zweige wie `0: A := B; C := D;`
578
+ - mehrere CASE-Labels wie `CMP_Type#LT, CMP_Type#LTE:`
579
+ - FB-Aufrufe formal mit `:=`
580
+ - FB-Ausgänge formal mit `=>`
581
+ - positionsbasierte FB-Aufrufe mit Ausgangsbindung
582
+ - Funktionsaufrufe
583
+ - verschachtelte FB-Attribute wie `CSC.LDC.LDSC1.PushButtonOn`
584
+ - Bitzugriffe wie `REQ.1`, `VIDI2OperatingMode.0`
585
+ - Zeitliterale wie `T#500ms`, `T#650ms`
586
+ - Standardfunktionen `INT_TO_REAL`, `REAL_TO_INT`
587
+
588
+ ## Testfälle
589
+
590
+ ### Compile-Test
591
+
592
+ `example_project.zip` kompiliert erfolgreich:
593
+
594
+ ```text
595
+ PROGRAM my_program
596
+ 64 Runtime-Variablen
597
+ 32 Top-Level-Anweisungen
598
+ Optimierte Runtime aktiv
599
+ ```
600
+
601
+ ### Connector-Pfad-Test
602
+
603
+ Alle 41 Variablen aus `example_connector.zip` wurden gegen das ST-Prozessabbild geprüft.
604
+
605
+ Ergebnis:
606
+
607
+ ```text
608
+ 41 / 41 Connector-Variablen auflösbar
609
+ 0 Pfadfehler
610
+ ```
611
+
612
+ ### EFuse-Funktionstest
613
+
614
+ Testfall:
615
+
616
+ - `PushButtonOn = TRUE`
617
+ - `LineTripped/PWR = FALSE`
618
+ - `EFuseControl.IN1 = 3`
619
+
620
+ Erwartetes Verhalten:
621
+
622
+ - `CTL1 = TRUE`
623
+ - `CommonON = TRUE`
624
+ - TON läuft bis `T#650ms`
625
+ - danach `CTL1 = FALSE`
626
+ - `WAIT1 = FALSE`
627
+ - PLC bleibt RUNNING
628
+
629
+ Ergebnis nach Korrektur:
630
+
631
+ ```text
632
+ CTL1 wird aktiv
633
+ CommonON wird aktiv
634
+ Timer läuft
635
+ WAIT1 wird nach Timeout gelöscht
636
+ LDC.LDSC1.WAIT wird zurückgeschrieben
637
+ Runtime bleibt ohne STOP
638
+ ```
639
+
640
+ ## Fazit
641
+
642
+ Der Compiler versteht das Example-Projekt jetzt vollständig genug für die enthaltene ST-Logik. Die wesentlichen funktionellen Abweichungen lagen nicht bei der Syntaxerkennung, sondern bei:
643
+
644
+ 1. positionalen FB-Ausgangsparametern,
645
+ 2. IEC-korrekter `VAR_TEMP`-Lebensdauer,
646
+ 3. Runtime-Synchronisation globaler Werte,
647
+ 4. einer echten ST-Logik-Auffälligkeit im EFuse-Baustein.
648
+
649
+ Diese Punkte sind in dieser Projektversion korrigiert.
650
+
651
+
652
+ ---
653
+
654
+ ## ST_COMPILER_README.md
655
+
656
+
657
+ # ME vPLC ST Compiler / Runtime
658
+
659
+ Der Compiler wurde als IEC-61131-3-orientierter ST-Interpreter erweitert.
660
+ Er ist bewusst lokal und leichtgewichtig umgesetzt und benötigt keine externe SPS-Runtime.
661
+
662
+ ## Unterstützte Programm-Organisationseinheiten
663
+
664
+ - `PROGRAM ... END_PROGRAM`
665
+ - `FUNCTION_BLOCK ... END_FUNCTION_BLOCK`
666
+ - `FUNCTION ... : <DATENTYP> ... END_FUNCTION`
667
+ - Instanzierung von Funktionsbausteinen in `VAR`, z. B. `Motor1 : FB_Motor;`
668
+ - Aufruf von FB-Instanzen mit formalen Parametern, z. B. `Motor1(Start := TRUE);`
669
+ - Zugriff auf FB-Ausgänge über Punktnotation, z. B. `Q := Motor1.Running;`
670
+
671
+ ## Unterstützte Variablenbereiche
672
+
673
+ - `VAR`
674
+ - `VAR_INPUT`
675
+ - `VAR_OUTPUT`
676
+ - `VAR_IN_OUT`
677
+ - `VAR_TEMP`
678
+ - `VAR_GLOBAL`
679
+ - `VAR CONSTANT`
680
+ - Direkte Variablen mit `AT %IX...`, `AT %QX...`, `AT %MW...` werden syntaktisch akzeptiert.
681
+
682
+ ## Unterstützte Datentypen und Literale
683
+
684
+ - `BOOL`
685
+ - `BYTE`, `WORD`, `DWORD`
686
+ - `INT`, `DINT`, `SINT`, `UINT`, `UDINT`
687
+ - `REAL`, `LREAL`
688
+ - `TIME`
689
+ - `STRING`
690
+ - `ARRAY [x..y] OF <TYPE>`
691
+ - `TYPE ... STRUCT ... END_STRUCT END_TYPE`
692
+ - Bool-Literale: `TRUE`, `FALSE`
693
+ - Zeitliterale: `T#650MS`, `T#2S`, `T#1M`, `T#1H`, `T#1D`
694
+ - Binär: `2#1010`
695
+ - Hex: `16#FF`, `B#16#FF`, `W#16#1234`, `DW#16#FFFF_FFFF`
696
+
697
+ ## Unterstützte ST-Anweisungen
698
+
699
+ - Zuweisung mit `:=`
700
+ - `IF ... THEN ... ELSIF ... ELSE ... END_IF`
701
+ - `FOR i := a TO b BY s DO ... END_FOR`
702
+ - `WHILE ... DO ... END_WHILE`
703
+ - Vergleich: `=`, `<>`, `<`, `<=`, `>`, `>=`
704
+ - Boolesche Operatoren: `AND`, `OR`, `XOR`, `NOT`
705
+ - Arithmetik: `+`, `-`, `*`, `/`, `MOD`
706
+ - Array-Zugriff: `INP[1]`, `CTL[i]`
707
+ - Struktur-/FB-Zugriff: `Instanz.Q`, `Daten.Feld`
708
+
709
+ ## Eingebaute IEC-Funktionsbausteine
710
+
711
+ - `TON`
712
+ - `TOF`
713
+ - `TP`
714
+ - `R_TRIG`
715
+ - `F_TRIG`
716
+ - `RS`
717
+ - `SR`
718
+ - `CTU`
719
+
720
+ ## Eingebaute Standardfunktionen
721
+
722
+ - `ABS`
723
+ - `MIN`
724
+ - `MAX`
725
+ - `LIMIT`
726
+ - `SEL`
727
+ - `MUX`
728
+ - `INT`, `DINT`, `REAL`, `BOOL`
729
+ - `SIN`, `COS`, `TAN`, `SQRT`
730
+
731
+ ## Grenzen
732
+
733
+ Dies ist kein zertifizierter IEC-61131-3-Compiler und erzeugt keinen nativen SPS-Maschinencode.
734
+ Es ist ein lokaler ST-Interpreter für die ME-vPLC-Simulation. Nicht enthalten sind derzeit u. a. vollständige `CASE`-Syntax, `REPEAT`, Pointer/ANY, vollständige Typprüfung, echte Hardware-Adressbindung und SFC/AS.
735
+
736
+ ## Erweiterung für das bereitgestellte Projekt
737
+
738
+ Der Compiler wurde zusätzlich auf die hochgeladenen Dateien `project.zip` und `connector.zip` getestet.
739
+
740
+ Neu abgedeckt:
741
+
742
+ - ENUM-/abgeleitete Datentypen in `TYPE ... : INT (...) END_TYPE`, z. B. `BCC_STATES`, `BCM_STATES`, `CMP_Type`
743
+ - qualifizierte ENUM-Konstanten wie `CMP_Type#GTE`
744
+ - Deklarationsattribute in geschweiften Klammern, z. B. `{ OUT HMI }`, werden toleriert
745
+ - `VAR_EXTERNAL` und `VAR_GLOBAL` mit gemeinsamem Global-Speicher
746
+ - `CASE ... OF ... END_CASE`
747
+ - mehrere CASE-Labels, z. B. `CMP_Type#LT, CMP_Type#LTE:`
748
+ - formale Parameter `:=`
749
+ - Ausgangsparameter-Mapping mit `=>`, z. B. `CTRL => ctrl1`
750
+ - nichtformale/positionale FB-Aufrufe, z. B. `HY(A, B, H, CMP_Type#GT, Q)`
751
+ - Inline-IF, z. B. `IF timer1.ET > ET THEN ET := timer1.ET; END_IF`
752
+ - Bitzugriff auf numerische Typen, z. B. `REQ.1`, `VIDI2OperatingMode.0`
753
+ - Konvertierungsfunktionen `INT_TO_REAL`, `REAL_TO_INT`, `DINT_TO_REAL`, `REAL_TO_DINT`
754
+ - Connector-Import als `.json` oder `.zip`
755
+
756
+
757
+ ## Performance-Runtime
758
+
759
+ Die Runtime wurde optimiert:
760
+
761
+ - ST-Ausdrücke werden in Python-Codeobjekte vorkompiliert und wiederverwendet.
762
+ - Variablen werden in einer wiederverwendbaren Runtime-Umgebung gehalten.
763
+ - PROGRAM- und FUNCTION_BLOCK-Runtimes werden nicht pro Zyklus neu aufgebaut.
764
+ - IEC-Timer und Standard-FBs laufen als native Python-Klassen mit persistentem Zustand.
765
+ - Dashboard-/API-Status basiert auf einem entkoppelten Snapshot.
766
+ - Flask-Debug und zyklischer Trace sind im normalen Start deaktiviert.
767
+ - Phasenstatistiken werden laufend ohne Listen berechnet.
768
+
769
+ ## Dashboard-Struktur
770
+
771
+ Die Oberfläche ist in drei Seiten aufgeteilt:
772
+
773
+ - **PLC Control**: Start/Stop, PLC Cycle Time, Auto-Zyklus und Statistik zurücksetzen.
774
+ - **PLC Connector**: Connector-Import und Modbus-/Connector-Status.
775
+ - **PLC Monitoring**: ST-Projekt-Import, Zykluskennzahlen und Phasenübersicht READ, EXECUTE, WRITE und SYNC.
776
+
777
+ Die Hauptseite enthält bewusst nur die Control-Elemente.
778
+
779
+ ## Optimized-Projekt: parallelisierte EFuse-Logik
780
+
781
+ Im Projekt `Optimized` wurde `FUNCTION_BLOCKS/FB_EFuseControl.st` angepasst.
782
+
783
+ Die bisherige sequenzielle Auswertung über `CURRENT` wurde entfernt. Stattdessen werden alle sieben EFuse-Kanäle in jedem PLC-Zyklus parallel verarbeitet:
784
+
785
+ - je Kanal ein eigener `TON`-Timer
786
+ - je Kanal eigene `CTRL`/`CMN`/`RST`-Auswertung über `FN_EFuse`
787
+ - `CTL1` bis `CTL7` werden in jedem Zyklus aktualisiert
788
+ - `CommonON` wird als Oder-Verknüpfung aller aktiven Common-Signale gebildet
789
+ - Timeout pro Kanal bleibt bei `T#650ms`
790
+
791
+ Das Projekt `Original` bleibt unverändert.
792
+
793
+ ## Optimized: EFuse 7-fach parallel
794
+
795
+ Im Projekt `Optimized` wurde `FB_EFuseControl.st` vollständig 7-fach parallelisiert:
796
+
797
+ - `IN1..IN7`, `P1..P7`
798
+ - `WAIT1..WAIT7`
799
+ - `timer1..timer7`
800
+ - `CTL1..CTL7`
801
+ - `ON1..ON7`
802
+ - `CommonON = ON1 OR ... OR ON7`
803
+
804
+ Zusätzlich wurde Kanal 4 im `FB_CSC.st` angebunden:
805
+
806
+ - `EFuseControl.IN4` aus `BCC.VIDI2PowerSupplyEFuse`
807
+ - `EFuseControl.P4` aus `BCC.FullyFunctional`
808
+
809
+ Der Optimized-Connector enthält zusätzliche WRITE-Variablen für `CTL4` und `ON1..ON7`.
810
+
811
+
812
+ ## Optimized: EFUSE-Kanalstruktur
813
+
814
+ Im Projekt `Optimized` wurde die EFUSE-Logik modularisiert:
815
+
816
+ - `FUNCTION_BLOCKS/FB_EFuseChannel.st` enthält die Logik für genau einen EFUSE-Kanal.
817
+ - `FUNCTION_BLOCKS/FB_EFuseControl.st` enthält sieben Instanzen `Ch1..Ch7` und ruft alle Kanäle in jedem PLC-Zyklus parallel auf.
818
+ - `Original` bleibt unverändert.
819
+
820
+ Damit entfällt die frühere sequenzielle `CURRENT`-Kaskade. Alle Ausgänge `CTL1..CTL7`, `ON1..ON7`, `CommonON`, `T` und `ET` werden im optimierten Projekt zyklisch aktualisiert.
821
+
822
+
823
+ ## EFUSE Optimized
824
+
825
+ Im Projekt `Optimized` ist die EFUSE-Logik modularisiert:
826
+
827
+ - `FB_EFuseChannel.st` enthält die Original-Logik für genau einen EFUSE-Kanal.
828
+ - `FB_EFuseControl.st` ruft sieben Channel-Instanzen parallel in jedem PLC-Zyklus auf.
829
+ - Das Original-Projekt bleibt unverändert.
830
+ - Die Optimierung ändert nicht die fachliche EFUSE-Entscheidungslogik, sondern entfernt nur die sequenzielle `CURRENT`/`CASE`-Abarbeitung über sieben Zyklen.
831
+
832
+
833
+ ## EFUSE Optimized - stabile 650-ms-Schaltfenster
834
+
835
+ Im Projekt `Optimized` ist die EFUSE-Logik modular aufgebaut:
836
+
837
+ - `FB_EFuseChannel.st` verarbeitet genau einen Kanal.
838
+ - `FB_EFuseControl.st` ruft sieben Kanalinstanzen parallel auf.
839
+ - Jeder Kanal latcht eine neue Schaltanforderung beim Start des Vorgangs.
840
+ - Während des laufenden 650-ms-Fensters bleiben `CTL`, `ON` und `WAIT` stabil.
841
+ - Neue IN-Wechsel werden erst nach Abschluss des aktuellen Vorgangs bewertet.
842
+
843
+ Damit wird verhindert, dass ein Ein-/Ausschalten innerhalb einer PLC-Zykluszeit den laufenden EFUSE-Schaltvorgang durcheinanderbringt. Die fachliche Bewertung von `REQ`, `PWR`, `CTRL`, `CMN` und `RST` erfolgt weiterhin über die originale Funktion `FN_EFuse`.
844
+
845
+ ## Optimized EFUSE Umsetzung
846
+
847
+ Im Multiprojekt **Optimized** wurde `FB_EFuseControl` erneut aus der Original-Logik abgeleitet und nur modularisiert/parallelisiert:
848
+
849
+ - `FB_EFuseChannel.st` bildet die originale Bearbeitung eines einzelnen `CURRENT`-Kanals nach.
850
+ - `FB_EFuseControl.st` ruft sieben Instanzen `Ch1..Ch7` in jedem PLC-Zyklus parallel auf.
851
+ - Es gibt keine zusätzliche Sonderlogik für Latching, Retrigger oder Completed-Filter.
852
+ - `Original` bleibt unverändert.
853
+
854
+ ## EFUSE Optimized Parallel Stable
855
+
856
+ Im Projekt `Optimized` wurde die EFUSE-Logik modular und parallel stabilisiert:
857
+
858
+ - `FB_EFuseChannel.st` bildet einen einzelnen EFUSE-Kanal ab.
859
+ - `FB_EFuseControl.st` ruft sieben Instanzen parallel auf.
860
+ - Jeder Kanal besitzt eigenen Zustand und eigenen Timer.
861
+ - Eine neue Anforderung wird beim Start gelatcht.
862
+ - Schnelle IN-Wechsel während eines laufenden Kanals überschreiben die laufende Logik nicht.
863
+ - `PWR` wird weiterhin live ausgewertet, damit der Zielzustand erkannt wird.
864
+ - `ON`, `CTL` und `WAIT` bleiben stabil, bis `FN_EFuse` den Abschluss meldet oder der 650-ms-Timer abläuft.
865
+
866
+ ## Änderung: entkoppelte Modbus-Kommunikation und 100-Zyklen-Statistik
867
+
868
+ - Die PLC-Phasen `READ` und `WRITE` führen keine direkten Modbus/TCP-Zugriffe mehr aus.
869
+ - Ein separater Modbus-Worker übernimmt Connect, Reconnect, READ, WRITE und Backoff.
870
+ - Der PLC-Zyklus arbeitet nur mit Eingangs- und Ausgangs-Caches.
871
+ - `Min`, `Avg` und `Max` der PLC-Phasen werden blockweise aus abgeschlossenen 100-Zyklen-Fenstern synchronisiert.
872
+ - Das Dashboard zeigt die letzte 100-Zyklen-Synchronisierung mit Zyklusnummer und Uhrzeit an.
873
+
874
+
875
+ ## Anpassung Statistik Live-Fenster
876
+
877
+ Die PLC-Phasenstatistik berechnet `min`, `avg` und `max` jetzt live aus den letzten 100 Zyklen. `Last` bleibt der aktuelle Zykluswert. Alte Ausreißer, zum Beispiel frühere Modbus-Timeouts, fallen nach 100 neuen Zyklen automatisch aus der Anzeige. Die Anzeige der letzten Synchronisierung dient nur noch als 100-Zyklen-Marker.
878
+
879
+ ## Optimized_V2
880
+
881
+ `Optimized_V2` ist eine zusätzliche Projektvariante neben `Original` und `Optimized`.
882
+
883
+ Ziel der Variante ist eine bausteinweise Optimierung, ohne das fachliche Originalverhalten zu verändern. Umgesetzt wurden aktuell:
884
+
885
+ - `FB_CSC`: zentrale Zustandsbedingungen werden einmal pro Zyklus berechnet und anschließend in der FSM verwendet.
886
+ - `FB_LDC`: Fuse-Trip-Bewertung der drei LDSC-Zweige wird einmal pro Zyklus gecacht.
887
+ - `FB_LDSC`: wiederkehrende Basisanforderungen werden einmal pro Zyklus berechnet.
888
+ - `EFUSE`: bleibt modular über `FB_EFuseChannel` und `FB_EFuseControl`, mit stabiler deterministischer Schaltfreigabe.
889
+ - `FB_LEDC`, `FB_BMS`, `FB_BCM`, `FB_BCC`: geprüft und zunächst funktionell unverändert gelassen, da dort die Reihenfolge der Zustände sicherheits- bzw. fachlogisch relevant ist.
890
+
891
+ Details stehen zusätzlich in `OPTIMIZED_V2_NOTES.txt` innerhalb des ST-Projekts.
892
+
893
+ ## Projektwechsel und ST-Kompilierung
894
+
895
+ Beim Wechsel eines Projekts über die Projekt-Dropdownliste wird das ST-Projekt aus dem jeweils ausgewählten Projektordner neu geladen und direkt frisch kompiliert. Dadurch wird verhindert, dass nach einem Projektwechsel noch eine alte Runtime, ein alter AST oder ein zuvor kompiliertes Programm weiterverwendet wird.
896
+
897
+ Relevante Projektstruktur:
898
+
899
+ ```text
900
+ backend/projects/Original/st_project/
901
+ backend/projects/Optimized/st_project/
902
+ backend/projects/Optimized_V2/st_project/
903
+ ```
904
+
905
+ Die API liefert zusätzlich zurück, welches Projekt und welche ST-Datei zuletzt kompiliert wurden:
906
+
907
+ ```text
908
+ st_compiled_project
909
+ st_compiled_file
910
+ st_compiled_at
911
+ ```
912
+
913
+ ## Projekt: EFUSE only
914
+
915
+ Das bestehende Projekt **EFUSE only** wurde modularisiert und parallelisiert. Es wurde kein neues Projekt angelegt.
916
+
917
+ Ziel:
918
+
919
+ - EFUSE-only bleibt als eigene auswählbare Projektvariante erhalten.
920
+ - Die EFUSE-Logik ist jetzt in kleine ST-Bausteine aufgeteilt.
921
+ - Alle 7 EFUSE-Kanäle werden in jedem PLC-Zyklus ausgeführt.
922
+ - Jeder Kanal besitzt einen eigenen `TON` und eigenen Zustand.
923
+ - Die fachliche Originalentscheidung bleibt in `FN_EFuse` gekapselt.
924
+ - Die Connector-kompatible Struktur `CSC.EFuseControl.*` bleibt erhalten.
925
+
926
+ Struktur im ST-Projekt:
927
+
928
+ ```text
929
+ DATATYPES/EFUSE_TYPES.st
930
+ FUNCTIONS/FN_EFuse.st
931
+ FUNCTION_BLOCKS/FB_EFuseChannel.st
932
+ FUNCTION_BLOCKS/FB_EFuseControl.st
933
+ PROGRAMS/my_program.st
934
+ project.json
935
+ ```
936
+
937
+ Die Datei liegt im Projekt unter:
938
+
939
+ ```text
940
+ backend/projects/EFUSE only/st_project/efuse_only_project.zip
941
+ ```
942
+
943
+ Der passende Connector liegt unter:
944
+
945
+ ```text
946
+ backend/projects/EFUSE only/connector/efuse_only_connector.zip
947
+ ```
948
+
949
+ Hinweis:
950
+
951
+ Die bekannten Connector-Pfade wie `CSC_EFuseControl_CTL1`, `CSC_EFuseControl_ON1`,
952
+ `CSC_EFuseControl_CommonON` und `CSC_LDC_LDSC1_PushButtonOn` bleiben erhalten.
953
+ Das Main-Programm ruft `FB_EFuseControl` auf und schreibt die Ergebnisse anschließend
954
+ in die Connector-Struktur `CSC.EFuseControl` zurück.
955
+
956
+
957
+ ## EFUSE only - KEEP-Logik
958
+
959
+ Im Projekt `EFUSE only` wurde die EFUSE-Logik um eine kanalbezogene KEEP-Stabilisierung erweitert.
960
+
961
+ - Jeder der sieben EFUSE-Kanäle besitzt ein eigenes `KEEP`-Signal.
962
+ - Eine neue Anforderung wird beim Start eines Schaltvorgangs gelatcht.
963
+ - Während `KEEP = TRUE` bleibt die gelatchte Anforderung aktiv, auch wenn der Eingang innerhalb der PLC-Zykluszeit umschaltet.
964
+ - `PWR` bleibt live, damit der Abschluss des Vorgangs sofort erkannt wird.
965
+ - `CTL`, `ON`, `WAIT`, `BUSY`, `NEED` und `KEEP` werden pro Kanal getrennt geführt.
966
+ - Der Connector wurde um `CSC_EFuseControl_KEEP1..KEEP7` erweitert.
967
+
968
+ Damit bleibt die EFUSE-only-Variante modularisiert und parallelisiert, verhindert aber instabile Zwischenzustände durch schnelle Eingangssignale.
969
+
970
+ ## EFUSE only - Channel 1
971
+
972
+ Das Projekt `EFUSE only` wurde auf eine reine Channel-1-Variante reduziert.
973
+
974
+ - Es wird ausschließlich `EFuseControl` Kanal 1 ausgeführt.
975
+ - `FB_EFuseControl.st` enthält nur noch `Ch1: FB_EFuseChannel`.
976
+ - `my_program.st` verarbeitet nur noch `EFUSE_REQ1`, `EFUSE_PWR1`, `CSC.LDC.LDSC1.PushButtonOn` und `CSC.LDC.LDSC1.LineTripped`.
977
+ - Der EFUSE-only-Connector wurde auf die Channel-1-relevanten Modbus-Variablen reduziert.
978
+ - Die Projekte `Original`, `Optimized` und `Optimized_V2` bleiben unverändert.
979
+
980
+ ## EFUSE only - Channel 1 + Channel 2
981
+
982
+ Die Projektvariante `EFUSE only` enthält jetzt Channel 1 und Channel 2. Beide Kanäle arbeiten autark:
983
+
984
+ - Channel 1 nutzt `CSC.LDC.LDSC1.PushButtonOn` und `CSC.LDC.LDSC1.LineTripped`.
985
+ - Channel 2 nutzt `CSC.LDC.LDSC2.PushButtonOn` und `CSC.LDC.LDSC2.LineTripped`.
986
+ - Beide Kanäle verwenden jeweils eine eigene `FB_EFuseChannel`-Instanz mit eigenem `TON`, `KEEP`, `WAIT`, `BUSY`, `NEED`, `CTL` und `ON`.
987
+ - `CommonON` wird aus `ON1 OR ON2` gebildet.
988
+ - Die Modbus-Connector-Variablen wurden auf die Channel-1-/Channel-2-Signale erweitert.
989
+
990
+
991
+ ## EFUSE only - No-Dead-Cycle Anpassung
992
+
993
+ Im Projekt **EFUSE only** wurde `FB_EFuseChannel.st` so angepasst, dass keine leeren Zwischenzyklen mehr entstehen.
994
+
995
+ - `CTL`, `ON`, `WAIT`, `BUSY` und `KEEP` bleiben während eines laufenden Schaltvorgangs stabil.
996
+ - `timer.Q` erzeugt keine periodische AUS-Phase mehr. Der TON dient als Status-/Überwachungszeit.
997
+ - Wenn ein Vorgang abgeschlossen ist, wird im selben PLC-Zyklus direkt geprüft, ob bereits eine neue Anforderung anliegt.
998
+ - Channel 1 und Channel 2 arbeiten autark mit jeweils eigener Instanz und eigenem Zustand.
999
+
1000
+ ## EFUSE only - Mico-Pro-orientierte Umsetzung
1001
+
1002
+ Das Projekt **EFUSE only** verwendet jetzt pro Kanal eine eigene Impuls-/Feedback-Zustandsmaschine:
1003
+
1004
+ - `REQ = 1`: Restart über ON-Klemme, ON-Puls 200 ms.
1005
+ - `REQ = 2`: Ausschalten über CTRL-Klemme, CTRL-Puls 650 ms.
1006
+ - `REQ = 3`: Einschalten über CTRL + ON, gemeinsamer Puls 650 ms.
1007
+ - Nach dem Puls werden die Steuerklemmen wieder freigegeben.
1008
+ - `WAIT`, `BUSY` und `KEEP` bleiben aktiv, bis die erwartete Rückmeldung `PWR`/Alarm-Klemme erreicht ist oder die Anforderung zurückgenommen wird.
1009
+ - Channel 1 und Channel 2 laufen autark mit jeweils eigener `FB_EFuseChannel`-Instanz.
1010
+
1011
+ Damit wird nicht mehr dauerhaft `CTRL`/`ON` gehalten, sondern die Mico-Pro-Zeitlogik über definierte Pulse abgebildet.
1012
+
1013
+
1014
+ ## EFUSE only Channel 1 bis 7
1015
+
1016
+ Das Projekt `EFUSE only` wurde auf sieben autarke Kanäle erweitert. Jeder Kanal nutzt dieselbe `FB_EFuseChannel`-Logik mit eigener TON-Instanz und eigener Puls-/Feedback-FSM nach Mico-Pro-Logik:
1017
+
1018
+ - `REQ = 1`: Restart über ON-Klemme, 200 ms Puls
1019
+ - `REQ = 2`: Ausschalten über CTRL-Klemme, 650 ms Puls
1020
+ - `REQ = 3`: Einschalten über CTRL + ON, 650 ms Puls
1021
+ - `PWR/Alarm`: Rückmeldung, ob der Kanal eingeschaltet ist
1022
+
1023
+ Alle sieben Kanäle besitzen eigene Signale `CTLx`, `ONx`, `WAITx`, `BUSYx`, `NEEDx`, `KEEPx`, `STATEx`. `CommonON` wird aus `ON1 OR ... OR ON7` gebildet.
1024
+
1025
+
1026
+ ## EFUSE only - Ausschaltimpuls korrigiert
1027
+
1028
+ Die EFUSE-only-Kanallogik wurde so angepasst, dass `IN = 2` immer einen definierten CTRL-Ausschaltimpuls erzeugt, auch wenn die Rueckmeldung/PWR noch nicht passend oder nicht sicher abgebildet ist. Nach dem 650-ms-Impuls werden `CTL` und `ON` wieder freigegeben. Wenn die Rueckmeldung weiterhin nicht dem Zielzustand entspricht, kann der Impuls wiederholt werden. Dadurch funktioniert das Abschalten stabiler und haengt nicht mehr daran, dass `PWR` vor dem ersten Ausschaltimpuls bereits TRUE ist.
1029
+
1030
+ ## EFUSE V4 KEEP-Latch
1031
+
1032
+ Die optimierten Projekte `Optimized` und `Optimized_V2` verwenden `FB_EFuseControl` als Parallel-Fast-Path mit `KEEP1..KEEP7`.
1033
+
1034
+ - `KEEPx` zeigt an, welcher Kanal aktuell aktiv gemerkt ist.
1035
+ - `KEEP_INx` speichert den gelatchten IN-Befehl fuer die laufende 650-ms-Impulsdauer.
1036
+ - `KEEP_COUNT` zeigt die Anzahl der aktuell aktiven/gemerkten Kanaele.
1037
+ - Kurze IN-Wechsel kleiner als 650 ms gehen dadurch nicht verloren.
1038
+ - Alle 7 Kanaele laufen parallel und blockieren sich nicht gegenseitig.
1039
+
1040
+ ## Projekt: Optimized_EFUSE-Function
1041
+
1042
+ Dieses Projekt enthält eine optimierte EFUSE-Funktion mit zyklischem 7-Kanal-Scan. In jedem PLC-Zyklus werden alle Kanäle geprüft. Benötigte Kanäle werden über `ACTIVE1..ACTIVE7` und `KEEP1..KEEP7` markiert. Dadurch ist direkt sichtbar, ob z. B. Kanal 2, 5 und 7 gleichzeitig aktiv sind. Die bisherige serielle Kanalzähler-Kaskade wird in diesem Projekt nicht mehr als Bearbeitungslogik verwendet.
1043
+
1044
+ Wichtige Diagnosewerte:
1045
+
1046
+ - `ACTIVE1..ACTIVE7`: Kanal benötigt aktuell einen EFUSE-Schaltimpuls.
1047
+ - `KEEP1..KEEP7`: Kanal wurde gelatcht und wird aktuell verarbeitet.
1048
+ - `ACTIVE_COUNT`: Anzahl aktuell erkannter aktiver Kanäle.
1049
+ - `KEEP_COUNT`: Anzahl aktuell gelatchter Kanäle.
1050
+ - `ACTIVE_MASK`: Bitmaske der aktuell aktiven Kanäle, Kanal 1 = 1, Kanal 2 = 2, Kanal 3 = 4 usw. Beispiel Kanal 2+5+7 = 82.
1051
+ - `KEEP_MASK`: Bitmaske der gelatchten Kanäle.
1052
+ - `FIRST_ACTIVE_CHANNEL` / `CURRENT`: erster aktuell erkannter aktiver Kanal, 0 wenn keiner aktiv ist.