# ToDo – appRobotHoming Nächste Schritte für den Umbau zum statischen Frontend + HTTPS-BFF-Proxy. Kontext/Architektur: siehe [`../README.md`](../README.md). Reihenfolge ist grob nach Priorität sortiert. Offene Entscheidungen sind als **Frage** markiert – die müssen vor der Umsetzung geklärt werden. --- ## 1. HTTPS wieder zum Laufen bringen (blockierend) **Diagnose abgeschlossen (2026-06-08):** - Backend läuft auf 2093, aber als **HTTP** (`http://…:2093/` → 200 + UI; `https://…:2093/` → keine Antwort). Es ist der **Container** (docker-compose): `/api/health` meldet `webcamUrl: http://appRobotWebcam:8444`. - Der Code ist korrekt: `https/localhost.key` + `localhost.pem` mit Passphrase `abcd` laden lokal **einwandfrei** in `https.createServer`. - **Root Cause:** Die Cert-Dateien **fehlen im Container**. `.gitignore` schließt `*.key`/`*.pem`/`*.pfx` aus → nicht in git → der Mount `/home/chk/Documents/appRobotHoming` auf `thinkcentre` hat sie nicht → `createHttpsServer()` scheitert an `fsPromises.access()` → **stiller HTTP-Fallback** (`server/server.js`, `createHttpsServer` → `return null`). **Gewählte Lösung (Entscheidung): Cert reist mit dem Repo/Volume.** Das self-signed Cert sichert nur den Hop **Proxy ↔ Backend** und hat keinen echten Wert (nie öffentlich). Daher darf es mit ins Repo und kommt über den bestehenden `/app`-Volume-Mount automatisch in den Container. - [x] `.gitignore`: gezielte Ausnahme `!https/localhost.key` + `!https/localhost.pem` (Schutz für alle anderen Schlüssel bleibt bestehen). → erledigt. - [ ] `https/localhost.key` + `https/localhost.pem` committen. - [ ] Deploy-Host `thinkcentre:/home/chk/Documents/appRobotHoming/` aktualisieren (git pull bzw. Dateien bereitstellen), damit der Container sie sieht. - [ ] Verifizieren: `https://thinkcentre.local:2093/api/health` antwortet über **HTTPS** (aktuell nur HTTP). Optional (separat, nicht Teil der Entscheidung): - [ ] Passphrase/Pfad konsequent aus dem Env (`HTTPS_KEY_PATH`/`HTTPS_CERT_PATH`/ `HTTPS_PASSPHRASE`) statt hartkodiert. - [ ] Stillen HTTP-Fallback lauter machen (klar loggen / hart abbrechen statt unbemerkt HTTP) – dieser Fallback hat den Bug verschleiert. - [ ] Reverse-Proxy prüfen: Leitet er WSS-Upgrade-Header korrekt an `https://…:2093` weiter? --- ## 2. WebCam-Bilder über die dokumentierte API holen → **entschieden: Option B** `server/server.js` ruft aktuell `WEBCAM_URL + /api/latest-snapshot` auf – diesen Endpoint gibt es **nicht**. **Entscheidung:** Der Homing-Backend setzt das Bundle selbst aus den dokumentierten Endpoints zusammen (kein neuer Endpoint im WebCam-Service). Service läuft und ist erreichbar unter `http://thinkcentre.local:8444` (→ `WEBCAM_URL`). Real verifizierte Contracts: - `GET /api/cameras` → ```json {"cameras":[ {"id":"cam0","name":"Kamera 0","position":"front","stream":true,"hires":true, ...}, {"id":"cam1","name":"Kamera 1","position":"left", "stream":true,"hires":true, ...}, {"id":"cam2","name":"Kamera 2","position":"right","stream":true,"hires":true, ...} ]} ``` - `GET /api/snapshot/{id}/hires` → `200 image/jpeg` (cam0/cam1 ~1280px, cam2 1920px). - `GET /health` → Status + `state`/`hasFrame` pro Kamera. Umsetzung in `server/server.js` (`/api/latest-snapshot`): - [ ] `GET {WEBCAM_URL}/api/cameras` holen → Kameraliste (mit `hires:true` filtern). - [ ] Für jede Kamera **parallel** `GET {WEBCAM_URL}/api/snapshot/{id}/hires` → JPEG, als base64 + `id`/`position` ins Bundle. - [ ] Bundle ans UI zurückgeben (statt der bisherigen CSV-Annahme). Reihenfolge/ Zuordnung über `id`+`position` stabil halten (wichtig für §3). - Hinweis: Die alte CSV/`_annotated.jpg`/JSON-Marker-Erkennung kommt **nicht** von der Webcam. Für den BodyTracker-Pfad ist sie ohnehin redundant (BodyTracker macht ArUco selbst); sie bleibt nur für den lokalen Fallback `public/calculateAngles.js` relevant. --- ## 3. Intrinsics-Fluss → **entschieden: WebCam liefert Intrinsics mit** **Klarstellung der Datentypen** (im Altcode unter „Intrinsics" vermischt): | Typ | Beispiel | Quelle | statisch | |---|---|---|---| | **Kamera-Intrinsics** (K, Distortion) | das echte „NPZ" | Kalibrierung | ✅ pro Kamera | | **Extrinsics** (`position_mm`, `orientation_deg`) | in `_two_cam.json` | wird gelöst | ❌ Output | | **Marker-3D-Posen** | in `_two_cam.json` | trianguliert | ❌ Output | Das, was `server/server.js` heute als `robotIntrinsics` (= `_two_cam.json`) schickt, sind **Extrinsics + triangulierte Marker** – also **BodyTracker-Output**, fälschlich als Input verschickt. Muss raus. Die WebCam liefert aktuell **kein** NPZ (alle Intrinsics-Endpoints → 404). Der BodyTracker hält in `/v1/config` nur Solver-Parameter, keine Intrinsics. **Entscheidung:** Die Kamera-Intrinsics leben beim **WebCam-Service** (Source of Truth) und werden mitgeliefert. Homing reicht sie an den BodyTracker durch. Aufgaben WebCam-Service: - [x] **Kalibrierung vorhanden** (verifiziert 2026-06-10): `/api/cameras` liefert `calibrationUrl` für alle 3 Kameras (cam0/cam1/cam2). `.npz`-Abruf über `GET /api/cameras/{id}/calibration` → `application/octet-stream` funktioniert. Kein Neu-Kalibrieren nötig. Aufgaben Homing-Backend (`server/server.js`): - [ ] `robotIntrinsics`/`_two_cam.json`-Pfad aus `/api/estimate` entfernen. - [ ] Pro Kamera Bild + zugehörige Intrinsics paaren (über `id`) und an `BODYTRACKER/v1/estimate` weiterreichen. **N Kameras** (aktuell 3), nicht fix 2. Aufgaben BodyTracker (wir besitzen ihn): - [ ] `/v1/estimate` so anpassen, dass er Intrinsics **als JSON je Kamera** annimmt (kein `.npz`-Zwang) – erspart NPZ-Erzeugung in Node. Format gemeinsam festzurren (K 3×3 oder fx/fy/cx/cy, dist k1,k2,p1,p2,k3, `image_size`). --- ## 4. Aufräumen (Altlasten aus der WSS/HTTPS-Server-Ära) - [ ] `docker-compose.yaml`: `WSS_VIDEO_DRIVER`, `WSS_URL`, `HTTPS_PORT`-Doppelung und `depends_on: appRobotDriver` prüfen/entfernen. Behalten: `WEBCAM_URL`, `BODYTRACKER_URL`, Port-Mapping `2093`, Cert-Volume. - [ ] `package.json` → `description` ist veraltet („verbindet zu WSS, sendet Befehle"). - [ ] Command-Buttons in `public/index.html` (HOME/STOP/STATUS/RESET/PING/ GCodeMotor) rufen `window.sendCommand` – **das ist nirgends definiert** (alter WSS-Transport). Entweder neuen Transport anbinden (gehört zu Erweiterung „Pose an appRobotDriver") oder bis dahin deaktivieren. - [ ] `public/snapshots` (Fallback) ist leer → `findLatestSnapshotFile()` liefert `null` → 404. Beispiel-Datensatz ablegen **oder** Fallback dokumentiert abschalten. --- ## 5. Frontend / UX (geplante Erweiterungen) - [ ] Erkennungsergebnis + erkannte Pose klarer ausgeben (statt nur Roh-JSON). - [ ] Manuelle Eingabe von `x, y, z, a, b, c, e`. - [ ] Wenn Hand nicht erkannt: Vorschlag für bessere Arm-/Foto-Position. - [ ] Pose an `appRobotDriver` weitergeben (neuer Schritt nach BodyTracker; ggf. der WSS-Pfad, für den HTTPS gebraucht wird). --- ## Definition of Done (erster Meilenstein) 1. `https://:2093/` liefert das statische UI über **HTTPS**. 2. `GET /api/latest-snapshot` liefert reale Bilder/Daten vom WebCam-Service. 3. `POST /api/estimate` liefert eine Pose vom BodyTracker und zeigt sie im UI. 4. Keine toten Buttons / keine WSS-Altlasten in Compose & package.json.