# robot.json – Zugriff via appRobotDriver > **Status: umgesetzt** (2026-06-17) — `server/robotConfig.js` ist aktiv. > Dieses Dokument beschreibt Entwurf und Implementierung. Der Implementierungsplan > (Schritte 1–3) ist vollständig abgearbeitet. --- ## Verhalten je Env-Variable | Variable | nicht gesetzt | gesetzt | |----------|--------------|---------| | `ROBOT_URL` | Kein Driver-Kontakt; alle Lese-/Schreibvorgänge direkt auf die lokale Datei | `fetchRobot()` liest von `GET {ROBOT_URL}/api/robot/config`; `pushRobot()` schreibt nach `POST {ROBOT_URL}/api/robot/config` | | `ROBOT_JSON` | Standardpfad `scripts/robot_1781069752019.json` | Angegebener Pfad wird als lokale Cache-Datei verwendet | Beide Variablen nicht gesetzt = **reiner Lokal-Modus**, identisch zum Verhalten vor dem Umbau. --- ## Ehemaliger Ist-Zustand (vor 2026-06-17) `appRobotHoming` las und schrieb die Roboter-Konfiguration direkt aus einer lokalen Datei: ``` ROBOT_JSON = process.env.ROBOT_JSON || 'scripts/robot_1781069752019.json' ``` Die Python-Skripte erhielten den Dateipfad als CLI-Argument (`-robot`, `--robot`). Alle Kalibrierungs-Endpoints schrieben ebenfalls in diese Datei. **Problem:** Der appRobotDriver besitzt die maßgebliche Konfiguration — nicht das Homing-System. Nach einem Neustart könnten Konfiguration und Driver auseinanderlaufen. --- ## Ziel-Zustand ``` Startup GET {ROBOT_URL}/api/robot/config → robot.json laden Kalibrierung schreiben → lokal anpassen → POST {ROBOT_URL}/api/robot/config Python-Skripte → weiterhin lokale Datei (Cache) (unverändert) ``` `appRobotDriver` ist die **Single Source of Truth**. `appRobotHoming` hält eine **lokale Kopie** (Cache-Datei) nur für die Dauer eines Laufs — Python-Skripte müssen nicht angepasst werden. --- ## appRobotDriver API (Platzhalter) Die genaue API ist noch zu klären. Annahmen: | Aktion | Endpoint | Body / Antwort | |--------|----------|----------------| | Konfiguration lesen | `GET {ROBOT_URL}/api/robot/config` | → JSON (robot.json-Inhalt) | | Konfiguration schreiben | `POST {ROBOT_URL}/api/robot/config` | Body: JSON (robot.json-Inhalt), → `{ ok: true }` | Sobald die echten Endpoints bekannt sind, diese Tabelle und die Implementierung (`server/robotConfig.js`) entsprechend anpassen. --- ## Implementierungsplan ### Schritt 1 — `server/robotConfig.js` (neu) Kapselt den gesamten robot.json-Zugriff. `server.js` und `editRobot.js` importieren nur noch diese Funktionen — kein direktes `fsPromises.readFile` / `writeFile` mehr. ```javascript // server/robotConfig.js (ESM) import fsPromises from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROBOT_URL = process.env.ROBOT_URL || ''; // Lokale Cache-Datei: bleibt als Fallback und für Python-Skripte const ROBOT_JSON = process.env.ROBOT_JSON || path.join(__dirname, '..', 'scripts', 'robot_1781069752019.json'); /** * Lädt robot.json. * Reihenfolge: (1) ROBOT_URL/api/robot/config, (2) lokale Datei als Fallback. * Schreibt das Ergebnis immer in die lokale Cache-Datei (für Python-Skripte). */ export async function fetchRobot() { if (ROBOT_URL) { const res = await fetch(new URL('/api/robot/config', ROBOT_URL)); if (!res.ok) throw new Error(`Driver ${res.status}: ${await res.text()}`); const data = await res.json(); // Cache für Python-Skripte aktualisieren await fsPromises.writeFile(ROBOT_JSON, JSON.stringify(data, null, 2), 'utf8'); return data; } // Fallback: lokale Datei (Entwicklung ohne Driver) return JSON.parse(await fsPromises.readFile(ROBOT_JSON, 'utf8')); } /** * Speichert robot.json. * Schreibt immer in lokale Cache-Datei; sendet zusätzlich an Driver wenn konfiguriert. */ export async function pushRobot(data) { await fsPromises.writeFile(ROBOT_JSON, JSON.stringify(data, null, 2), 'utf8'); if (ROBOT_URL) { const res = await fetch(new URL('/api/robot/config', ROBOT_URL), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); if (!res.ok) throw new Error(`Driver ${res.status}: ${await res.text()}`); } } /** Pfad zur lokalen Cache-Datei – wird an Python-Skripte als -robot-Argument übergeben. */ export const robotCachePath = ROBOT_JSON; ``` --- ### Schritt 2 — `server/editRobot.js` anpassen `readRobot()` und `writeRobot()` sind die einzigen I/O-Primitiven in `editRobot.js`. Sie müssen auf `fetchRobot()` / `pushRobot()` umgestellt werden. **Aktuell:** ```javascript async function readRobot(robotPath) { return JSON.parse(await fsPromises.readFile(robotPath, 'utf8')); } async function writeRobot(robotPath, data) { await fsPromises.writeFile(robotPath, JSON.stringify(data, null, 2), 'utf8'); } ``` **Neu:** ```javascript import { fetchRobot, pushRobot } from './robotConfig.js'; async function readRobot(_robotPath) { // _robotPath ignoriert – Quelle ist Driver return fetchRobot(); } async function writeRobot(_robotPath, data) { return pushRobot(data); } ``` Alle exportierten Funktionen (`assignByZRange`, `setArmMarkerSpin`, `adoptXAxis`, `setJointOriginYZ`, …) bleiben **unverändert** — sie rufen intern `readRobot` / `writeRobot` auf. > Der `robotPath`-Parameter bleibt in den Signaturen erhalten (Kompatibilität), > wird aber ignoriert. Alternativ: alle Aufrufer in `server.js` bereinigen und > Parameter entfernen (Folgeschritt). --- ### Schritt 3 — `server/server.js` anpassen #### 3a — Python-Skripte erhalten weiterhin die Cache-Datei ```javascript // Vorher: import { ROBOT_JSON } from './config.js'; // oder const direkt // '-robot', ROBOT_JSON // Nachher: import { robotCachePath } from './robotConfig.js'; // '-robot', robotCachePath ``` Die Pipeline (`runBoardPipeline`, `runHoming`) fetcht robot.json **einmal vor dem Lauf** via `fetchRobot()`, um den Cache zu aktualisieren: ```javascript import { fetchRobot, robotCachePath } from './robotConfig.js'; async function runBoardPipeline(runDir, send, refSet) { // Cache aktualisieren bevor Python startet await fetchRobot(); // Python-Skripte erhalten robotCachePath wie bisher const script1Args = [..., '-robot', robotCachePath, ...]; // … } ``` #### 3b — `GET /api/robot` liest via `fetchRobot()` ```javascript // Vorher: app.get('/api/robot', async (req, res) => { const robot = JSON.parse(await fsPromises.readFile(ROBOT_JSON, 'utf8')); return res.json(robot); }); // Nachher: import { fetchRobot } from './robotConfig.js'; app.get('/api/robot', async (req, res) => { try { const robot = await fetchRobot(); return res.json(robot); } catch (err) { return res.status(502).json({ error: `Driver nicht erreichbar: ${err.message}` }); } }); ``` #### 3c — Kalibrierungs-Endpoints: kein Änderungsbedarf Da `editRobot.js` intern `readRobot` / `writeRobot` verwendet und diese umgestellt werden (Schritt 2), propagieren sich alle Kalibrierungs-Schreibvorgänge automatisch zum Driver. Kein Änderungsbedarf in den einzelnen Endpoints. --- ## Startup-Verhalten Beim Start von `server.js` einmalig robot.json laden und cachen: ```javascript // server.js – nach HTTPS-Server-Start try { await fetchRobot(); console.log('✅ robot.json vom Driver geladen und gecacht.'); } catch (err) { console.warn(`⚠ Driver nicht erreichbar – nutze lokale Datei: ${err.message}`); } ``` --- ## Fallback-Verhalten | Szenario | Verhalten | |----------|-----------| | `ROBOT_URL` nicht gesetzt | Nur lokale Datei — Entwicklungsmodus, Driver nicht nötig | | Driver beim Start nicht erreichbar | Warnung, lokale Cache-Datei wird verwendet | | Driver während Lauf nicht erreichbar | `pushRobot()` wirft Fehler → Kalibrierungs-Endpoint antwortet 502 | | Python-Skript schlägt fehl | Kein push nötig (Python schreibt nicht in robot.json) | --- ## Datei-Übersicht nach Umbau | Datei | Rolle | |-------|-------| | `server/robotConfig.js` *(neu)* | `fetchRobot()`, `pushRobot()`, `robotCachePath` | | `server/editRobot.js` | `readRobot` / `writeRobot` delegieren an `robotConfig.js` | | `server/server.js` | importiert `robotCachePath` statt lokalem `ROBOT_JSON`; ruft `fetchRobot()` vor Pipelines | | `scripts/robot_1781069752019.json` | Bleibt als lokale Cache-Datei; **nicht** mehr primäre Quelle der Wahrheit | --- ## Status: Umgesetzt (2026-06-17) `server/robotConfig.js` erstellt. `server/editRobot.js` und `server/server.js` angepasst. ## Offene Fragen - [ ] Genaue Endpoints des appRobotDriver für GET / POST robot.json bestätigen (aktuell: `/api/robot/config`) - [ ] Soll der Driver eine Versions-/Konflikterkennung haben (z.B. ETag / `updatedAt`)? - [ ] `pushRobot()` bei Driver-Fehler: aktuell hard fail → Kalibrierungs-Endpoint antwortet 502 - [ ] Authentifizierung zwischen appRobotHoming und appRobotDriver nötig?