Files
appRobotHoming/doc/accessRobotAPI.md
2026-06-19 06:43:06 +02:00

8.8 KiB
Raw Blame History

robot.json Zugriff via appRobotDriver

Status: umgesetzt (2026-06-17) — server/robotConfig.js ist aktiv.
Dieses Dokument beschreibt Entwurf und Implementierung. Der Implementierungsplan (Schritte 13) 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 in server.js bereinigen 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?