Claude API

This commit is contained in:
chk
2026-06-08 19:04:31 +02:00
parent 10d306b7d4
commit c777f871cd
12 changed files with 529 additions and 28 deletions

111
doc/API.md Normal file
View File

@@ -0,0 +1,111 @@
# API-Referenz
Der Driver stellt zwei Schnittstellen bereit:
| Schnittstelle | Zweck | Port (Container) | Port (Host, docker-compose) |
|---------------|-------|------------------|------------------------------|
| **Input WebSocket** | Steuerbefehle empfangen, Status-Antworten senden | `2095` (`PORT`) | `2096` |
| **Info-/Status-Server (HTTPS)** | Statusübersicht + statische Web-UI | `2098` | `2098` |
---
## 1. Input WebSocket (`wss://…:2095`)
Implementiert in `server/InputWS.js`. Eingehende Nachrichten sind **Plain-Text-Strings**.
Die Antwortlogik unterscheidet bewusst zwischen **gezielten Antworten** (nur an den
Anfrager) und **Broadcasts** (an alle verbundenen Clients).
### Antwort-Routing
| Eingabe | Verarbeitung | Antwort | Empfänger |
|---------|--------------|---------|-----------|
| `Ping` | Heartbeat, wird geloggt | `Ping` | **nur Anfrager** (gezielt) |
| `M114` | Statusabfrage | Positions-JSON (siehe unten) | **nur Anfrager** (gezielt) |
| G-Code (`G1`, `G90`, `G91`, `G28`, `M1`, `M92`, …) | Bewegung/Zustandsänderung | aktuelles Positions-JSON | **alle Clients** (Broadcast) |
| Datei-Befehle (`FShow`, `FList`, `FPoint`, `FPlus`, `FMinus`, `FLoad`, `FSave`, `FClear`, `M20/23/28/29`) | Datei-/Log-Verwaltung | Befehlsergebnis | **alle Clients** (Broadcast) |
| alles andere | | Fehler-Envelope | **nur Anfrager** (gezielt) |
**Begründung der Trennung:** Eine Bewegung ändert die Roboterposition — das ist ein
Status-Update, das jeder Client (z. B. die Simulation) sehen soll → Broadcast. Eine
reine Abfrage (`Ping`, `M114`) ist eine direkte Antwort an den Anfrager → gezielt.
> **Hinweis:** Feinere Zielsteuerung der Datei-Befehle (z. B. `FShow` als
> Anfrager-only-Antwort) sowie `FFirst`/`FLast` gehören zur Datei-Verwaltung in
> **ToDo 4** und bleiben hier bewusst unverändert.
### Positions-JSON (`M114` / Broadcast nach Bewegung)
```json
{
"position": { "x": 0, "y": 30, "z": 0, "a": 0, "b": 0, "c": 0 },
"motorCounts":{ "x": 0, "y": 0, "z": 0, "a": 0, "b": 0, "c": 0, "e": 0 }
}
```
- `position` — kartesische Pose + Orientierung (`a`/`b`/`c` = ϕ/ϴ/Ψ in rad).
- `motorCounts` — aktuelle Motor-/Achswerte.
### Fehler-Envelope (maschinenlesbar)
Bei unbekannter Eingabe oder Verarbeitungsfehler erhält **nur der Anfrager**:
```json
{ "type": "error", "code": "UNKNOWN_COMMAND", "message": "Unrecognized input", "input": "<original>" }
```
| `code` | Bedeutung |
|--------|-----------|
| `UNKNOWN_COMMAND` | Eingabe passt auf keinen bekannten Befehl |
| `GCODE_ERROR` | Fehler beim Parsen/Ausführen eines G-Code-Befehls |
| `FILE_ERROR` | Fehler bei einem Datei-Befehl |
Erfolgs-Antworten (`Ping`, Positions-JSON) bleiben aus Kompatibilitätsgründen im
bisherigen Rohformat; das Envelope gilt nur für Fehler.
---
## 2. Info-/Status-Server (`https://…:2098`)
Implementiert in `server/InfoServer.js`. Selbstsigniertes Zertifikat.
### Statische Web-UI
`GET /` · `GET /app.js` · `GET /style.css` · `GET /allApps.css`
### `GET /api/status`
Liefert Verbindungs- und Health-Informationen als JSON:
```json
{
"generatedAt": "2026-06-08T12:00:00.000Z",
"health": { "ok": false, "connectedSenders": 1, "totalSenders": 3 },
"clients": ["127.0.0.1"],
"senders": [
{
"name": "Base",
"state": "connected",
"url": "fluidNcBase.local",
"isTestMode": false,
"error": null,
"reconnectAttempt": 0,
"reconnectTimer": false,
"health": "ok",
"reason": null
}
],
"lastCommands": ["2026-06-08T…: G1 X10 Y10"],
"lastPings": ["2026-06-08T… 127.0.0.1 : Ping"]
}
```
- `health.ok``true`, wenn **alle** Sender verbunden sind.
- pro Sender: `state``connected | connecting | reconnecting | disconnected`;
`health``ok | warning | disconnected`.
### `GET /api/position`
Liefert die aktuelle Roboterposition (gleiches Positions-JSON wie oben),
**unabhängig** von laufenden Senderverbindungen.
### Sonstige Pfade
`404 Not found`.

