Files
appRobotFileservice/doc/fileBrowser.md
2026-06-14 21:45:22 +02:00

4.4 KiB

ROADMAP — appRobotFileservice Web-UI (Datei-Browser)

Ziel

Einfache Web-Oberfläche direkt auf Port 2100, die GCode-Programme verwaltet. Kein Framework, kein Build-Schritt — reines HTML/CSS/JS, serviert als static files.


Phase 1 — Datei-Browser (aktuell implementiert)

Dateien: public/index.html, public/index.css

Funktionen

Feature Status Endpunkt
Programm-Liste laden GET /api/programs
Aktives Programm anzeigen (Zeilenliste in Grad) GET /api/active
Programm als aktiv setzen (FLoad) PUT /api/active
Programm löschen DELETE /api/programs/:id
Stepping: First / Prev / Next / Last `POST /api/active/first
Programm leeren (FClear) POST /api/active/clear
Cursor in Tabelle hervorheben + auto-scrollen
Auto-Refresh (5 s Polling)
Collapse-Karten (wie appRobotHoming)

Was Phase 1 noch fehlt

  • Download .gcode — Endpunkt GET /api/programs/:id/download muss im Server hinzugefügt werden (liefert die rohe Datei mit Content-Disposition: attachment).
  • Upload .gcode — Datei vom Desktop in den Service laden (Phase 2).
  • UmbenennenPUT /api/programs/:id mit neuem name.

Phase 2 — Datei-Verwaltung

Download-Endpunkt (kleines Backend-Feature für Phase 1.5)

GET /api/programs/:id/download
→ Content-Type: text/plain
→ Content-Disposition: attachment; filename="<id>.gcode"
→ Body: rohe .gcode-Datei

Implementierung: 1 Route in src/routes/programs.js + store.gcodePath(id).

Upload

POST /api/programs/upload
Body: multipart/form-data  { file: <gcode-Datei> }
→ speichert unter slugify(filename) in GCodeFiles/

Im Frontend: <input type="file" accept=".gcode,.ngc"> + FormData fetch.

Umbenennen / Metadaten bearbeiten

PUT /api/programs/:id ist bereits vorhanden — nur das Frontend-Formular fehlt. Inline-Eingabefeld in der Programm-Zeile, Enter → PUT.


Phase 3 — Verzeichnis-Navigation

Aktuell: alles flach im GCodeFiles/-Ordner. Später: Unterordner für Projekte (z. B. GCodeFiles/greifen/, GCodeFiles/ablegen/).

Backend

Neue Konfiguration: storageDir bleibt Wurzel; zusätzlicher optionaler subDir-Parameter.

GET /api/programs?dir=greifen        → listet GCodeFiles/greifen/
PUT /api/active { id, dir }          → lädt GCodeFiles/<dir>/<id>.gcode
POST /api/dirs { name }              → legt Unterordner an
DELETE /api/dirs/:name               → löscht (leer) Unterordner

Wichtig: Pfad-Traversal verhindern — assertValidId auf jede Pfad-Komponente anwenden.

Frontend

Breadcrumb-Leiste oberhalb der Programmliste:

GCodeFiles/ > greifen/ > [zurück]

Doppelklick auf Ordner-Zeile → navigiert hinein.
Klick auf Breadcrumb-Segment → navigiert zurück.


Phase 4 — Live-Updates (WebSocket oder SSE)

Aktuell: Polling alle 5 s.
Besser: Server-Sent Events (SSE) oder WebSocket, damit die UI sofort reagiert wenn der Driver per FPoint einen neuen Punkt schreibt.

Option A — Server-Sent Events (einfach, read-only)

GET /api/events
→ text/event-stream
→ event: active-changed\ndata: <ActiveState-JSON>\n\n

Der Fileservice emittiert nach jedem _persist() ein SSE-Event. Frontend: new EventSource('/api/events') statt setInterval.

Option B — WebSocket (bidirektional, für spätere Steuerung)

Erlaubt auch WS-basierte FCode-Befehle direkt von der Web-UI. Aufwändiger, aber konsistent mit dem Driver-Pattern.

Empfehlung für Phase 4: SSE — eine Zeile Mehraufwand gegenüber Polling, kein zusätzliches Protokoll.


Phase 5 — Inline-Editor

Einzelne Zeilen direkt im Browser bearbeiten.

PUT /api/active/lines/:index  { line: "G90 G1 x0 y300 z0 a90.00 …" }
DELETE /api/active/lines/:index
POST /api/active/lines        { line, atIndex }

Alle drei Endpunkte sind bereits im Backend implementiert.
Frontend: Klick auf Tabellenzeile → <input> erscheint inline; Escape abbricht, Enter speichert.


Datei-Übersicht (nach Phase 1)

appRobotFileservice/
  public/
    index.html       HTML-Struktur + JavaScript (inline)
    index.css        Design-System (identisch mit appRobotHoming/styles.css)
  doc/
    fileBrowser_ROADMAP.md   diese Datei
  src/
    server.js        +express.static('public/')
    routes/
      programs.js    TODO Phase 2: /download-Endpunkt
      active.js      komplett