# AppRobotDriver Dieses Projekt empfängt G-Code und Robotersteuerbefehle, berechnet Inverse Kinematik für einen mehrgliedrigen Roboterarm und leitet die resultierenden Achsenbefehle an mehrere GRBL/FluidNC-Telnet-Sender weiter. ## Architektur - `startRobot.js` startet zwei HTTPS-Server: - Eingabe-Server + WebSocket für G-Code und Steuerbefehle - Info-Server für Status, Position und einfache Weboberfläche - `server/InputWS.js` empfängt Nachrichten von WebSocket-Clients, prüft sie auf G-Code oder Datei-Kommandos und gibt Positionsdaten zurück. - `robot/GCode.js` verarbeitet G-Code, übersetzt ihn in Roboter-Koordinaten und triggert `robot.sendCommand()`. - `robot/RobotBase.js` ist die abstrakte Basisklasse / der Interface-Vertrag: generische Infrastruktur (Zustand, `sendCommand`, Motor-Geschwindigkeiten) plus die zwei abstrakten Kinematik-Methoden. - `robot/kinematics/Arm3SegmentLinearX.js` ist die konkrete Kinematik (Inverse + Vorwärts) für den aktuellen Arm. Die Auswahl der Kinematik erfolgt über `robot/KinematicsFactory.js` (Umgebungsvariablen `ROBOT_KINEMATICS` / `ROBOT_KINEMATICS_PARAMS`). Siehe `doc/ToDo_12_InverseKinematikConfig_ROADMAP.md`. - `robot/RobotConfig.js` liest `data/robot/robot.json` beim Start synchron und gibt einen typisierten Konfigurations-Record zurück (Kinematik-Parameter, Bewegungs-Defaults, Controller-Endpunkte). Env-Variablen überschreiben die JSON-Werte. - `server/RobotConfigService.js` stellt `GET/PUT /api/robot` und `GET /api/robot/history` über den InfoServer bereit (Single Source of Truth für alle Apps). Schreibzugriffe erfordern `Authorization: Bearer `. - `robot/TelnetSenderGRBL.js` formatiert die Motor-Positionen in GRBL-kompatible Befehle und sendet sie per Telnet an einen Zielcontroller. ## Eingaben Die Eingaben kommen per WebSocket an den HTTPS-Server und werden in `server/InputWS.js` verarbeitet. ### Unterstützte Nachrichten - `Ping` - Antwort: Wird zurück an alle verbundenen Clients gesendet. - `M114` - Antwort: Positionsdaten des Roboters im JSON-Format. - G-Code-Befehle: - `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`, `FShow`, `FList`, `FLoad `, `FSave `, `FClear` - `FFirst`, `FLast` — erkannt, aber noch nicht implementiert - `M20`, `M23`, `M28`, `M29` ### G-Code-Verarbeitung - `GCode.receiveGCode(robot, message)` - Gruppiert Zeilen, unterstützt Inline-Jogging (`$J=`) - Schaltet zwischen absoluter und relativer Koordinatenverarbeitung - Aktualisiert Position und Winkel im `robot`-Objekt - Führt inverse Kinematik aus mit `robot.calculateAngles3D()` - Sendet das Ergebnis an `robot.sendCommand()` ## Ausgaben - WebSocket-Broadcasts an alle verbundenen Clients - Nachdem ein G-Code-Befehl verarbeitet wurde, sendet das System `GCode.getM114(robot)` zurück. - Für Datei-Kommandos gibt `GCode.receiveFC()` ebenfalls die aktuelle Position zurück. - Telnet-Ausgabe an GRBL/FluidNC-Geräte - `TelnetSenderGRBL.execCommand()` erzeugt `G1`/`G90`-Befehle mit Achsenzuordnung und Feedrate. - Info-Server API - `/api/status` — zeigt Client-Status, Sender-Status und letzte Befehle/Pings an - `/api/position` — gibt die aktuelle Roboterposition und Motorwinkel als JSON zurück ## Konfiguration ### Starten - `npm start` - Alternativ: `node startRobot.js` ### Umgebungsvariablen - `PORT` - Standard: `2095` - Port für den WebSocket/HTTPS-Eingabeserver - `GRBL_BASE_IP` - Standard: `fluidNcBase.local` - Zielhost für den ersten Telnet-Sender - `GRBL_ELLBOW_IP` - Standard: `fluidNcEllbow.local` - Zielhost für den Ellbogen-Sender - `GRBL_HAND_IP` - Standard: `fluidNcHand.local` - Zielhost für den Hand-Sender - `ROBOT_DEFAULT_FEEDRATE` - Standard: `1000` (mm/min) - Default-Feedrate für `G1`-Befehle, wenn keine `F`-Angabe vorhanden ist - `ROBOT_SPEED_MODE` - Werte: `legacy` (Standard) oder `correct` - `legacy`: alte Speed-Regelung — jeder Sender erhält die kartesische Feedrate `F` unverändert (Verhalten exakt wie bisher). - `correct`: koordinierte Feedrate pro Sender, sodass alle Controller den Bewegungs­schritt gleichzeitig beenden. Aktiviert automatisch `calculateSpeeds()`. - Details: `doc/ToDo_6a_Speed.md` - `ROBOT_USE_SPEED_CALC` - Werte: `true`, `1` oder sonst leer - Interner Schalter, ob `robot.calculateSpeeds()` rechnet. Ändert allein **nicht** die Sender-Ausgabe — dafür ist `ROBOT_SPEED_MODE=correct` nötig. Vom Korrekt-Modus automatisch aktiviert. - `ROBOT_KINEMATICS` - Standard: `arm3segmentlinearx` - Bezeichner der Kinematik-Klasse (case-insensitive). Bekannte Werte: `arm3segmentlinearx`, `grabit` / `robot02` (Joy-IT Grab-It). Unbekannter Bezeichner → Fehler beim Start. - `ROBOT_KINEMATICS_PARAMS` - JSON-Objekt mit Konstruktor-Parametern, z. B. `{"l1":250,"l2":264,"l3":100}`. Überschreibt die Werte aus `robot.json`. Wird von der Factory als viertes Argument an den Konstruktor weitergereicht (erlaubt kinematik-spezifische Parameter wie `baseHeight`). - `ROBOT_API_KEY` - Statischer Bearer-Token für `PUT /api/robot`. Fehlt die Variable, generiert `RobotConfigService` beim ersten Start einen zufälligen Key und speichert ihn in `data/robot/.apikey` (nicht im Repo). Der Key wird beim Start einmalig geloggt. ### HTTPS-Konfiguration - `https/localhost.key` - `https/localhost.pem` - Passphrase: Env-Variable `HTTPS_PASSPHRASE`, Default `abcd` ### robot.json `data/robot/robot.json` ist die zentrale Konfigurationsdatei für einen konkreten Roboter. Sie wird von `robot/RobotConfig.js` beim Start synchron gelesen. Fehlt die Datei, startet der Driver mit Fallback-Defaults und loggt eine Warnung. Relevante Abschnitte für den Driver: ```json { "kinematics": { "type": "arm3segmentlinearx" }, "motion": { "defaultFeedrate": 1000, "speedMode": "legacy" }, "controllers": { "base": { "ip": "fluidNcBase.local", "port": 2300, "protocol": "telnet", "axes": ["x","y","z"] }, "elbow": { "ip": "fluidNcEllbow.local", "port": 5000, "protocol": "telnet", "axes": ["a",null,null] }, "hand": { "ip": "fluidNcHand.local", "port": 5000, "protocol": "telnet", "axes": ["c","e","b"] } } } ``` Armlängen werden aus dem `links`-Abschnitt abgeleitet (`Arm1.skeleton.to[1]` → l1 usw.). Env-Variablen haben Vorrang vor robot.json (nützlich für Tests und schnelle Korrekturen). Snapshots werden automatisch vor jedem PUT angelegt (`data/robot/robot_YYYYMMDD_HHmmss.json`). Snapshots sind nicht im Repo (`.gitignore`), `robot.json` selbst schon. ### Telnet-Sender-Konfiguration `startRobot.js` erzeugt die `TelnetSenderGRBL`-Instanzen dynamisch aus `cfg.controllers` (geladen von `robot/RobotConfig.js`). Die Defaults entsprechen drei Controllern: | Key | Default-IP | Port | Achsen | |-----|-----------|------|--------| | `base` | `fluidNcBase.local` | 2300 | `x, y, z` | | `elbow` | `fluidNcEllbow.local` | 5000 | `a` | | `hand` | `fluidNcHand.local` | 5000 | `c, e, b` | IPs können per Env-Variable überschrieben werden (`GRBL_BASE_IP`, `GRBL_ELLBOW_IP`, `GRBL_HAND_IP`). Alles andere (Port, Achsen, Controller-Anzahl) wird in `robot.json` konfiguriert. ## Serverschnittstellen ### WebSocket Input Server - Läuft auf `https://localhost:` - Erwartet WebSocket-Verbindungen und verarbeitet Nachrichten als G-Code oder Steuerbefehle ### Info Server - Läuft auf `https://localhost:2098` - Statische Dateien: - `/` - `/app.js` - `/style.css` - `/allApps.css` - API-Endpunkte: - `/api/status` - `/api/position` - `/api/robot` — `GET`: aktuelle `robot.json`; `PUT`: überschreibt sie (Auth erforderlich) - `/api/robot/history` — Liste aller Snapshots - `/api/robot/history/:ts` — einen bestimmten Snapshot abrufen ## Wichtige Dateien - `startRobot.js` - `server/InputWS.js` - `server/InfoServer.js` - `robot/RobotBase.js` — abstrakte Basisklasse / Interface-Vertrag (generische Infrastruktur) - `robot/kinematics/Arm3SegmentLinearX.js` — konkrete Kinematik (Modell + Inverse/Vorwärts), Default-Arm - `robot/kinematics/Arm3SegmentRotaryBase.js` — Kinematik für den Joy-IT „Grab-It" (Robot02), 5 Achsen + Greifer mit Drehbasis (`ROBOT_KINEMATICS=grabit`) - `robot/KinematicsFactory.js` — wählt die Kinematik per Umgebungsvariable - `robot/RobotConfig.js` — liest `data/robot/robot.json`, gibt typisierten Konfigurations-Record zurück - `server/RobotConfigService.js` — REST-Endpunkte `/api/robot*` (lesen/schreiben, Snapshots, Auth) - `data/robot/robot.json` — zentrale Roboter-Konfiguration (Single Source of Truth) - `robot/GCodeParser.js` — wandelt rohe Nachrichten in strukturierte Befehlsobjekte - `robot/RobotController.js` — wendet geparste Befehle auf das Modell an (Steuerlogik) - `robot/GCode.js` — Fassade + Datei-Befehle - `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 - HTTPS-Zertifikate: `https/localhost.key` und `https/localhost.pem` (Passphrase via `HTTPS_PASSPHRASE`, Default `abcd`). - `data/robot/robot.json` — wird beim Start eingelesen; fehlt die Datei, startet der Driver mit Defaults + Warnung. - `logs/` wird beim Start automatisch angelegt (`fs.mkdirSync('logs', { recursive: true })` in `startRobot.js`). - Telnet-Sender werden sofort beim Start als `cmdReceivers` registriert; interne Reconnect-Logik überbrückt verzögerte Controller-Verbindungen automatisch. ## ToDo / Open Tasks Architektur- und Refactoring-Aufgaben sind in `doc/ToDo_*.md` dokumentiert: | Datei | Thema | Status | |---|---|---| | `doc/ToDo_1_Parsing.md` | G-Code-Parser-Schicht einführen | ✅ erledigt | | `doc/ToDo_2_Anbindung.md` | Sender-Interface und Orchestrierung | ✅ erledigt | | `doc/ToDo_3_Config.md` | Zentralisierte Konfiguration | offen | | `doc/ToDo_4_GCode.md` | G-Code- und Datei-Handling trennen | offen | | `doc/ToDo_5_API.md` | WebSocket-Antwortlogik strukturieren | ✅ erledigt | | `doc/ToDo_6_RobotController.md` | RobotController-Klasse einführen | ✅ erledigt | | `doc/ToDo_6a_Speed.md` | Speed-Steuerung: Schalter, `calculateSpeeds()`-Fix, koordinierte Feedrate | ✅ erledigt (WS-Sender offen) | | `doc/ToDo_6b_FileHandling.md` | File-Handling: fehlende Befehle, Cursor im Speicher, Fehler-Feedback | offen | | `doc/ToDo_7_Tests.md` | Testabdeckung und Stabilität | teilweise | | `doc/ToDo_8_Bugs.md` | Bekannte konkrete Bugs | teilweise | | `doc/ToDo_9_HardwareFeedback.md` | Hardware-Feedback-Loop (GRBL-Antworten, Command-Queue, Positionsabgleich) | teilweise (Baustein Port→Motor ✅, Pakete 1–6 offen) | | `doc/ToDo_10_VerbindungsVerlust.md` | Verbindungsverlust erkennen, Watchdog, UI-Statusanzeige | offen | | `doc/ToDo_12_InverseKinematikConfig_ROADMAP.md` | Austauschbare Kinematik: RobotBase, KinematicsFactory, Grab-It | ✅ erledigt | | `doc/ToDo_14_robot_json_service.md` | robot.json als REST-Service, RobotConfigService, RobotConfig | teilweise (Schritte 1–4 in appRobotDriver ✅, Schritte 5–7 offen) | | `doc/ToDo_49_Cleanup.md` | Pre-Release-Cleanup: tote Code, Zertifikate, ToDos, README | offen | ### 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_6a Speed-Steuerung — calculateSpeeds bugfix, dann Sender-Integration ToDo_6b File-Handling Detail — fehlende F-Befehle, Cursor im Speicher ToDo_2 Sender-Interface — mit Entscheidung: Telnet vs. FluidNC-WebSocket ToDo_9 Hardware-Feedback — baut auf ToDo_2 auf ToDo_10 Verbindungsverlust — baut auf ToDo_2 auf, parallel zu ToDo_9 möglich 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 - [ ] `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`? - [x] HTTPS-Passphrase aus Env-Variable (`HTTPS_PASSPHRASE`) — erledigt - [x] `logs/`-Verzeichnis beim Start automatisch anlegen — erledigt (`startRobot.js`)