diff --git a/README.md b/README.md index 6f29757..67046de 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,13 @@ Die Eingaben kommen per WebSocket an den HTTPS-Server und werden in `server/Inpu - `M114` - Antwort: Positionsdaten des Roboters im JSON-Format. - G-Code-Befehle: - - `G90`, `G91`, `G1`, `G28`, `G92` + - `G90`, `G91`, `G1`, `G28` + - `G92` (wird intern als `M92` verarbeitet — setzt Motorposition ohne Bewegung) - Messungen in `X`, `Y`, `Z`, `A`, `B`, `C`, `E`, `F` - `M1` für direkte Motor-Koordinaten - Datei-Kommandos: - - `FPoint`, `FPlus`, `FMinus`, `FFirst`, `FLast`, `FShow`, `FList`, `FLoad `, `FSave `, `FClear` + - `FPoint`, `FPlus`, `FMinus`, `FShow`, `FList`, `FLoad `, `FSave `, `FClear` + - `FFirst`, `FLast` — erkannt, aber noch nicht implementiert - `M20`, `M23`, `M28`, `M29` ### G-Code-Verarbeitung @@ -121,18 +123,50 @@ Die Achszuordnung kann in `robot/TelnetSenderGRBL.js` durch Anpassung der Konstr - `robot/Robot.js` - `robot/GCode.js` - `robot/TelnetSenderGRBL.js` +- `robot/fluidnc/FluidNCClient.js` — alternative WebSocket-basierte FluidNC-Anbindung mit Reconnect-Logik (noch nicht integriert) - `GCodeFiles/` — enthalten Beispiel- und Log-G-Code-Dateien +## Laufzeitvoraussetzungen + +- Das Verzeichnis `logs/` muss im Arbeitsverzeichnis existieren, da `InputWS.js` dort `pings.log` und `gcode_commands.log` schreibt. +- HTTPS-Zertifikate: `https/localhost.key` und `https/localhost.pem` (Passphrase aktuell hardcoded `abcd`). +- Die Telnet-Sender werden erst nach 5 Sekunden zum Roboter hinzugefügt, damit die Verbindungen Zeit haben aufzubauen. + ## ToDo / Open Tasks -- Architektur- und Refactoring-Aufgaben sind zusätzlich in `doc/ToDo_*.md` dokumentiert. +Architektur- und Refactoring-Aufgaben sind in `doc/ToDo_*.md` dokumentiert: + +| Datei | Thema | +|---|---| +| `doc/ToDo_1_Parsing.md` | G-Code-Parser-Schicht einführen | +| `doc/ToDo_2_Anbindung.md` | Sender-Interface und Orchestrierung | +| `doc/ToDo_3_Config.md` | Zentralisierte Konfiguration | +| `doc/ToDo_4_GCode.md` | G-Code- und Datei-Handling trennen | +| `doc/ToDo_5_API.md` | WebSocket-Antwortlogik strukturieren | +| `doc/ToDo_6_RobotController.md` | RobotController-Klasse einführen | +| `doc/ToDo_7_Tests.md` | Testabdeckung und Stabilität | +| `doc/ToDo_8_Bugs.md` | Bekannte konkrete Bugs | +| `doc/ToDo_9_HardwareFeedback.md` | Hardware-Feedback-Loop (GRBL-Antworten, Command-Queue, Positionsabgleich) | + +### Empfohlene Bearbeitungsreihenfolge + +``` +ToDo_8 Bugs beheben — kurz, blockiert nichts anderes +ToDo_3 Config — Fundament für alles Weitere +ToDo_1 Parser ┐ +ToDo_6 RobotController ┘ zusammen, da eng verzahnt +ToDo_4 Datei-Handling — danach, klar abgrenzbar +ToDo_2 Sender-Interface — mit Entscheidung: Telnet vs. FluidNC-WebSocket +ToDo_9 Hardware-Feedback — baut auf ToDo_2 auf +ToDo_5 API — parallel zu ToDo_2/4 möglich +ToDo_7 Tests — begleitend zu allen obigen +``` + +Kurzübersicht weiterer offener Punkte: - [ ] Dokumentation der vollständigen G-Code-Syntax erweitern -- [ ] Feedrate-Berechnung im Sender genauer definieren -- [ ] `ROBOT_USE_SPEED_CALC` und `motorSpeeds` im Einsatz prüfen -- [ ] Fehlerbehandlung bei Telnet-Verbindungen verbessern -- [ ] Einheitliche Behandlung von absoluten und relativen `M1`-Motorbefehlen -- [ ] `G92`-Verhalten überprüfen: Position setzen ohne Roboterbewegung -- [ ] Zusätzliche Testfälle für `InputWS`, `GCode` und `TelnetSenderGRBL` schreiben -- [ ] HTTPS-Konfiguration und Zertifikatsverwaltung verbessern -- [ ] Mehrsprachige Kommentare/README-Übersetzung bei Bedarf +- [ ] `FFirst`/`FLast`-Befehle in `GCode.receiveFC()` implementieren +- [ ] `ROBOT_USE_SPEED_CALC` und `motorSpeeds` im echten Betrieb prüfen +- [ ] `FluidNCClient.js` evaluieren: als Ersatz oder Ergänzung zu `TelnetSenderGRBL`? +- [ ] HTTPS-Konfiguration und Zertifikatsverwaltung verbessern (Passphrase aus Env-Variable) +- [ ] `logs/`-Verzeichnis beim Start automatisch anlegen diff --git a/doc/ToDo_2_Anbindung.md b/doc/ToDo_2_Anbindung.md index d92215b..5bb4f67 100644 --- a/doc/ToDo_2_Anbindung.md +++ b/doc/ToDo_2_Anbindung.md @@ -27,8 +27,9 @@ Dieses ToDo konzentriert sich auf die technische Integration der Komponenten, ni - [ ] `TelnetSenderGRBL` als konkrete Implementierung - async `connect()`-Methode - eindeutiger Verbindungsstatus, nicht nur `this.tSocket` - - reconnect/backoff-Strategie + - reconnect/backoff-Strategie (→ `FluidNCClient.js` hat eine funktionierende Reconnect-Logik, die als Referenz dienen kann) - saubere Fehlerlogs + - **Bug:** `close`-Event-Handler nutzt falsche `this`-Bindung — siehe `doc/ToDo_8_Bugs.md` Bug 1 - [ ] Sender-Schicht testbar und austauschbar machen - später können andere Sender als `TelnetSenderGRBL` angehängt werden @@ -41,4 +42,5 @@ Dieses ToDo konzentriert sich auf die technische Integration der Komponenten, ni ## Hinweis - Parsing, Konfiguration, Datei-Management und Tests werden getrennt in eigenen `doc/ToDo_*.md`-Dateien behandelt. -- Event-basierte Architektur ist aktuell nicht vorgesehen; die Umsetzung folgt Option A mit einer klaren Sender-Interface-Schicht. \ No newline at end of file +- Event-basierte Architektur ist aktuell nicht vorgesehen; die Umsetzung folgt Option A mit einer klaren Sender-Interface-Schicht. +- Die Entscheidung Telnet vs. FluidNC-WebSocket (siehe `robot/fluidnc/FluidNCClient.js`) sollte hier fallen — `FluidNCClient` ist bidirektional und hat Reconnect-Logik, was `ToDo_9` (Hardware-Feedback-Loop) direkt ermöglicht. \ No newline at end of file diff --git a/doc/ToDo_3_Config.md b/doc/ToDo_3_Config.md index 4ceb0ad..489004f 100644 --- a/doc/ToDo_3_Config.md +++ b/doc/ToDo_3_Config.md @@ -15,4 +15,6 @@ Zentralisierte Konfiguration statt verstreuter Hardcodierung. Konfiguration soll - HTTPS-Zertifikatpfade und Passphrase - [ ] `startRobot.js`, `TelnetSenderGRBL`, `InfoServer.js` und weitere Module mit dem Config-Modul arbeiten lassen - [ ] Optional: `config/default.json` oder `.env` als Konfigurationsbasis bereitstellen -- [ ] Fehlende oder ungültige Konfiguration frühzeitig mit klarer Fehlermeldung melden \ No newline at end of file +- [ ] Fehlende oder ungültige Konfiguration frühzeitig mit klarer Fehlermeldung melden +- [ ] HTTPS-Passphrase aus Umgebungsvariable lesen statt hardcoded `'abcd'` in `startRobot.js` +- [ ] `logs/`-Verzeichnis beim Start automatisch anlegen (aktuell crash wenn nicht vorhanden — siehe `doc/ToDo_8_Bugs.md` Bug 4) \ No newline at end of file diff --git a/doc/ToDo_4_GCode.md b/doc/ToDo_4_GCode.md index ac1b51a..c238ed0 100644 --- a/doc/ToDo_4_GCode.md +++ b/doc/ToDo_4_GCode.md @@ -12,4 +12,5 @@ G-Code-Logik sauber von Datei-Management trennen. Die Bewegungssteuerung soll ni - [ ] `GCode.js` auf reines G-Code-Parsing reduzieren - [ ] Datei-Befehle in `InputWS.js` separate behandeln und an den FileManager weiterleiten - [ ] Logfile-Operationen von der Steuerkreislauf-Logik entkoppeln -- [ ] `G92`/`M92`-Verhalten im Kontext des Datei-Managements klar dokumentieren \ No newline at end of file +- [ ] `G92`/`M92`-Verhalten im Kontext des Datei-Managements klar dokumentieren +- [ ] `FFirst`/`FLast` in `receiveFC()` implementieren — aktuell erkannt aber nicht ausgeführt (siehe `doc/ToDo_8_Bugs.md` Bug 2) \ No newline at end of file diff --git a/doc/ToDo_8_Bugs.md b/doc/ToDo_8_Bugs.md new file mode 100644 index 0000000..910cb32 --- /dev/null +++ b/doc/ToDo_8_Bugs.md @@ -0,0 +1,87 @@ +# ToDo 8 — Bekannte Bugs + +## Ziel + +Konkrete, im Code identifizierte Fehler beheben — unabhängig von den Architektur-Refactorings in den anderen ToDo-Dateien. + +--- + +## Bug 1: `TelnetSenderGRBL` — `close`-Event verliert `this`-Kontext + +**Datei:** `robot/TelnetSenderGRBL.js`, Zeile 54–57 + +**Problem:** Das `close`-Event verwendet eine reguläre `function()` statt einer Arrow Function. Dadurch zeigt `this` innerhalb des Handlers auf das EventEmitter-Objekt, nicht auf die `TelnetSenderGRBL`-Instanz. `this.tSocket = null` hat keinen Effekt — nach einer Verbindungstrennung bleibt `tSocket` auf dem alten, ungültigen Objekt. + +```js +// Falsch: +this.tSocket.on("close", function () { + this.tSocket = null; // 'this' ist hier NICHT TelnetSenderGRBL +}); + +// Richtig: +this.tSocket.on("close", () => { + this.tSocket = null; +}); +``` + +--- + +## Bug 2: `FFirst` und `FLast` sind nicht implementiert + +**Datei:** `robot/GCode.js` + +**Problem:** `ContainsFilesCommand()` erkennt `FFirst` und `FLast` und leitet sie an `receiveFC()` weiter. `receiveFC()` behandelt sie aber nicht — die Befehle werden stillschweigend ignoriert und es wird nur `getM114` zurückgegeben. + +**Erwartetes Verhalten:** +- `FFirst` — Cursor auf den ersten Eintrag der Log-Datei setzen und die Position anfahren +- `FLast` — Cursor auf den letzten Eintrag setzen und die Position anfahren + +--- + +## Bug 3: G92/M92-Mismatch + +**Datei:** `robot/GCode.js` + +**Problem:** `containsCommand()` erkennt `G92`, aber `receiveGCode()` prüft auf `g[0] == "M92"`. Ein eingehender Befehl `G92 X10` wird als G-Code erkannt, fällt dann aber durch alle Bedingungen in `receiveGCode()`, und löst unbeabsichtigt `calculateAngles3D()` + `sendCommand()` aus, ohne die Position zu setzen. + +**Klärungsbedarf:** Ist G92 oder M92 der korrekte Eingabe-Befehl? Beides konsistent machen. + +--- + +## Bug 4: `logs/`-Verzeichnis wird nicht sichergestellt + +**Datei:** `server/InputWS.js`, Zeilen 66–67 und 77–78 + +**Problem:** `fs.appendFileSync('./logs/gcode_commands.log', ...)` und `fs.appendFileSync('./logs/pings.log', ...)` crashen beim ersten Aufruf, wenn das `logs/`-Verzeichnis nicht existiert. + +**Fix:** Beim Start `fs.mkdirSync('./logs', { recursive: true })` aufrufen, z. B. in `startRobot.js` oder am Anfang von `initInputWS`. + +--- + +## Bug 5: Falscher Finitude-Check in `TelnetSenderGRBL.execCommand` + +**Datei:** `robot/TelnetSenderGRBL.js`, Zeile 161 + +**Problem:** +```js +if(this.aAxisGrbl == "x" && mNew.xMotorChanged && Number.isFinite(mNew.y)){ +``` +Der Check prüft `mNew.y` statt `mNew.x`. Wenn `mNew.x` `NaN` oder `Infinity` wäre, würde das trotzdem durchgehen. + +--- + +## Bug 6: `containsMCode` matcht zu breit + +**Datei:** `robot/GCode.js`, Zeile 12 + +**Problem:** `s.indexOf('M1') == 0` trifft auch auf `M10`, `M11`, `M12` usw. zu. + +```js +// Aktuell: +static containsMCode(s){ return s.indexOf('M1') == 0 } + +// Präziser: +static containsMCode(s){ return s === 'M1' || s.startsWith('M1 ') } +``` + +Hinweis: Diese Methode wird im aktuellen Code nicht aufgerufen — sie hat keine Wirkung, ist aber irreführend. diff --git a/doc/ToDo_9_HardwareFeedback.md b/doc/ToDo_9_HardwareFeedback.md new file mode 100644 index 0000000..badd9ad --- /dev/null +++ b/doc/ToDo_9_HardwareFeedback.md @@ -0,0 +1,48 @@ +# ToDo 9 — Hardware-Feedback-Loop + +## Ziel + +Der Roboter-Treiber soll nicht nur Befehle senden, sondern auch Antworten der Hardware lesen. Nur so können Fehler erkannt, Positionen verifiziert und Befehlsfolgen zuverlässig synchronisiert werden. + +Aktuell ist der Datenfluss vollständig blind: + +``` +WebSocket → GCode → calculateAngles3D → sendCommand → tSocket.write() + ↓ + GRBL antwortet mit "ok" / "error" + → wird nie gelesen (data => {}) +``` + +--- + +## Paket 1: GRBL-Antworten lesen + +- [ ] `connection.on('data', data => {})` in `TelnetSenderGRBL` ersetzen durch echtes Lesen + - GRBL antwortet auf jeden G-Code-Befehl mit `ok` oder `error: ` + - Antworten parsen und ins Log schreiben +- [ ] Fehlerantworten nach außen meldbar machen + - an `InfoServer` oder über einen EventEmitter + - damit der WebSocket-Client Feedback bekommt, ob ein Befehl angenommen wurde + +## Paket 2: Command-Queue mit ok-Handshake + +- [ ] Sendepuffer einführen: Befehle erst abschicken, wenn das vorherige `ok` eingegangen ist + - GRBL hat intern ~128 Byte Puffer — bei schnellen Befehlsfolgen (Datei abspielen) droht sonst Puffer-Überlauf und stille Befehlsverwerfung + - Alternative: GRBL Line-Counting-Protokoll (sendet mehrere Befehle, zählt Zeichen im Puffer) +- [ ] Timeout für ausbleibende `ok`-Antworten definieren + - nach X ms ohne Antwort: Fehler loggen, ggf. Verbindung zurücksetzen + +## Paket 3: Hardwareposition abfragen (`?`-Status) + +- [ ] Periodisch GRBL-Statusabfrage senden: `?` + - GRBL antwortet mit `` + - Alternative: nach jedem abgeschlossenen Move abfragen +- [ ] Gemeldete Hardware-Position mit Softwareposition (`robot.x/y/z`) vergleichen + - bei Abweichung: warnen oder synchronisieren + - schützt gegen Drift durch Endschalter-Auslösung, Motor-Stall, Verbindungsunterbrechung +- [ ] Status (`Idle`, `Run`, `Alarm`, `Hold`) für den `InfoServer` bereitstellen + - `/api/status` um GRBL-Zustand erweitern + +## Hinweis zur Implementierung + +`robot/fluidnc/FluidNCClient.js` ist eine bidirektionale WebSocket-Anbindung an FluidNC (Port 81) mit Reconnect-Logik und `EventEmitter`-Interface — diese Klasse ist eine gute Grundlage für alle drei Pakete und sollte bei der Umsetzung von `ToDo_2` (Sender-Interface) mit evaluiert werden.