Initiales Projekt-Skelett appRobotFileservice
Ausgelagertes Programm-/File-Handling (vormals GCode.receiveFC im appRobotDriver, ToDo_4 / ToDo_6b). Express-Service mit .gcode + .json-Storage, aktivem Programm + Cursor, Teaching (FPoint) und Playback. Speicherung in Grad, driver-nativ (Radian) zum Driver. Konzept/API unter doc/draft_filehandeling*.md. Tests: jest (13 gruen). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
129
README.md
Normal file
129
README.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# appRobotFileservice
|
||||
|
||||
Programm-/File-Handling-Service für den AppRobot. Speichert **G-Code-Programme**
|
||||
(`.gcode` + `.json`-Sidecar), hält das **aktive Programm + Cursor** und unterstützt
|
||||
**Teaching** (Pose aufnehmen) und **Playback** (Programm abspielen).
|
||||
|
||||
Dieses Projekt wurde aus dem `appRobotDriver` ausgelagert (vormals `GCode.receiveFC`,
|
||||
ToDo_4 / ToDo_6b). Konzept und Schnittstelle:
|
||||
[`doc/draft_filehandeling.md`](doc/draft_filehandeling.md) ·
|
||||
[`doc/draft_filehandeling_API.md`](doc/draft_filehandeling_API.md).
|
||||
|
||||
## Rolle in der Architektur
|
||||
|
||||
```
|
||||
Steuerungen → appRobotDriver → appRobotFileservice
|
||||
(Joystick, …) (Gateway) (dieses Projekt, passiv)
|
||||
```
|
||||
|
||||
- Steuerungen kennen **nur den Driver**. Datei-Befehle (**FCodes** wie `FList`,
|
||||
`FPoint`, `FPlus`) schickt die Steuerung an den Driver, der sie als REST-Aufrufe
|
||||
hierher weiterreicht.
|
||||
- Dieser Service ist **passiv und driver-agnostisch**: er ruft den Driver nie an,
|
||||
kennt weder dessen URL noch dessen Pose. Beim `FPoint` schickt der **Driver die
|
||||
Pose mit**.
|
||||
- **Playback:** dieser Service liefert die nächste Zeile **driver-nativ (Radian)**
|
||||
zurück; **ausgeführt** wird sie vom Driver.
|
||||
|
||||
## Einheiten (wichtig)
|
||||
|
||||
- **Gespeichert** wird in **Grad** (standardnahe `.gcode`, lesbar): `a/b/c/e` in Grad,
|
||||
`x/y/z` in mm.
|
||||
- **Am Wire / zum Driver** ist alles **driver-nativ**: `a/b/c/e` in **Radian**.
|
||||
- Die Umrechnung passiert **ausschließlich hier** (`src/gcode/units.js`) — der Driver
|
||||
rechnet nie um.
|
||||
|
||||
## Dateiformat
|
||||
|
||||
`.gcode` sieht aus wie Standard-G-Code; Zeitstempel und Cursor stehen im
|
||||
**Kommentarfeld** (`;…`, standardkonform):
|
||||
|
||||
```
|
||||
G90 G1 x0 y300 z0 a90.00 b-90.00 c0.00 e0.00 f1000 ;1759566014
|
||||
G90 G1 x310 y444 z0.5 a90.00 b-90.00 c0.00 e6.88 f1000 ;1759566112! <- Cursor (!)
|
||||
```
|
||||
|
||||
- `;<epoch>` = Aufnahme-Zeitstempel · abschließendes `!` = Cursor-Zeile.
|
||||
- Der Cursor lebt zur Laufzeit als In-Memory-Index (schnelles Stepping ohne
|
||||
Neuschreiben) und wird beim Speichern/Entladen als `!` zurückgeschrieben.
|
||||
- `<id>.json` ist ein Sidecar mit Metadaten (Name, Zeiten, `lineCount`, `angleUnit`).
|
||||
|
||||
## Start
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start # http://localhost:2100
|
||||
npm test # jest
|
||||
```
|
||||
|
||||
HTTP (kein TLS) — der Service ist intern (Driver → Service). TLS kann später analog
|
||||
zum Driver-`InfoServer` ergänzt werden.
|
||||
|
||||
## API (Kurzüberblick)
|
||||
|
||||
Vollständig in [`doc/draft_filehandeling_API.md`](doc/draft_filehandeling_API.md).
|
||||
|
||||
| FCode (am Driver) | Endpoint |
|
||||
|---|---|
|
||||
| `FList` | `GET /api/programs` |
|
||||
| `FShow [id]` | `GET /api/programs/:id` |
|
||||
| `FSave <name>` | `POST /api/programs` |
|
||||
| `FLoad <id>` | `PUT /api/active` |
|
||||
| `FClear` | `POST /api/active/clear` |
|
||||
| `FPoint` | `POST /api/active/points` |
|
||||
| `FPlus` / `FMinus` | `POST /api/active/next` / `/prev` |
|
||||
| `FFirst` / `FLast` | `POST /api/active/first` / `/last` |
|
||||
| `FGoto <n>` | `POST /api/active/goto` |
|
||||
| `FPlay` / `FStop` | `POST /api/active/play` / `/stop` |
|
||||
|
||||
Beispiel:
|
||||
|
||||
```bash
|
||||
# Teaching: leeres Programm aktiv, Pose aufnehmen, speichern
|
||||
curl -X PUT localhost:2100/api/active -H 'content-type: application/json' -d '{"id":"demo_c"}'
|
||||
curl -X POST localhost:2100/api/active/points -H 'content-type: application/json' \
|
||||
-d '{"pose":{"x":0,"y":300,"z":0,"a":1.5708,"b":-1.5708,"c":0,"e":0},"feedrate":1000}'
|
||||
curl -X POST localhost:2100/api/programs -H 'content-type: application/json' -d '{"name":"Demo C","fromActive":true}'
|
||||
|
||||
# Playback: laden, erste Zeile (Radian) holen → der Driver führt sie aus
|
||||
curl -X PUT localhost:2100/api/active -H 'content-type: application/json' -d '{"id":"demo_c"}'
|
||||
curl -X POST localhost:2100/api/active/first
|
||||
```
|
||||
|
||||
> Hinweis: `PUT /api/active` legt ein nicht existierendes Programm **leer an** (für
|
||||
> Teaching). `EMPTY_PROGRAM`/`CURSOR_OUT_OF_RANGE` betreffen nur das Stepping/Playback.
|
||||
|
||||
## Konfiguration (Env)
|
||||
|
||||
| Variable | Default | Zweck |
|
||||
|---|---|---|
|
||||
| `FILE_SERVICE_PORT` | `2100` | Port |
|
||||
| `STORAGE_DIR` | `./GCodeFiles` | Verzeichnis für `.gcode` + `.json` |
|
||||
| `FILE_EXT` | `gcode` | `gcode` oder `ngc` |
|
||||
| `STORE_ANGLE_UNIT` | `deg` | Speichereinheit der Winkel |
|
||||
| `FILE_API_KEY` | – | Bearer-Token für Schreibzugriffe (fehlt → offen, Dev) |
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
```
|
||||
index.js Einstiegspunkt (startet den Server)
|
||||
src/
|
||||
config.js Env-Konfiguration
|
||||
server.js Express-App (createApp)
|
||||
errors.js Fehler-Envelope + Middleware
|
||||
auth.js Bearer-Auth (für Schreibzugriffe)
|
||||
gcode/units.js Grad↔Radian, Zeilenformat, Cursor-/Kommentar-Helfer
|
||||
store/fileStore.js .gcode + .json Persistenz (id-basiert, kein Pfad-Zugriff)
|
||||
active/activeState.js aktives Programm + Cursor (Single Source of Truth)
|
||||
routes/programs.js /api/programs*
|
||||
routes/active.js /api/active*
|
||||
test/ jest (units, fileStore, activeState)
|
||||
doc/ Konzept + API (Drafts)
|
||||
GCodeFiles/ Programm-Storage (zur Laufzeit)
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
Erste lauffähige Umsetzung. Offen u. a.: WebSocket-Event-Kanal (Live-Cursor),
|
||||
Playlists („nächste File"), benannte Labels im Sidecar, TLS. Siehe „Offene Fragen"
|
||||
in [`doc/draft_filehandeling.md`](doc/draft_filehandeling.md).
|
||||
Reference in New Issue
Block a user