View File

@@ -6,16 +6,31 @@ Die Schnittstellen sollen klar und vorhersagbar antworten. Steuerbefehle brauche
## Aufgaben
- [ ] WebSocket-Antwortlogik strukturieren
- [x] WebSocket-Antwortlogik strukturieren
- Steuerbefehle erhalten gezielte Responses
- `Ping`, `M114`, Statusabfragen und Fehlermeldungen getrennt behandeln
- [ ] Broadcasts nur dort verwenden, wo sie sinnvoll sind
-`server/InputWS.js` als klarer Router; `Ping`/`M114` antworten gezielt an den Anfrager
- [x] Broadcasts nur dort verwenden, wo sie sinnvoll sind
- Broadcasts für Status-Updates, nicht für direkte Steuerantworten
- [ ] `InfoServer` um detaillierte Statusinformationen erweitern
- Senderverbindungen
- Health-Checks
- letzte Befehle / Pings
- [ ] API-Endpunkte klar dokumentieren
- `/api/status`
- `/api/position`
- [ ] Fehlermeldungen konsistent und maschinenlesbar machen
- → Bewegung (G-Code) broadcastet die neue Position; `Ping`/`M114` sind gezielt
- [x] `InfoServer` um detaillierte Statusinformationen erweitern
- Senderverbindungen · Health-Checks · letzte Befehle / Pings
- → bereits in ToDo 2 angelegt; ergänzt um Top-Level `health`-Summary + `generatedAt`
- [x] API-Endpunkte klar dokumentieren
- `/api/status` · `/api/position`
- `doc/API.md`
- [x] Fehlermeldungen konsistent und maschinenlesbar machen
- → einheitliches Fehler-Envelope `{ type, code, message, input }`
(`UNKNOWN_COMMAND` / `GCODE_ERROR` / `FILE_ERROR`)
## Tests
- `test/InputWS.api.test.js` — gezielte vs. Broadcast-Antworten, Fehler-Envelope
- `test/InfoServer.test.js` — Health-Summary + `generatedAt`
## Bewusst nicht in diesem ToDo
- Feinere Zielsteuerung der Datei-Befehle (z. B. `FShow` nur an Anfrager) und
`FFirst`/`FLast` → gehören zur Datei-Verwaltung in **ToDo 4**.
- Erfolgs-Payloads (`Ping`, Positions-JSON) bleiben aus Rückwärtskompatibilität im
Rohformat (externe Clients: Simulation/Gamepad); nur Fehler nutzen das Envelope.

View File

@@ -6,7 +6,10 @@ Konkrete, im Code identifizierte Fehler beheben — unabhängig von den Architek
---
## Bug 1: `TelnetSenderGRBL` — `close`-Event verliert `this`-Kontext
## Bug 1: `TelnetSenderGRBL` — `close`-Event verliert `this`-Kontext ✅ ERLEDIGT
> Behoben im ToDo-2-Refactoring: Der `close`-Handler nutzt jetzt eine Arrow-Function
> (`robot/TelnetSenderGRBL.js`), `this` zeigt korrekt auf die Sender-Instanz.
**Datei:** `robot/TelnetSenderGRBL.js`, Zeile 5457
@@ -48,7 +51,11 @@ this.tSocket.on("close", () => {
---
## Bug 4: `logs/`-Verzeichnis wird nicht sichergestellt
## Bug 4: `logs/`-Verzeichnis wird nicht sichergestellt ✅ ERLEDIGT
> Behoben: `initInputWS()` ruft `ensureLogDir()` (`fs.mkdirSync('./logs', { recursive: true })`)
> beim Start auf. `ensureLogDir` ist exportiert und idempotent.
> Test: `test/InputWS.logDir.test.js`.
**Datei:** `server/InputWS.js`, Zeilen 6667 und 7778
@@ -70,7 +77,11 @@ Der Check prüft `mNew.y` statt `mNew.x`. Wenn `mNew.x` `NaN` oder `Infinity` w
---
## Bug 6: `containsMCode` matcht zu breit
## Bug 6: `containsMCode` matcht zu breit ✅ ERLEDIGT
> Behoben: `containsMCode` nutzt jetzt `s === 'M1' || s.startsWith('M1 ')`.
> Test: `test/GCode.containsMCode.test.js`.
> (Hinweis bleibt: Methode wird im Produktivcode noch nicht aufgerufen.)
**Datei:** `robot/GCode.js`, Zeile 12