Files
appRobotDriver/doc/ToDo_14_robot_json_service.md
2026-06-11 22:05:45 +02:00

7.3 KiB
Raw Blame History

Roadmap: robot.json als zentraler Service

Ist-Zustand (Problem)

robot.json existiert aktuell an mindestens zwei unabhängigen Orten:

App Pfad Rolle
appRobotHoming scripts/robot_<ts>.json (Env: ROBOT_JSON) Lesen + Schreiben (editRobot.js)
appRobotRendering data/robot/robot.json Lesen (Rendering)
appRobotDriver Armlängen hardcodiert (250, 264, 100)

Es gibt keine Versionierung, keinen Single Point of Truth, und wenn Homing die Geometrie kalibriert, bekommen Driver und Rendering davon nichts mit.


Ziel-Architektur

appRobotDriver ist das Zentrum des Systems (er steuert die Hardware). Er besitzt daher auch die robot.json und stellt sie über einen REST-Endpunkt bereit. Alle anderen Apps lesen/schreiben ausschließlich über diesen Endpunkt.

appRobotDriver
  └── data/robot/
        ├── robot.json                  ← aktueller Stand (Single Source of Truth)
        ├── robot_20260101_143522.json  ← Snapshot vor jeder Änderung
        └── robot_20260115_091010.json

appRobotHoming   ──GET/PUT──►  appRobotDriver :2098/api/robot
appRobotRendering ──GET──────►  appRobotDriver :2098/api/robot
appRobotSimulation ──GET────►  appRobotDriver :2098/api/robot

Der InfoServer (Port 2098) bekommt die neuen Endpunkte. Der WebSocket-Server (Port 2095) bleibt unverändert.


API-Design

Alle Endpunkte unter dem bereits laufenden InfoServer auf Port 2098.

GET  /api/robot            → robot.json als JSON (kein Auth nötig)
PUT  /api/robot            → ersetzt robot.json, legt vorher Snapshot an (Auth nötig)
GET  /api/robot/history    → Liste aller Snapshots [{ filename, timestamp }]
GET  /api/robot/history/:ts → einen bestimmten Snapshot abrufen

Sicherheit (trivial, da Netz sicher)

PUT-Requests brauchen einen statischen API-Key als HTTP-Header:

Authorization: Bearer <ROBOT_API_KEY>

Key wird per Umgebungsvariable konfiguriert (ROBOT_API_KEY). Fehlt die Variable, wird ein zufälliger Key generiert und beim Start geloggt. Für GET braucht es keinen Key — Lesen ist überall erlaubt.

Das ist die einzige Absicherung. Kein JWT, keine Sessions, kein Rate-Limiting — Netz ist sicher, und ein versehentlicher Schreib-Request aus einem Browser soll trotzdem nicht funktionieren.


Status

Schritt Bereich Status
1 — Datei anlegen appRobotDriver erledigt
2 — RobotConfigService appRobotDriver erledigt
3 — Registrierung InfoServer appRobotDriver erledigt
4 — Driver liest Armlängen appRobotDriver erledigt
5 — appRobotHoming umstellen appRobotHoming offen
6 — appRobotRendering umstellen appRobotRendering offen
7 — Aufräumen alle Repos offen

Die Schritte 14 betreffen ausschließlich appRobotDriver und sind vollständig umgesetzt. Schritte 57 betreffen appRobotHoming und appRobotRendering — separate Tickets/Sessions.


Umsetzungsschritte

Schritt 1 — Datei anlegen (appRobotDriver)

  • Verzeichnis data/robot/ anlegen
  • Default-robot.json wird vom Nutzer geliefert und dort abgelegt
  • .gitignore-Eintrag für data/robot/robot_*.json (Snapshots gehören nicht ins Repo, robot.json selbst schon)
  • Driver startet mit Defaults (l1: 250, l2: 264, l3: 100) wenn Datei fehlt, loggt Warnung

Schritt 2 — RobotConfigService (appRobotDriver)

Neue, in sich geschlossene Datei server/RobotConfigService.js. Sie hat keine Abhängigkeiten auf andere Teile des Drivers und kann in jeden Express- oder https.createServer-basierten Server mit einer Zeile eingehängt werden:

