Multiple printers, printer/slot in Spoolman, kept in sync
- One worker per printer (name, IP, CC2 Control URL, own pinned host key); a spool sits in at most one slot of one printer, moves between printers - Spoolman: location "<printer> Slot N" plus extra fields "drucker"/"slot" (created by the bridge), cleared and "Lager" on removal - Full comparison every minute: the printer wins over manual edits of loaded spools; stale printer locations go to storage; own locations untouched - Automatic migration of v1 settings, state and host key - Status hint when a tag is still in a tray but unmapped (e.g. after "Take out" in CC2 Control) - SSH test: connection drops during exec give a clean error, not a 500 - Mock environment with several printers; tests for all of the above Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GcEk5tkfFSYD6NTF66NkC
This commit is contained in:
1 parent
bf32667f77
commit
a9041eb538
15 files changed
+1400
-684
No files matched your search
@@ -1,11 +1,12 @@
|
||||
# cc2-spoolman-bridge
|
||||
|
||||
Bridge zwischen der Canvas des **Elegoo Centauri Carbon 2** (Community-Firmware, CC2 Control) und **Spoolman**,
|
||||
mit Weboberfläche und **NFC-Tag-Generator**.
|
||||
Bridge zwischen der Canvas eines oder mehrerer **Elegoo Centauri Carbon 2** (Community-Firmware, CC2 Control) und
|
||||
**Spoolman**, mit Weboberfläche und **NFC-Tag-Generator**.
|
||||
|
||||
- Liegt eine Spule mit eigenem Tag in der Canvas, erkennt die Bridge die Spoolman-Spule am Tag, legt sie in
|
||||
CC2 Control an (bzw. findet sie wieder), weist sie dem Slot zu und setzt in Spoolman den Ort („CC2 Slot 1–4“,
|
||||
beim Entnehmen „Lager“).
|
||||
- Liegt eine Spule mit eigenem Tag in einer Canvas, erkennt die Bridge die Spoolman-Spule am Tag, legt sie in der
|
||||
CC2 Control dieses Druckers an (bzw. findet sie wieder) und weist sie dem Slot zu.
|
||||
- In Spoolman steht dann, wo die Rolle liegt: Ort „<Drucker> Slot N“ (z. B. „Centauri Carbon 2 Links Slot 3“) und
|
||||
die Zusatzfelder **Drucker** und **Slot**. Entnommene Rollen kommen ins „Lager“, die Felder werden geleert.
|
||||
- Den von CC2 Control gemessenen Verbrauch bucht sie nach jedem Druck auf genau diese Spoolman-Spule.
|
||||
- Der Tag-Generator gibt für jede Spoolman-Spule die vollständige Befehlskette zum Beschreiben eines leeren NTAG213 aus.
|
||||
|
||||
@@ -56,17 +57,23 @@ Oberfläche: `http://10.10.6.10:5066`
|
||||
|
||||
### 3. In der Oberfläche
|
||||
|
||||
1. *Einstellungen* prüfen (Drucker-IP, CC2-Control- und Spoolman-URL, ID-Offset 10000).
|
||||
2. Privaten Schlüssel einfügen oder hochladen und speichern. Er liegt dann mit Rechten 600 in
|
||||
`/data/ssh/id_key`; die Oberfläche zeigt nur Fingerprint und öffentlichen Schlüssel.
|
||||
3. **Verbindung testen**: zeigt die 4 Slots und den Host-Key-Fingerprint des Druckers. Fingerprint vergleichen und
|
||||
bestätigen. Danach wird er bei jeder Verbindung geprüft; ein geänderter Host-Key wird abgelehnt.
|
||||
1. *Einstellungen* → **Drucker**: Name, IP, SSH-Port/-Benutzer und CC2-Control-URL je Drucker; „Drucker
|
||||
hinzufügen“ für weitere. Speichern. Der Name erscheint so in Spoolman (Ort und Feld „Drucker“).
|
||||
2. Privaten Schlüssel einfügen oder hochladen und speichern. Er gilt für alle Drucker (dieselbe eingeschränkte
|
||||
`authorized_keys`-Zeile auf jedem Drucker) und liegt mit Rechten 600 in `/data/ssh/id_key`; die Oberfläche zeigt
|
||||
nur Fingerprint und öffentlichen Schlüssel.
|
||||
3. Je Drucker **Verbindung testen**: zeigt die 4 Slots und den Host-Key-Fingerprint. Vergleichen und bestätigen.
|
||||
Danach wird er bei jeder Verbindung geprüft; ein geänderter Host-Key wird abgelehnt.
|
||||
4. *Status* im Dry-Run beobachten. Wenn die „würde …“-Einträge stimmen, Dry-Run ausschalten.
|
||||
|
||||
Ein Update von v1 übernimmt Einstellungen, Zuordnungen, Buchungsstände und den Host-Key automatisch; der bisherige
|
||||
Drucker heißt danach „CC2“ (Ort bleibt „CC2 Slot N“) und kann in den Einstellungen umbenannt werden – Ort und
|
||||
Felder in Spoolman ziehen dann mit.
|
||||
|
||||
### Umgebungsvariablen
|
||||
|
||||
Siehe [`.env.example`](.env.example). `PRINTER_HOST`, `SSH_PORT`, `SSH_USER`, `CC2_URL`, `SPOOLMAN_URL`,
|
||||
`ID_OFFSET`, `POLL_INTERVAL` und `DRY_RUN` sind nur Startwerte, bis die Einstellungen einmal in der Oberfläche
|
||||
`ID_OFFSET`, `POLL_INTERVAL`, `DRY_RUN` und `PRINTER_NAME` (erster Drucker) sind nur Startwerte, bis die Einstellungen einmal in der Oberfläche
|
||||
gespeichert wurden (`/data/settings.json`). `BRIDGE_USER` und `BRIDGE_PASSWORD` schalten Basic-Auth ein
|
||||
(`/healthz` bleibt offen). `PORT` (Standard 5066), `LOG_LEVEL`.
|
||||
|
||||
@@ -77,15 +84,27 @@ gespeichert wurden (`/data/settings.json`). `BRIDGE_USER` und `BRIDGE_PASSWORD`
|
||||
kleinere Werte sind echte Gewichte von Original- oder Fremdtags und werden ignoriert. Neu ist ein Tag, wenn sich die ID
|
||||
im Slot gegenüber dem letzten Datensatz ändert.
|
||||
|
||||
**Zuordnung.** Die Bridge speichert Slot ↔ Spule selbst (`/data/state.json`). Fällt `weight` nach einer
|
||||
Bearbeitung am Display auf 1000 zurück, bleibt die Zuordnung. Aufgehoben wird sie nur, wenn
|
||||
**Zuordnung.** Die Bridge speichert Drucker/Slot ↔ Spule selbst (`/data/state.json`). Eine Spule liegt höchstens
|
||||
in einem Slot eines Druckers. Fällt `weight` nach einer Bearbeitung am Display auf 1000 zurück, bleibt die
|
||||
Zuordnung. Aufgehoben wird sie nur, wenn
|
||||
- der Slot länger als 20 s leer ist (Tray-Status 0),
|
||||
- CC2 Control die Spule ins Lager legt (Slot ohne Spule und ohne offene Rückfrage),
|
||||
- CC2 Control die Spule herausnimmt („Take out“) oder ins Lager legt (Slot ohne Spule und ohne offene Rückfrage),
|
||||
- im Slot ein Tag mit einer anderen ID gescannt wird oder
|
||||
- die Spule in einem anderen Slot gescannt wird (Umzug).
|
||||
- die Spule in einem anderen Slot oder im anderen Drucker gescannt wird (Umzug).
|
||||
|
||||
Weist du eine gespiegelte Spule in CC2 Control von Hand einem belegten Slot zu, übernimmt die Bridge das.
|
||||
|
||||
**„Take out“ in CC2 Control** zählt als Entnahme: Ort „Lager“, Felder leer. Bleibt die Rolle physisch im Tray,
|
||||
rechnet CC2 Control ihren Verbrauch keiner Spule mehr zu; der Status zeigt dann „Tag steckt noch, ist aber keinem
|
||||
Slot zugeordnet“. Zum erneuten Zuordnen die Rolle neu einlegen und den Scan bestätigen.
|
||||
|
||||
**Spoolman synchron halten.** Nach jeder Änderung schreibt die Bridge Ort und Zusatzfelder (die Felder legt sie beim
|
||||
ersten Mal selbst an). Zusätzlich vergleicht sie jede Minute alle Spoolman-Spulen: Geladene Rollen bekommen ihren
|
||||
Ort/ihre Felder zurück, falls sie dort von Hand geändert wurden (der Drucker gewinnt). Rollen mit einem Druckerort
|
||||
oder gesetztem Feld „Drucker“, die in keinem Slot liegen, kommen ins Lager. Eigene Orte wie „Regal 2“ bei nicht
|
||||
geladenen Rollen bleiben unangetastet. Wird ein Drucker umbenannt oder entfernt, ziehen Ort und Felder mit bzw. seine
|
||||
Rollen kommen ins Lager.
|
||||
|
||||
**CC2 Control.** Gespiegelte Spulen erkennt die Bridge an `note` = `spoolman:<id>`. Fehlt die Spule, legt sie sie
|
||||
mit `name` = Label (`lot_nr`, sonst Hersteller + ID dreistellig), `brand`, `material`, `color`, `diameter`,
|
||||
`density`, `net`, `remaining`, `tare` und `price` aus Spoolman an und weist sie dem Slot zu. Damit ist auch die
|
||||
@@ -131,11 +150,13 @@ Optional kann statt der Elegoo-URL ein Link auf die Spule in Spoolman auf den Ta
|
||||
```bash
|
||||
docker build --target test . # Tests (pytest) im Container
|
||||
docker build -t cc2-spoolman-bridge:dev . # Image
|
||||
python tools/mock_env.py --host-header mock:8081 # Mock für Drucker (SSH :2222), CC2 Control, Spoolman
|
||||
python tools/mock_env.py --host mock --printers 2 # Mock: 2 Drucker (SSH :2222/2223, CC2 :8081/8082), Spoolman
|
||||
```
|
||||
|
||||
Die Tests decken ab: Tag-Kodierung gegen die verifizierte Vorlage, ID-Dekodierung, Palette und Materialvorschlag,
|
||||
Zuordnung bei verschwindender ID, Verbrauchs-Delta und Idempotenz (auch nach Abbruch), Dry-Run, Request-Format für
|
||||
Zuordnung bei verschwindender ID, Verbrauchs-Delta und Idempotenz (auch nach Abbruch), Dry-Run, mehrere Drucker
|
||||
(Umzug, Ausfall eines Druckers, Entfernen, Umbenennen), Spoolman-Ort und Zusatzfelder inkl. Korrektur von Hand-
|
||||
Änderungen, Migration von v1, Request-Format für
|
||||
CC2 Control (Host-Header, kein Origin, `X-CC2-Request`, `key=value`-Body, `enable` als nacktes `on`/`off`) und SSH
|
||||
mit Host-Key-Prüfung gegen einen lokalen SSH-Server.
|
||||
|
||||
|
||||
Reference in new issue
Block a user