5.9 KiB
ToDo 6b — File-Handling
✅ Erledigt / abgelöst: Das File-Handling wird in das eigenständige Projekt
appRobotFileserviceausgelagert (Driver als Gateway, FCodes als Pass-through). Die hier beschriebenen Detailprobleme werden dort gelöst: Cursor als In-Memory- Index (Paket 2), explizite Grad↔Radian-Umrechnung im Fileservice (Paket 3), Fehler-Envelope (Paket 4), asynchrones IO (Paket 5). Konzept & Schnittstelle:fileserviceAPI.md. Die folgende Analyse bleibt als Umsetzungs-Vorlage für jenes Projekt erhalten.
Ist-Zustand
GCode.receiveFC() implementiert nur einen Bruchteil der erkannten Befehle:
| Befehl | Erkannt | Implementiert | Anmerkung |
|---|---|---|---|
FPoint |
✅ | ✅ | Speichert aktuelle Position |
FPlus |
✅ | ✅ | Cursor vorwärts |
FMinus |
✅ | ✅ | Cursor rückwärts |
FShow |
✅ | ✅ | Gibt Dateiinhalt zurück |
FFirst |
✅ | ❌ | Cursor auf erste Zeile |
FLast |
✅ | ❌ | Cursor auf letzte Zeile |
FList |
✅ | ❌ | Listet verfügbare G-Code-Dateien |
FLoad <file> |
✅ | ❌ | Lädt eine andere Datei als aktive |
FSave <file> |
✅ | ❌ | Speichert aktive Datei unter neuem Namen |
FClear |
✅ | ❌ | Leert die aktive Log-Datei |
M20 |
✅ | ❌ | List SD/Files |
M23 |
✅ | ❌ | Select file |
M28 |
✅ | ❌ | Start write |
M29 |
✅ | ❌ | Stop write |
Zusätzliche strukturelle Probleme:
- Cursor lebt in der Datei (
';!'-Marker): jedesFPlus/FMinusliest und schreibt die ganze Datei neu - Synchrones File-IO (
readFileSync/writeFileSync) blockiert den Node.js-Event-Loop - Kein Fehler-Feedback an den WebSocket-Client — Fehler gehen nur auf
console.error - Aktive Datei ist statisch:
static fileName = "GCodeFiles/log.gcode"—FLoadkann das nicht ändern, weil es nicht implementiert ist toPiMultiple()ist eine String-Manipulation aus der Vor-Parser-Ära, inkonsistent mitGCodeParserFPointhardcodiertf1000— sollterobot.feedrateverwenden (auch in ToDo_6a)- Kein Directory-Listing für
FList— welche Dateien sind gültig?
Konzept
Die gesamte Datei-Logik wird in eine eigene Klasse GCodeFileManager ausgelagert
(gemäß ToDo_4). Diese ToDo beschreibt die inhaltliche Umsetzung — unabhängig davon,
ob sie noch in GCode.js oder schon in GCodeFileManager landet.
Der Cursor wird aus der Datei in den Speicher verlagert: currentLineIndex als
Instanzvariable, die nur beim Laden einer Datei initialisiert wird. Das spart permanentes
Neu-Schreiben der Datei.
Pakete
Paket 1: Fehlende Befehle implementieren
FFirst—currentLineIndexauf 0 setzen, erste Zeile anfahrenFLast—currentLineIndexauf letzte Zeile setzen, anfahrenFClear— aktive Log-Datei leeren,currentLineIndexauf 0FList— Inhalte vonGCodeFiles/auflesen, Liste zurückgebenXYZ__FList__XYZ log.gcode log_2025_10_04.gcode ...FLoad <dateiname>— benannte Datei ausGCodeFiles/laden,currentLineIndexauf den;!-Marker setzen (Rückwärtskompatibilität), oder auf 0 falls kein MarkerFSave <dateiname>— aktiven Puffer unterGCodeFiles/<dateiname>speichernM20/M23/M28/M29— Marlin-kompatible Aliases fürFList/FLoad/FSave/Stop, oder explizit als „nicht unterstützt" mit Fehlermeldung antworten
Paket 2: Cursor in den Speicher verlagern
Aktuell wird der Cursor als ';!' direkt in die Datei geschrieben. Das zwingt bei
jedem FPlus/FMinus die gesamte Datei neu zu schreiben.
currentLineIndexals Instanzvariable einführen (startet bei 0 oder am';!'-Marker beim Laden)FPlus/FMinusnur nochcurrentLineIndexändern, Datei bleibt unverändert';!'-Marker beim Speichern (FSave) optional mitschreiben (für externe Kompatibilität)- Beim Laden einer bestehenden Datei: Zeile mit
';!'suchen →currentLineIndexsetzen, dann';!'-Marker aus der Datei entfernen (einmalige Migration)
Paket 3: toPiMultiple durch Parser-Integration ersetzen
Gespeicherte Dateien enthalten Winkel in Grad (a45.00), der Parser erwartet
Zahlenwerte ohne Umrechnungspflicht. Die Konversion muss explizit und testbar sein.
- Beim Lesen einer Zeile aus der Datei: erkennen, ob Winkel in Grad oder Rad vorliegen
- Marker-Ansatz:
FPointkönnte einen Einheiten-Kommentar schreiben (;unit=deg) - Oder: Konvention festlegen und dokumentieren (Dateien immer in Grad, Anzeige in Grad)
- Marker-Ansatz:
toPiMultiple()durch eine klar benannte FunktiondegreesToRadians(gCodeString)ersetzen, die internGCodeParser.parse()nutzt statt raw-String-ManipulationFPointsollte die Einheit konsistent speichern — Grad ist sinnvoller für Lesbarkeit
Paket 4: Fehler-Feedback und Validierung
- Bei Dateifehlern (nicht gefunden, Leserechte) → strukturierte Fehlermeldung an den WebSocket-Client zurückgeben (gemäß Fehler-Envelope aus ToDo_5)
FLoadvalidiert, dass die Zieldatei existiert und mindestens eine gültige G-Code-Zeile enthält- Dateinamen in
FLoad/FSavesanitizen: keine../-Pfade, nurGCodeFiles/-Verzeichnis
Paket 5: Asynchrones File-IO (optional, später)
Alle aktuellen readFileSync/writeFileSync-Aufrufe blockieren den Event-Loop.
Bei kleinen Dateien (< 1 MB) ist das tolerierbar. Bei größeren Programmen oder
häufigem FPoint-Schreiben wird es spürbar.
FPoint-Schreiben auffs.appendFile(async) umstellen — Cursor ist im Speicher, kein Lesen nötigFShow/FListauffs.readFile(async) umstellenFLoad/FSaveasync
Betroffene Dateien
robot/GCode.js(oder künftigrobot/GCodeFileManager.jsnach ToDo_4)server/InputWS.js— Fehler-Routing für File-Befehletest/GCode.FileOperation.test.js— stark erweitern