const robotConfigService = require('./server/RobotConfigService');
robotConfigService.register(app, { apiKey: process.env.ROBOT_API_KEY });
// fertig — alle /api/robot*-Routen sind registriert

Das Modul kapselt intern:

readRobotJson()          → Promise<object>
writeRobotJson(data)     → Promise<{ snapshotFile }>   // legt robot_<ts>.json an + pruning
listHistory()            → Promise<{ filename, day, timestamp }[]>
readSnapshot(ts)         → Promise<object>
pruneSnapshots()         → löscht überschüssige Snapshots (s. Regel unten)

Snapshot-Pruning-Regel: Pro Tag maximal 100 Snapshots. Sind es mehr, wird nur der neueste des Tages behalten. Diese Bereinigung läuft automatisch nach jedem Schreibvorgang.

Timestamp-Format: YYYYMMDD_HHmmss (konsistent mit appRobotHoming).

API-Key: Wird per Option übergeben. Fehlt der Key (undefined), generiert das Modul beim ersten Start einen zufälligen Key, loggt ihn einmalig und speichert ihn in data/robot/.apikey (nicht im Repo). So funktioniert es ohne Konfiguration, ist aber trotzdem nicht offen.

Schritt 3 — Registrierung in InfoServer.js (appRobotDriver)

Eine Zeile in server/InfoServer.js am Anfang der Request-Handler:

robotConfigService.register(httpsServer, { apiKey });

Da InfoServer.js kein Express nutzt (rohes https.createServer), bekommt RobotConfigService intern einen minimalen Router, der url-Matching selbst macht — oder InfoServer.js wird auf Express umgestellt (kleiner Schritt, bringt mehr Flexibilität für spätere Endpunkte).

Schritt 4 — Driver liest Armlängen aus robot.json

startRobot.js liest beim Start arm-lengths aus data/robot/robot.json.
Fallback auf { l1: 250, l2: 264, l3: 100 } mit Log-Warnung wenn Datei fehlt oder Keys fehlen.

// links.Arm1.size[1]   → l1
// links.Arm2.size[1]   → l2
// links.Ellbow.size[0] → l3

Schritt 5 — appRobotHoming auf Driver-API umstellen

server/server.js in appRobotHoming:

  • ROBOT_JSON-Env-Variable durch ROBOT_DRIVER_URL ersetzen (z.B. https://appRobotDriver:2098)
  • Neue Hilfsfunktionen fetchRobotJson() / pushRobotJson(data) (HTTP GET/PUT mit API-Key)
  • Alle fsPromises.readFile(ROBOT_JSON)-Aufrufe durch await fetchRobotJson() ersetzen
  • Nach jeder editRobot.js-Transformation: await pushRobotJson(updated)
  • editRobot.js bleibt unverändert (pure Transformationen, kein File-IO)

Schritt 6 — appRobotRendering auf Driver-API umstellen

robot.json wird einmalig beim Start vom Driver geholt und gecacht. Cache wird per GET /api/robot aktualisierbar. Env-Variable ROBOT_DRIVER_URL.

Schritt 7 — Aufräumen

  • Lokale robot.json-Kopien in appRobotHoming und appRobotRendering entfernen
  • .gitignore-Einträge in den betroffenen Repos anpassen
  • ROBOT_JSON-Env-Variable aus docker-compose-Dateien entfernen, ROBOT_DRIVER_URL hinzufügen

Entschiedene Punkte

Frage Entscheidung
Driver-Start ohne robot.json Mit Defaults starten + Warnung loggen
Snapshot-Limit Max. 100 pro Tag; danach pro Tag nur die letzte Version behalten
Caching in Clients Ja, erlaubt — Ziel ist API-only-Zugriff, kein direktes File-IO
Port InfoServer 2098 bleibt; weitere Endpunkte werden dort angehängt

Nicht in dieser Roadmap

  • Konflikte bei gleichzeitigen Schreibzugriffen (mutex) — vorerst nicht nötig, Homing ist der einzige Schreiber
  • Diff-Anzeige zwischen Snapshots
  • Rollback-Endpunkt (kann manuell über GET /api/robot/history/:ts + PUT /api/robot gemacht werden)