Files
appRobotDriver/doc/ToDo_6b_FileHandling.md
2026-06-09 12:05:18 +02:00

5.3 KiB

ToDo 6b — File-Handling

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): jedes FPlus/FMinus liest 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"FLoad kann das nicht ändern, weil es nicht implementiert ist
  • toPiMultiple() ist eine String-Manipulation aus der Vor-Parser-Ära, inkonsistent mit GCodeParser
  • FPoint hardcodiert f1000 — sollte robot.feedrate verwenden (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

  • FFirstcurrentLineIndex auf 0 setzen, erste Zeile anfahren
  • FLastcurrentLineIndex auf letzte Zeile setzen, anfahren
  • FClear — aktive Log-Datei leeren, currentLineIndex auf 0
  • FList — Inhalte von GCodeFiles/ auflesen, Liste zurückgeben
    XYZ__FList__XYZ
    log.gcode
    log_2025_10_04.gcode
    ...
    
  • FLoad <dateiname> — benannte Datei aus GCodeFiles/ laden, currentLineIndex auf den ;!-Marker setzen (Rückwärtskompatibilität), oder auf 0 falls kein Marker
  • FSave <dateiname> — aktiven Puffer unter GCodeFiles/<dateiname> speichern
  • M20/M23/M28/M29 — Marlin-kompatible Aliases für FList/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.

  • currentLineIndex als Instanzvariable einführen (startet bei 0 oder am ';!'-Marker beim Laden)
  • FPlus/FMinus nur noch currentLineIndex ändern, Datei bleibt unverändert
  • ';!'-Marker beim Speichern (FSave) optional mitschreiben (für externe Kompatibilität)
  • Beim Laden einer bestehenden Datei: Zeile mit ';!' suchen → currentLineIndex setzen, 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: FPoint könnte einen Einheiten-Kommentar schreiben (;unit=deg)
    • Oder: Konvention festlegen und dokumentieren (Dateien immer in Grad, Anzeige in Grad)
  • toPiMultiple() durch eine klar benannte Funktion degreesToRadians(gCodeString) ersetzen, die intern GCodeParser.parse() nutzt statt raw-String-Manipulation
  • FPoint sollte 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)
  • FLoad validiert, dass die Zieldatei existiert und mindestens eine gültige G-Code-Zeile enthält
  • Dateinamen in FLoad/FSave sanitizen: keine ../-Pfade, nur GCodeFiles/-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 auf fs.appendFile (async) umstellen — Cursor ist im Speicher, kein Lesen nötig
  • FShow/FList auf fs.readFile (async) umstellen
  • FLoad/FSave async

Betroffene Dateien

  • robot/GCode.js (oder künftig robot/GCodeFileManager.js nach ToDo_4)
  • server/InputWS.js — Fehler-Routing für File-Befehle
  • test/GCode.FileOperation.test.js — stark erweitern