Files
appRobotDriver/doc/ToDo_14_robot_json_service.md
2026-06-12 17:03:38 +02:00

8.1 KiB
Raw Permalink 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 (→ ToDo 3)
4a — InfoServer auf Express umgestellt appRobotDriver erledigt
4b — UI: Robot.json + History in index.html 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)

InfoServer.js wurde auf Express umgestellt. Registrierung mit einer Zeile:

robotConfigService.register(app, { apiKey: options.apiKey });

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

Ausgelagert nach robot/RobotConfig.js (→ ToDo 3). Liest beim Start synchron data/robot/robot.json, leitet l1/l2/l3 aus links.*.skeleton.to ab (nicht mehr aus size):

// links.Arm1.skeleton.to[1]   → l1 (Math.abs)
// links.Arm2.skeleton.to[1]   → l2 (Math.abs)
// links.Ellbow.skeleton.to[0] → l3

Fallback auf Defaults wenn Datei fehlt. Controller-IPs/-Ports/-Achsen ebenfalls aus robot.json (keine hardcodierten Werte mehr in startRobot.js).

Schritt 4a — InfoServer auf Express umgestellt

server/InfoServer.js nutzt jetzt Express statt rohem https.createServer. Ermöglicht saubere Router-Registrierung und ist Grundlage für alle weiteren API-Endpunkte.

Schritt 4b — UI: Robot.json + History in index.html

Zwei neue Panels im InfoServer-Frontend (public/index.html + app.js):

  • Robot.json — zeigt aktuelle robot.json mit aufklappbaren Top-Level-Abschnitten (<details>). Aktualisiert sich automatisch, solange kein Snapshot ausgewählt ist. Label (_label-Feld) wird oben angezeigt.
  • Robot.json History — listet alle Snapshots aus GET /api/robot/history. Klick auf Eintrag lädt diesen Snapshot in das Robot.json-Panel. Klick auf „aktuell" schaltet zurück auf Live-Ansicht.

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)