8.8 KiB
robot.json – Zugriff via appRobotDriver
Status: umgesetzt (2026-06-17) —
server/robotConfig.jsist 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.
// 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:
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:
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 inserver.jsbereinigen und Parameter entfernen (Folgeschritt).
Schritt 3 — server/server.js anpassen
3a — Python-Skripte erhalten weiterhin die Cache-Datei
// 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:
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()
// 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:
// 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?