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

271 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
```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?