2026-06-14 11:18:46 +02:00
2026-04-06 05:24:41 +02:00
2026-06-12 18:59:56 +02:00
2026-06-14 11:18:46 +02:00
2026-04-26 20:38:21 +02:00
2026-02-01 13:25:03 +01:00
2026-06-14 11:18:46 +02:00
2026-06-14 10:32:31 +02:00
2026-06-14 11:18:46 +02:00
2026-06-14 11:18:46 +02:00
2026-06-14 11:18:46 +02:00
2026-06-11 22:05:45 +02:00
2026-06-14 11:18:46 +02:00
2026-06-14 10:32:31 +02:00
2026-02-01 13:25:03 +01:00
2026-02-01 13:25:03 +01:00
2026-04-23 17:27:52 +02:00
2026-04-23 17:27:52 +02:00
2026-06-14 11:18:46 +02:00
2026-06-14 10:32:31 +02:00

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, routet G-Code-Befehle lokal und leitet FCodes via robot/FCodeClient.js an appRobotFileservice weiter.
  • robot/GCode.js verarbeitet G-Code, übersetzt ihn in Roboter-Koordinaten und triggert robot.sendCommand() (kein Datei-Handling mehr).
  • robot/FCodeClient.js übersetzt FCodes (FPoint, FPlus, …) in REST-Aufrufe an appRobotFileservice (Gateway-Funktion des Drivers).
  • 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_API_KEY>.
  • 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
  • FCodes (Datei-/Programm-Befehle) — werden durch den Driver an appRobotFileservice weitergeleitet:
    • FPoint, FPlus, FMinus, FFirst, FLast, FGoto <n>
    • FShow [id], FList, FLoad <id>, FSave <name>, FClear
    • FPlay, FStop
    • Vollständige API: doc/fileserviceAPI.md

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 FCodes leitet der Driver das Ergebnis von appRobotFileservice weiter (Stepping-Befehle zusätzlich als Pose-Broadcast nach lokaler Ausführung).
  • 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.
  • FILESERVICE_URL
    • Standard: http://appRobot_Fileservice:2100
    • URL der appRobotFileservice — wird von robot/FCodeClient.js verwendet. Im Container-Netz entspricht das dem Docker-Dienstnamen aus dem Portainer-Stack.
  • SHELLY_URL
    • URL für den Shelly Smart Plug Emergency-Stop: http://<IP>/rpc/Switch.Set?id=0&on=false
    • Überschreibt controllers.emergencyStop.url aus robot.json (analog zu GRBL_BASE_IP).
    • Wichtig in Docker: .local-mDNS-Hostnamen werden im Container nicht aufgelöst — stattdessen die echte IP verwenden (z.B. http://192.168.0.99/rpc/Switch.Set?id=0&on=false).
    • Details: doc/15_EmergencyStop_done.md

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:

{
  "kinematics": { "type": "arm3segmentlinearx" },
  "motion":     { "defaultFeedrate": 1000, "speedMode": "legacy" },
  "controllers": {
    "base":  { "ip": "fluidNcBase.local",   "port": 2300, "protocol": "telnet", "axes": ["x","y","z"],  "heartbeatInterval": 10000 },
    "elbow": { "ip": "fluidNcEllbow.local", "port": 5000, "protocol": "telnet", "axes": ["a",null,null], "heartbeatInterval": 10000 },
    "hand":  { "ip": "fluidNcHand.local",   "port": 5000, "protocol": "telnet", "axes": ["c","e","b"],  "heartbeatInterval": 10000 },
    "emergencyStop": {
      "protocol":  "shelly",
      "url":       "http://<SHELLY-IP>/rpc/Switch.Set?id=0&on=false",
      "urlOn":     "http://<SHELLY-IP>/rpc/Switch.Set?id=0&on=true",
      "urlStatus": "http://<SHELLY-IP>/rpc/Switch.GetStatus?id=0"
    }
  }
}

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 heartbeatInterval
base fluidNcBase.local 2300 x, y, z 10 000 ms
elbow fluidNcEllbow.local 5000 a 10 000 ms
hand fluidNcHand.local 5000 c, e, b 10 000 ms

IPs können per Env-Variable überschrieben werden (GRBL_BASE_IP, GRBL_ELLBOW_IP, GRBL_HAND_IP). Alles andere (Port, Achsen, Controller-Anzahl, Heartbeat) wird in robot.json konfiguriert.

heartbeatInterval (ms) steuert, wie oft ? an den FluidNC-Controller gesendet wird. Der Sender erkennt eine tote Verbindung (z.B. nach NotAus), wenn zwei aufeinanderfolgende Heartbeats ohne Antwort bleiben (deadTimeout = 2 × heartbeatInterval). Danach wird der Socket geschlossen und der bestehende Reconnect-Mechanismus startet automatisch.

Serverschnittstellen

WebSocket Input Server

  • Läuft auf https://localhost:<PORT>
  • 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 — Sender-Status inkl. isGCodeReceiver-Flag
    • /api/position
    • /api/robotGET: aktuelle robot.json; PUT: überschreibt sie (Auth erforderlich)
    • /api/robot/history — Liste aller Snapshots
    • /api/robot/history/:ts — einen bestimmten Snapshot abrufen
    • /api/power-status — Shelly-Schaltzustand (armed: true/false, Spannung, Leistung)
    • /api/emergency-stopPOST: Feed Hold ! an alle FluidNC + Shelly Strom AUS
    • /api/power-onPOST: Shelly Strom EIN
    • /api/alarm-unlockPOST: $X an alle FluidNC (nach Strom-Neustart)

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 für G-Code-Verarbeitung (Bewegung, Pose, Logging)
  • robot/FCodeClient.js — Gateway: übersetzt FCodes in REST-Aufrufe an appRobotFileservice
  • robot/TelnetSenderGRBL.js
  • robot/ShellyEmergencyStop.js — steuert Shelly Smart Plug als Emergency-Stop-Aktor (HTTP GET, kein GCode)
  • robot/fluidnc/FluidNCClient.js — alternative WebSocket-basierte FluidNC-Anbindung mit Reconnect-Logik (noch nicht integriert)
  • GCodeFiles/ — G-Code-Programme werden jetzt in appRobotFileservice verwaltet

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 ausgelagert → appRobotFileservice
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 ausgelagert → appRobotFileservice
doc/fileserviceAPI.md REST-API der appRobotFileservice (Programme, aktiver Cursor, Teaching/Playback) implementiert
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 16 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 14 in appRobotDriver , Schritte 57 offen)
doc/15_EmergencyStop_done.md Emergency Stop: Shelly + FluidNC Feed Hold, API, UI, Restart-Ablauf erledigt
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        — ausgelagert → appRobotFileservice (siehe drafts)
ToDo_6a Speed-Steuerung      — calculateSpeeds bugfix, dann Sender-Integration
ToDo_6b File-Handling Detail — ausgelagert → appRobotFileservice (siehe drafts)
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 und gesamtes File-Handling → ausgelagert in appRobotFileservice (siehe doc/fileserviceAPI.md)
  • ROBOT_USE_SPEED_CALC und motorSpeeds im echten Betrieb prüfen
  • FluidNCClient.js evaluieren: als Ersatz oder Ergänzung zu TelnetSenderGRBL?
  • HTTPS-Passphrase aus Env-Variable (HTTPS_PASSPHRASE) — erledigt
  • logs/-Verzeichnis beim Start automatisch anlegen — erledigt (startRobot.js)
Description
Main Driver. Receives World-Coordinates GCode and sends it to the different Boards.
Readme 6 MiB
Languages
JavaScript 88.8%
G-code 3.3%
TeX 3%
CSS 2.4%
HTML 1.3%
Other 1.2%