Grotti 2.2.0: Auth, API-Tokens, MCP und Doku-Trennung.
This commit is contained in:
1 parent
b20f8a7779
commit
5a3716b26a
65 files changed
+2212
-198
No files matched your search
@@ -0,0 +1,42 @@
|
||||
# ACE-Farben in Grotti (Moonraker)
|
||||
|
||||
Stand **12.10.2026**: An Kobra 3 **da26** (`10.10.1.60`) liefert Moonraker die ACE-Spulenfarben unter **`mmu`**, nicht unter `filament_hub` (steht oft nicht in `objects/list`).
|
||||
|
||||
- Relevante Felder: `gate_color` (Hex `AARRGGBB` oder `RRGGBB`), `gate_material`, optional `gate_status` bzw. Listen pro Platz.
|
||||
- Grotti liest das in `grotti/moonraker.py` (`extract_slots`) und zeigt die Farben als Swatches auf der Druckerwand.
|
||||
- Fallback: `filament_hub` / `filament_hubs[].slots` mit `color` und `type`, falls vorhanden.
|
||||
|
||||
## Senden: welches Material welcher Slot
|
||||
|
||||
12.10.2026: In `Dateien` bei Druckern mit Slots die Slice-Farbe (`paint_index`) einem ACE-Platz (`ams_index`, 0-basiert) zuordnen. Grotti schreibt `Dateiname.gcode.acm` und lädt sie vor `print/start` hoch. Ohne Sidecar: auf `da26` oft HTTP 400 „cannot parse the file“. Siehe [Grotti-Senden-Queue](Grotti-Senden-Queue).
|
||||
|
||||
## 12.10. Abbruch `tulip pla.gcode` auf da26 — kein ACE-Blink
|
||||
|
||||
Beobachtung: Material ging initial zum Extruder, ACE-Slot blinkte nicht, kein Nachschub vom ACE. Andere Kobra 3 (92ee/6e41) drucken dieselbe Datei von der externen Spule weiter; nicht angefasst.
|
||||
|
||||
Ursache (Moonraker-Log `da26`, lesend):
|
||||
|
||||
- Job `000009` (tot-printing, 0 mm Filament) und `00000A` (~695 s Druck, ~658 mm) beide `cancelled` auf `10.10.1.60`.
|
||||
- Bei jedem MQTT-Start: `mmu_ace.patch_print_data` → `detected_tools unknown … skipping auto-feed (no trailer found)`. Ohne Trailer/Tools kein Auto-Feed → kein Slot-Blinken, kein ACE-Nachschub.
|
||||
- Metadaten-Extrakt für die Datei scheitert (`Unable to extract metadata` / `mmu_ace_metadata` abgebrochen).
|
||||
- Grotti-Sidecar `tulip pla.gcode.acm`: `paint_index 0 → ams_index 1` (Farbe Datei `#000000`, Slot-Farbe `002B49`). Parallel liegt `tulip pla.acm` mit Identity-Map T0–T3 → Plätze 0–3. MQTT-Payload nutzte die 4er-Map, nicht Grotti-1er-Map.
|
||||
- Start ohne `bed_leveling`: Grotti übergibt `ams_settings` nur als `.acm`; Moonraker baut die MQTT-`ams_settings` selbst. `auto_leveling: 0`.
|
||||
- Initialer Extruder-Feed ohne Blink: Restfilament im Pfad / Extrusion aus dem Schlauch, nicht ACE-Auswahl. Nach Abbruch: `mmu.gate`/`tool` = −1, `active_filament` leer; vier Plätze weiter belegt.
|
||||
|
||||
Grotti-DB `sends`: da26 zweimal `tulip pla.gcode` (ohne persistiertes `ace_map`; Mapping nur in der Queue im Speicher und in der `.acm` auf dem Drucker). Queue-API leer nach Abschluss.
|
||||
|
||||
Nächster Start auf da26: gewünschten ACE-Platz in Grotti setzen (bei schwarzer Slice-Farbe zuletzt Platz 1 = dunkelblau). Alte `tulip pla.acm` nicht mit Grotti-`.gcode.acm` vermischen. Ohne erfolgreichen Trailer/Metadaten bleibt Auto-Feed aus — dann blinkt der ACE weiterhin nicht.
|
||||
|
||||
## Fix Grotti (12.10.2026, nach Diagnose)
|
||||
|
||||
Anycubic erwartet die Sidecar als **gleichen Basename + `.acm`**: Start `tulip pla.gcode` → `tulip pla.gcode.acm`. Grotti lädt Grotti-Map zusätzlich nach `tulip pla.acm` hoch (Überschreiben), damit eine alte Identity-Map nicht gewinnt.
|
||||
|
||||
Mit gesetzter ACE-Zuordnung startet Grotti den Druck per **MQTT** und setzt `ams_box_mapping` aus Grotti-Map — nicht mehr nur über Moonraker-`print/start` (dort Identity-Fallback / falsche `.acm`). Bettnetz-Checkbox steuert weiter nur `auto_leveling`.
|
||||
|
||||
13.10.2026: Fehlt `; referenced_tools` beim Senden mit ACE-Zuordnung, hängt Grotti ihn an — aus T-Befehlen, sonst aus `paint_info` / der gewählten `paint_index`-Map (Einzelfarbe oft `0`). Zusätzlich die Rinkhals-Kopfzeile `; processed by MmuAcePatcher`. Warnung nur noch, wenn danach immer noch kein Trailer da ist.
|
||||
|
||||
## 13.10.2026 — MQTT 10101 trotz Moonraker `cancelled` (da26 / Gridfinity)
|
||||
|
||||
Nach Grotti-Send `Gridfinity_bin_1x1x6u_PLA_0.2_49m32s.gcode` an `da26` (`10.10.1.60`): Moonraker `print_stats.state` = `cancelled`, Anycubic-MQTT-Task blieb aktiv → nachfolgender Start mit **code 10101** („已存在打印任务“ / Print task already exists). Grotti `abbrechen` traf nur Moonraker `/printer/print/cancel`, nicht den Anycubic-Task.
|
||||
|
||||
Klärung: MQTT `action: stop`, `taskid: "-1"` auf Topic `…/slicer/printer/{modelId}/{deviceId}/print` (Rinkhals-Docs). Report `state: stopping`, code 200; danach MQTT-Info `data.state: free`. Grotti `abbrechen` macht seither Moonraker-cancel **und** best-effort MQTT-stop (`anycubic_lan.cancel_print`). Wenn MQTT-stop nicht greift: Display abbrechen oder Reboot als letzte Option.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Grotti: Abräumen und weiterdrucken (Kobra 3)
|
||||
|
||||
Stand **13.10.2026**.
|
||||
|
||||
Nach dem Druck kann Grotti auf der **Kobra 3** Bett und Düse abkühlen und die Teile mit dem Extruderkopf nach vorn vom Bett schieben. Danach startet der nächste Schritt oder die nächste Wiederholung. Die **Kobra S1** ist geschlossen — Abräumen dort ist noch offen.
|
||||
|
||||
## Quittierung vs. Schieben
|
||||
|
||||
- **Wand „Platte geräumt“:** Nur Quittierung. Tabelle `bed_status`, API `POST /api/v1/drucker/<host>/abraeumen` mit `confirm`. Fährt keine Bahn. `needs_clear` setzt der Watcher bei Druckende/Abbruch/Fehler (nicht schon beim Start). Solange gesetzt, startet „wenn frei“ den nächsten Job nicht.
|
||||
- **Ablauf (Dateien):** Drucken → Abkühlen → Schieben → Tasten, dann der nächste Druck mit LeviQ. Eine Bestätigung beim Einreihen; Schieben läuft ohne zweite Rückfrage. Nach erfolgreichem Schieben ist die Platte automatisch quittiert.
|
||||
- **Normale Drucke** und „Nochmal“ schieben nicht — nach dem Druck muss man auf der Wand quittieren.
|
||||
|
||||
## Oberfläche
|
||||
|
||||
Unter **Dateien** erscheint die Karte **Ablauf**, sobald mindestens eine Kobra 3 gewählt ist. Der Nutzer baut die Schritte selbst:
|
||||
|
||||
- **Drucken** — Datei, Bettnetz (LeviQ) standardmäßig an
|
||||
- **Abkühlen** — Heizung aus, Lüfter an, Düse in die Bettmitte, warten bis Bett/Düse unter den Grenzen
|
||||
- **Schieben** — Bahn mit einstellbaren Zahlen, danach Lüfter aus
|
||||
- **Tasten** — kein `G28 Z`. **Mit aktivem LeviQ-Netz** (kein `BED_MESH_CLEAR`): `Result` = Höhe über der lokalen Platte. Bezugspunkt + Tastpunkt (x/y) einstellbar. Maß: letztes `Result is z=` aus dem Store. Über 1 mm = Restteil.
|
||||
|
||||
Darunter **wie oft hintereinander**. Einreihen legt einen Eintrag in die Warteschlange „Wenn frei“. **Schieben testen** fährt die Bahn auf einer freien Kobra 3 (Bestätigung „Bett ist leer“). Werte merkt sich der Browser lokal.
|
||||
|
||||
Vor dem Bett braucht es eine Kiste. Der Weg nach vorn muss frei sein.
|
||||
|
||||
Standardreihenfolge: `Drucken → Abkühlen → Schieben → Tasten` (dann Wiederholung, LeviQ am Druckstart). Altes 3×3-Prüfen (`probe_count` / `mesh_*`) wird übersprungen und in der Schrittleiste nicht mehr gezeigt.
|
||||
|
||||
## Standardbahn (editierbar)
|
||||
|
||||
- Abkühlen: Heizung aus, Idle verlängern (Stepper an), Park Bettmitte. Z zuerst relativ **+40 mm** (gegen Z-max gekappt), dann X125/Y125. Hub wird geprüft.
|
||||
- Schieben: hoch → Y hinten (`y_from` Default **250**) → Z noch klar? → **langsam** auf `z_push` (`F400`, nie F3000). Z prüfen; bei Abweichung Abbruch. Nur die X-Spuren aus der Config. `M107`.
|
||||
- Tasten: Mesh an. Absolut auf Freiraum, ein `PROBE` am Tastpunkt, `Result is z=`. Kein `SET Z=100` / Bezug-Null (hat die Koordinate nur verfälscht). Z zu tief nach Leerlauf → Abbruch, Idle soll Stepper an lassen.
|
||||
|
||||
Y klein ist vorn. Das Wischpad liegt hinten (~Y 260) und bleibt außerhalb der Bahn. Grotti klemmt Eingaben (X 0–250, Y 0–235, Z-Schieben 0,6–30, Z-Umsetzen bis 80, Tempo 5–80 mm/s).
|
||||
|
||||
## Technik
|
||||
|
||||
- Kein Makro auf dem Drucker (`printer.cfg` schreibt Rinkhals neu). Grotti schickt G-code per Moonraker `/printer/gcode/script`.
|
||||
- Modul `grotti/eject.py`, Steuerung in `print_queue.py`.
|
||||
- Ablauf = eine Queue-Zeile mit `steps` (JSON), `step_index`, `repeat_total`, `repeat_done`, `phase`.
|
||||
- Nach dem Druck kein `G28` (Z-Home würde in die Teile fahren). Slice-Ende Present nur `X250 Y220` — **kein Z-Hub**. Abkühlen: Heizung aus, Lüfter an, relativ Z+40 (≤ Z-max), dann X 125 Y 125. Schieben: anheben, Spur hinten ansetzen, langsam senken, nach vorn, hinten parken, `M107`.
|
||||
- Abräumen braucht gehomed Achsen. Slice-Ende der Kobra 3 enthält `M84; disable motors` (nach Present) — danach sofort unhomed. Bei Ablauf mit Cool/Sweep entfernt Grotti `M84`/`M18` beim Upload. Zusätzlich: `SET_IDLE_TIMEOUT` schon während des Drucks und alle 120 s beim Abkühlen; wenn trotzdem unhomed, `SET_KINEMATIC_POSITION` mit der **echten** letzten Toolhead-XYZ (Present), nie erfundene Z. Kein automatisches `G28` bei belegtem Bett. „Schieben testen“ (Bett leer bestätigt) homt mit `G28`.
|
||||
|
||||
Gestoppter Ablauf: Seitenleiste ▶ setzt beim gespeicherten `step_index` fort (`PATCH /druck-queue/<id>` mit `status: running, resume: true`).
|
||||
- Tasten: Mesh aus, Rand-PROBE + Z-Null (Retract 2 mm), Mitte-PROBE, letztes `Result is z=` gegen `max_delta_mm`. Nie `G28 Z`. Nie Toolhead-Z nach dem Retract. Fortsetzen bei gemeldetem Z unter Bett erlaubt (nur relativ hoch).
|
||||
- Druckfehler oder Abbruch stoppt den Ablauf — kein Weiterschieben.
|
||||
|
||||
## Trockenlauf (Crash-Fix prüfen)
|
||||
|
||||
Bett **leer**, ein Drucker reicht. Ziel: Cool-Hub und Anfahren hinten testen, **ohne** `G0 Z{z_push}`.
|
||||
`PROBE` fährt nur bis Trigger — nicht wie `G0 Z2` zwangsweise auf Koordinate. Trotzdem **nicht** mit Z8 starten (nach dem Crash zu unheimlich).
|
||||
|
||||
**Lauf A — sicher (zuerst):**
|
||||
1. `G28`, Düse wischen.
|
||||
2. `G90` → `G0 Z40 F1800` → Present `X250 Y220`.
|
||||
3. Cool-Park: relativ Z+40 (≤ Z-max), Mitte. Erwartung: Z ≈ 80, Mitte.
|
||||
4. `sweep_go_back_high` (hoch + Y hinten). Erwartung: hinten, Z klar oben.
|
||||
5. Statt Senken: **`PROBE`**. Erwartung: `Result is z=` typisch < 1 mm; sofort `G0 Z40`.
|
||||
6. Stop. Keine Y-Bahn, kein `z_push`.
|
||||
|
||||
**Lauf B — niedrige „letzte Schicht“ (nur wenn A sauber):**
|
||||
Wie A, aber Schritt 2 mit `G0 Z15` (nicht Z8). Cool +40 → Z ≈ 55. Wieder nur PROBE, nie `G0 Z2`.
|
||||
|
||||
Optional ganz am Ende: einmal `sweep_lower` mit `F400` + `assert_clear`, Bett leer — nur nach A+B ok.
|
||||
|
||||
Grotti-Schalter „Trockenlauf / PROBE statt z_push“ noch nicht gebaut — bis dahin manuell oder `_tmp_`-Skript mit `eject.*_script`.
|
||||
|
||||
## Grenzen
|
||||
|
||||
- Nur Familie `kobra_3`.
|
||||
- Teile höher als die Umsetzhöhe trifft die Düse auf dem Weg nach hinten.
|
||||
- Festsitzendes Material (z. B. PETG) schiebt die Düse nicht zuverlässig ab.
|
||||
|
||||
## Backlog (später)
|
||||
|
||||
Ideen liegen in Grotti unter **Ideen** (Status „später“), nicht nur hier:
|
||||
|
||||
- **Abdeckungen gegen Verkanten** — Führung/Rutsche vorn, damit geschobene Teile nicht an Bettkante, Rahmen oder in der Kiste verkanten und den nächsten Lauf blockieren.
|
||||
- **Kobra S1** — eigener Abräum-Ablauf (geschlossen, Tür).
|
||||
|
||||
Erledigt: Antasten / Bettnetz vergleichen (Schritt **Prüfen**, 13.10.2026).
|
||||
@@ -0,0 +1,141 @@
|
||||
# Anycubic-Stack: wie Druck, Abbruch und ACE wirklich laufen
|
||||
|
||||
Stand **15.10.2026**. Quellen: Anycubic [Klipper-go](https://github.com/ANYCUBIC-3D/Klipper-go), [K3-klipper-mcu](https://github.com/ANYCUBIC-3D/K3-klipper-mcu); Rinkhals `kobra.py`, `mmu_ace.py`, `mmu_ace_metadata.py`, Docs `firmware/mqtt.md` und `firmware/goklipper.md` (lokal unter `D:\Projekte\_ref\`). Nicht geraten — am Quellcode und an der Rinkhals-Doku gelesen.
|
||||
|
||||
## Schichten
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph host [PC]
|
||||
Grotti[Grotti]
|
||||
end
|
||||
subgraph printer [Kobra 3 / S1]
|
||||
Moonraker[Moonraker + kobra.py]
|
||||
MmuAce[mmu_ace + mmu_ace_metadata]
|
||||
Gkapi[gkapi MQTT Broker]
|
||||
Gklib[gklib GoKlipper]
|
||||
Ui[K3SysUi Touch]
|
||||
Mcu[MCU Firmware]
|
||||
AceHw[ACE Hardware]
|
||||
end
|
||||
Grotti -->|"HTTP :80 upload / print/start / cancel"| Moonraker
|
||||
Grotti -->|"MQTTS :9883 print start/stop"| Gkapi
|
||||
Grotti -->|"HTTP :18910 info/ctrl Credentials"| Gkapi
|
||||
Moonraker -->|"bei print/start oft MQTT lokal :2883"| Gkapi
|
||||
Moonraker --> Gklib
|
||||
MmuAce --> Moonraker
|
||||
Gkapi --> Gklib
|
||||
Ui --> Gkapi
|
||||
Gklib --> Mcu
|
||||
Gklib --> AceHw
|
||||
```
|
||||
|
||||
| Komponente | Offen? | Rolle |
|
||||
| --- | --- | --- |
|
||||
| **gklib** (GoKlipper) | teilweise ([Klipper-go](https://github.com/ANYCUBIC-3D/Klipper-go)) | Klipper-Host: Motion, Heater, `virtual_sdcard`, ACE-G-codes |
|
||||
| **MCU** | teilweise ([K3-klipper-mcu](https://github.com/ANYCUBIC-3D/K3-klipper-mcu)) | Stepper/Sensoren |
|
||||
| **gkapi** | nein (proprietär) | MQTT-Broker, Druck-Tasks, Cloud/LAN, Credentials `:18910` |
|
||||
| **K3SysUi** | nein | Touch-UI |
|
||||
| **Rinkhals Moonraker** | ja | Vanilla Moonraker + `kobra.py` + `mmu_ace*` |
|
||||
|
||||
Anycubic schreibt in den READMEs: proprietäre Features sind gekapselt. MQTT-Taskverwaltung und Cloud stecken nicht in Klipper-go.
|
||||
|
||||
## Zwei Welten beim Druckstart
|
||||
|
||||
1. **Klipper-Pfad** (Moonraker `POST /printer/print/start` → gklib `virtual_sdcard`): setzt `print_stats`, lädt G-code in gklib.
|
||||
2. **Anycubic-Task** (MQTT `type: print`, `action: start` an Topic `…/slicer/printer/{modelId}/{deviceId}/print`): legt den Job an, den Display und Cloud kennen; steuert LeviQ/`auto_leveling`, ACE-Map in der Payload.
|
||||
|
||||
Rinkhals `kobra.py` `patch_mqtt_print` hängt den Moonraker-`print/start` oft auf MQTT um (`mqtt_print_file`), lokal `127.0.0.1:2883`. Grotti kann denselben Start von außen über **MQTTS `:9883`** mit Credentials aus `:18910` machen — dann mit eigener `task_settings` und `ams_settings` (siehe [Senden-Queue](Senden-Queue)).
|
||||
|
||||
### MQTT Start (belegt)
|
||||
|
||||
Aus Rinkhals-Doku `firmware/mqtt.md` und `kobra.py`:
|
||||
|
||||
- Publish: `anycubic/anycubicCloud/v1/slicer/printer/{modelId}/{deviceId}/print`
|
||||
- Report: `…/printer/public/{modelId}/{deviceId}/print/report`
|
||||
- Pflichtfelder Start: `filename`, `filetype` (1), `taskid`
|
||||
- Optional: `ams_settings.ams_box_mapping`, `task_settings.auto_leveling` (0/1 Integer)
|
||||
- Rinkhals und Grotti setzen `taskid` auf eine Zufallszahl; die Doc-Minimalbeispiel nutzt `"-1"` — beides kommt vor
|
||||
|
||||
### MQTT Stop (belegt) — warum 10101
|
||||
|
||||
```json
|
||||
{ "type": "print", "action": "stop", "data": { "taskid": "-1" } }
|
||||
```
|
||||
|
||||
Moonraker `/printer/print/cancel` trifft nur gklib (`print_stats` → `cancelled`). Der Anycubic-Task in gkapi bleibt → nächster MQTT-Start mit **code 10101** („Print task already exists“ / chinesische Meldung). Rinkhals `mqtt_print_file` kennt 10101 und **retryt einmal**; Grotti sendet bei Abbruch Moonraker-cancel **und** MQTT-stop.
|
||||
|
||||
### Task-Hygiene (wie Rinkhals)
|
||||
|
||||
Vorbild: `kobra.py` `mqtt_print_file` + `firmware/mqtt.md`. **Kobra 3 und Kobra S1** — dieselbe gkapi-API (`:18910` / MQTTS `:9883`). Gemessen 15.10.2026: S1 `modelId` 20025 / `state: free`, K3 `modelId` 20024; `project: null` zählt nicht als busy. Abräumen-Ablauf bleibt nur Kobra 3.
|
||||
|
||||
| Schritt | Verhalten in Grotti |
|
||||
| --- | --- |
|
||||
| Vor MQTT-Start | `ensure_task_free`: `info/query`; wenn `state` nicht free oder `project` gesetzt → MQTT-stop, bis zu 3× pollen |
|
||||
| Vor Moonraker-`print/start` | dieselbe Hygiene best-effort (Rinkhals wandelt Start oft intern zu MQTT um) |
|
||||
| gkapi kurz weg | `print_info` → `None`, negativer Cache ~45 s; Start über Moonraker läuft weiter |
|
||||
| Report **10101** | einmal cancel + 1,5 s Pause + erneuter Start |
|
||||
| Report **10107** | klare Filament-Meldung |
|
||||
| Live | Snapshot-Feld `anycubic_task` (`state`, `task_id`, `filename`) aus gecachtem `print_info` (TTL ~10 s); Wand zeigt die Zeile |
|
||||
|
||||
Codes und Retry: `grotti/anycubic_lan.py` (`message_for_code`, `ensure_task_free`, `start_print`).
|
||||
|
||||
### Report-Timeout
|
||||
|
||||
`kobra.py` wartet max. 30 s auf `print/report`. Nach Bettnetz/`auto_leveling` kann der Report später kommen, der Druck trotzdem laufen (`info/query` → `project.task_id`). Grotti prüft bei Timeout deshalb `print_info` (MQTT `info/query`).
|
||||
|
||||
## FIRMWARE_RESTART
|
||||
|
||||
In **Klipper-go** ist der Befehl implementiert wie bei Klipper:
|
||||
|
||||
- `Cmd_FIRMWARE_RESTART` → `Request_restart("firmware_restart")` (`gcode.go`)
|
||||
- Nach dem Reactor-Ende: Event `project:firmware_restart` → MCU `_firmware_restart` (`k3c.go`, `Mcu.go`)
|
||||
|
||||
Auf dem Gerät **deadlockt gklib** trotzdem (beobachtet, Rinkhals #32): Log zeigt Annahme des Befehls, danach keine weitere Verarbeitung, Moonraker bleibt in `startup`. Rinkhals `patch_klipper_restart` **lehnt** `RESTART` / `FIRMWARE_RESTART` unter GoKlipper ab. Grotti ebenso. Config: Display-Reboot oder Strom. Hängenden Fehler: **Fehler löschen** (`SDCARD_RESET_FILE`), nicht Firmware-Restart.
|
||||
|
||||
Der Open-Source-Code erklärt den Intent des Befehls; die Deadlock-Ursache steckt vermutlich im ausgelieferten Binary / der Anbindung an gkapi — nicht im veröffentlichten Happy Path.
|
||||
|
||||
## ACE
|
||||
|
||||
### In gklib (Klipper-go `extras_ace.go`)
|
||||
|
||||
G-codes: `ACE_CHANGE_TOOL`, `ACE_FEED`, `ACE_RETRACT`, `ACE_SET_SLOT`, Trocknen, Endless Spool, … Kommunikation über Seriell (`extras_ace_commun.go`). `Get_status` liefert ACE-`info` + Endless-Spool-Flags — **nicht** das Moonraker-Objekt `mmu` mit `gate_color`.
|
||||
|
||||
### In Rinkhals Moonraker (`mmu_ace.py`)
|
||||
|
||||
- Emuliert Happy-Hare-ähnliches **`mmu`**-Objekt (`gate_color`, `gate_material`, …) für Clients
|
||||
- Beim MQTT-Start: `register_print_data_patcher` → wenn keine `ams_settings` in der Payload, baut Identity-/TTG-Map aus den Gates und hängt `ams_settings` an
|
||||
- Liest/schreibt Sidecar **`basename.acm`** neben dem G-code; ohne ACE kann sie nach `.acm.disabled` umbenannt werden
|
||||
- Auto-Feed-Logik vor Start, wenn nichts im Toolhead ist (Issue #464)
|
||||
|
||||
### Upload-Metadaten (`mmu_ace_metadata.py`)
|
||||
|
||||
Beim Moonraker-Upload: ganze Datei lesen, ggf. umschreiben. Fingerprint `; processed by MmuAcePatcher`. Trailer `; referenced_tools = 0,2,…`. Ohne Trailer: gklib „skipping auto-feed (no trailer found)“. Grotti setzt Fingerprint + Trailer vor dem Upload, damit der teure Durchlauf entfällt ([Senden-Queue](Senden-Queue)).
|
||||
|
||||
### `.acm` vs MQTT-`ams_settings`
|
||||
|
||||
Zwei Kanäle für dieselbe Zuordnung:
|
||||
|
||||
| Kanal | Wann |
|
||||
| --- | --- |
|
||||
| Datei `name.gcode.acm` / `name.acm` auf dem Drucker | Stock/gklib liest Sidecar beim Start |
|
||||
| MQTT-Feld `data.ams_settings` | gkapi / Rinkhals-Patcher legt Map in die Payload |
|
||||
|
||||
Ohne Map: Rinkhals füllt oft Identity T0→Platz0 … — deshalb Grotti bei eigener ACE-Zuordnung per MQTT mit expliziter Map startet und beide `.acm`-Varianten hochlädt ([ACE-Live](ACE-Live)).
|
||||
|
||||
## Was Grotti bewusst nutzt
|
||||
|
||||
| Aktion | Weg | Beleg |
|
||||
| --- | --- | --- |
|
||||
| Einfacher Start | Upload + Moonraker `print/start` → Rinkhals MQTT | `kobra.py` `patch_mqtt_print` |
|
||||
| Start mit Bettnetz oder ACE-Map | Upload (+ `.acm`) + Grotti-MQTT `:9883` | `anycubic_lan.start_print`, mqtt.md |
|
||||
| Abbruch | Moonraker cancel + MQTT stop `taskid:-1` | `mqtt_stop_print`, mqtt.md |
|
||||
| Credentials | `:18910/info` + `/ctrl` AES | `anycubic_lan.credentials` |
|
||||
| Slots anzeigen | Moonraker `mmu` (Rinkhals) | `mmu_ace.py` |
|
||||
| Kein Firmware-Restart | abgelehnt | Rinkhals #32, `patch_klipper_restart` |
|
||||
|
||||
## Offene Grenzen
|
||||
|
||||
- Quellcode von **gkapi** (Task-State-Machine, exakte 10101-Bedingungen) ist nicht öffentlich.
|
||||
- Deadlock in **FIRMWARE_RESTART** ist beobachtet und in Rinkhals abgefangen, Root Cause im Binary nicht freigelegt.
|
||||
- Kobra X / K4-Stack ist ein anderes System (C++-Klipper), nicht GoKlipper — für unsere Drucker irrelevant.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Chargen, Etiketten und 3D-Viewer
|
||||
|
||||
Stand 14.10.2026.
|
||||
|
||||
## Spulen-Chargen
|
||||
|
||||
Jede Spule in Grotti bekommt automatisch eine `chargen_nr` der Form `S-YYYYMMDD-0001`. Derselbe Wert steht in `code` und auf dem Etikett. Optional: `hersteller_charge` vom Rollenetikett.
|
||||
|
||||
Scannen: auf Material den Code tippen oder per USB-Handscanner (Tastatur + Enter). Lookup `GET /api/v1/spulen/by-code/<code>`. QR auf dem Etikett öffnet `/material?spool=<id>`.
|
||||
|
||||
Etikett: `/etikett/<id>`, Druck über den Browser. QR per lokalem `qrcode.min.js` (`web/static/`). Basis-URL für den QR kommt aus Einstellungen → **FQDN** (`config.json` Key `fqdn`); leer = Host der aktuellen Anfrage. Beispiel: `https://grotti.example.de/material?spool=12`.
|
||||
|
||||
## 3D-Pfad
|
||||
|
||||
`GET /api/v1/dateien/<id>/pfad` liefert einen gedünnten Toolpath (bis ca. 120 000 Punkte, plus `layer_breaks`, Cache-`version` 5) aus dem lokalen G-code. Die Dateien-Seite und das Cockpit zeichnen ihn mit Three.js.
|
||||
|
||||
Darstellung: nur Extrusionswege. Preview = orange. Live: gedruckt leicht verdickt grün, offen grau; Schnitt nach `progress`. Parser akzeptiert `E.39`/`Z.6`. Bett: Gitter 10 mm, mm-Sprites, Legende.
|
||||
|
||||
**Exclude-Object** (nur Klipper/Moonraker): Status aus `exclude_object`. Polygone im Viewer; Liste unter dem Pfad; Zwei-Klick → `POST .../steuern` Action `exclude_object` mit `confirm`. Fehlt Modul/DEFINEs → Panel aus. BambuLab später eigener Adapter.
|
||||
|
||||
Cockpit-Live: Kamera-Frames werden unsichtbar vorgeladen (letztes Bild bleibt), `no-cam`-Layout nur ohne Kamera-URL. 3D-Orbit bleibt beim 5‑s-Poll erhalten (`setPath` nur beim ersten Laden / Dateiwechsel).
|
||||
|
||||
Auf der Wand: Caption `Dateiname · % · Schicht a/b`, sonst „Datei nicht in Grotti“.
|
||||
|
||||
Bedienung: Orbit / Zoom / Schwenken / Doppelklick-Reset; Tippen auf Polygon wählt das Objekt.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Grotti-Dateien Metadaten
|
||||
|
||||
`stored_path` liegt nur in der DB und in Rohzeilen (`get_file_row`, `list_file_rows`). Die API-Antwort (`file_out` / `GET /api/v1/dateien`) enthält den Pfad bewusst nicht.
|
||||
|
||||
`POST /api/v1/dateien/neu-lesen` liest Watch-Ordner neu und ruft `refresh_file_meta` auf Rohzeilen auf — nicht auf `list_files`, sonst `KeyError: 'stored_path'`.
|
||||
|
||||
## Was der Parser liest
|
||||
|
||||
Kopfkommentare **und** Footer (letzte ~128 KB). Anycubic/Orca legen Gewicht, Zeit und Prozesswerte oft ans Dateiende.
|
||||
|
||||
In der Bibliothek gespeichert:
|
||||
|
||||
| Feld | Bedeutung |
|
||||
|------|-----------|
|
||||
| `filaments` | Typ/Farbe (`paint_info` oder `filament_type`/`filament_colour`) |
|
||||
| `weight_g` / `estimated_s` | Filamentgewicht und Druckzeit |
|
||||
| `printer_family` | aus `printer_model` |
|
||||
| `slice_meta` | jsonb: `layer_height`, `layers`, `max_z_mm`, `nozzle_mm`, `temp_nozzle`, `temp_bed`, `slicer` |
|
||||
|
||||
Anzeige: Material, Zeit, Gewicht, Schichthöhe, Maschine, Projekt immer in der Zeile; Rest im Info-Popup bzw. unter der gewählten Datei. Nach Parser-Update: **Ordner neu lesen**.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Grotti: Alltag und Oberfläche
|
||||
|
||||
Stand **14.10.2026**, v1.4.0.
|
||||
|
||||
## Design
|
||||
|
||||
- Dunkles UI mit Orange-Akzent, Lucide-ähnliche Stroke-Icons (SVG-Sprite in `layout.html`).
|
||||
- Kurze Seitenuntertitel; Technik-/Config-Hinweise liegen in der Doku, nicht als Fließtext in den Formularen.
|
||||
- Einheitliche Seitenköpfe, Toolbar-Filter, kompakte Tabellen, Formularfelder mit kleinen Labels, Empty-States mit Icon.
|
||||
- **Anzeige pro Browser** (Einstellungen → Dieser Browser): `Desktop` oder `Regal (Touch)` in `localStorage grotti-display`. Shortcut `?shelf=1` / `?shelf=0`. Regal: größere Controls, kompakte Nav (Drucker/Kameras/Warteschlange), Sidebar default eingeklappt.
|
||||
- Seitenmenü einklappbar (Icon-Rail, `grotti-nav-collapsed`). Unter 760 px weiter Bottom-Nav.
|
||||
|
||||
## Seitenleiste
|
||||
|
||||
- Hauptmenü: Drucker, Dateien, Kameras, Aktivität, Warteschlange, Protokoll, Material, Projekte. Darunter Einstellungen, Ideen, Doku (mit Icons); Fuß **© by dominic@gundel.dev** und Version (Changelog).
|
||||
- Live-Leiste, eigene Scrollfläche, Boxen auf- und zuklappbar (Zustand in `localStorage` `grotti-live-closed`):
|
||||
- **Läuft jetzt**: laufende Aufträge und Abläufe mit Schrittleiste, Durchlauf `n/m`, aktueller Phase und ×-Abbrechen; auch Direktstarts ohne Queue.
|
||||
- **Wartet**: wartende Aufträge mit Ziel, Priorität hoch/runter, Abbrechen; die letzten Fehler mit Fortsetzen/ausblenden.
|
||||
- **Aufgaben**: Platte belegt ohne Ablauf — „geräumt“ per Zwei-Klick.
|
||||
- **Senden**: laufende Uploads mit Fortschritt.
|
||||
- **Alerts**: ungelesene wichtige Ereignisse, „gelesen“, Link auf Aktivität.
|
||||
- Aktualisierung: Senden 2 s, Queue 4 s, Aufgaben/Alerts 8 s.
|
||||
|
||||
## Wand
|
||||
|
||||
- Karte je Drucker: Zustandschip, Fertig-Uhrzeit groß, Fortschrittsbalken, drei Kacheln (Rest, Schicht, Läuft), Temperaturbalken Düse/Bett mit Ziel, Datei. Klick auf die Karte öffnet das Cockpit. Pause, Abbrechen, Fehler löschen und Platte geräumt bleiben auf der Karte (Zwei-Klick).
|
||||
- Laufender Ablauf als Streifen mit Schrittleiste und Abbrechen. Wartende Aufträge für diesen Drucker als Hinweis.
|
||||
- Streifen „Fehler“ mit **Fehler löschen** und „Platte belegt“ mit **Platte geräumt** (während eines Ablaufs ausgeblendet, der räumt selbst).
|
||||
- **Cockpit** (Hash `/#<host>`): Kamera (Frame-Vorladen; zugeklappt oder ohne Kamera → eine Spalte, kein leeres 16:10), Status, Temps inkl. Bauraum wenn vorhanden, Lüfter-Icons, Steuerung, 3D-Pfad (Exclude-Object), Bettnetz. E-Stop nur bei printing/paused/heating, Zwei-Klick. Live vom Watcher.
|
||||
|
||||
## Dateien und Senden
|
||||
|
||||
- Links Bibliothek: Suche, Filter Maschine/Projekt, Vorschaubild; Zeile zeigt Material, Zeit, Gewicht, Schichthöhe, Maschine, Projekt; Details per Info-Popup. Metadaten aus G-code-Kopf **und** Footer. Hochladen / Ordner neu lesen.
|
||||
- Rechts der Flow: Datei → Drucker (Live-Zustand, eingelegte Rolle) → Wann (Jetzt / Wenn frei / Nächster freier) oder Reiter Ablauf.
|
||||
- Kein freies Spulen-Dropdown: Abzug nimmt die Rolle(n) am Ziel-Drucker zur Startzeit. ACE: Zuordnung Datei-Farbe → Platz. Warnung bei Material-Mismatch oder zu wenig Rest.
|
||||
- Startknopf mit Zwei-Klick bei „Jetzt“. Auswahl in `localStorage` `grotti-send-v1`.
|
||||
|
||||
## Material
|
||||
|
||||
- Reiter **Spulen** / **Sorten**. Scan-Feld im Seitenkopf.
|
||||
- Spulen: Filter Alle / Am Drucker / Regal / Wenig Rest + Suche. Formular nur bei Auswahl oder „Neue Spule“ (× schließt). Ort = Drucker · ACE/extern bzw. Regal.
|
||||
- Sorten: Profile (Dichte, mm³/s, Preis, Maschinen). Anlegen/ändern/löschen; „Spule damit anlegen“ wechselt zum Spulen-Reiter.
|
||||
|
||||
## Warteschlange
|
||||
|
||||
- Seite `/warteschlange`: Filter Läuft / Wartet / Fehler / Historie. Priorität, Abbrechen, Fortsetzen.
|
||||
- Unter **Läuft** / **Alle aktiv** auch Direktstarts aus `/laeuft` (ohne Queue-Zeile), mit Fortschritt und Link zur Wand.
|
||||
|
||||
## Aktivität
|
||||
|
||||
- Zeitstrahl nach Tagen. Filter in der URL. Ungelesene Alerts markiert.
|
||||
|
||||
## Kameras und Handy
|
||||
|
||||
- Kamerakacheln mit Live-Zustand (`live=1`). Snapshot-Cache 2 s. Unter 760 px: Schnellmenü Drucker / Dateien / Aktivität.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Glossar: Moonraker, Mainsail und der Rest
|
||||
|
||||
Stand **15.10.2026**. Begriffe rund um Kobra 3 / S1, Rinkhals und Grotti. Architektur-Details: [Anycubic-Stack](Anycubic-Stack).
|
||||
|
||||
## Die Schichten in einem Satz
|
||||
|
||||
| Schicht | Rolle |
|
||||
| --- | --- |
|
||||
| **MCU-Firmware** | Läuft auf der Drucker-Platine: Stepper, Heizer, Sensoren. |
|
||||
| **gklib (GoKlipper)** | „Gehirn“ auf dem Linux der Kobra — Anycubics Go-Port von Klipper. |
|
||||
| **gkapi** | Anycubic-Dienst: MQTT, Cloud/LAN, Druck-Tasks, Touch-Anbindung. |
|
||||
| **Moonraker** | HTTP/WebSocket-API vor gklib — das, was Apps und Grotti ansprechen. |
|
||||
| **Mainsail / Fluidd** | Web-Oberflächen *auf* Moonraker (Live-Steuerung, Konsole). |
|
||||
| **Grotti** | Eure lokale Farm-Seite: Queue, Wand, Material, Abräumen — spricht Moonraker (+ MQTT wo nötig). |
|
||||
| **Rinkhals** | Community-Aufsatz auf der Stock-Firmware: bringt Moonraker, SSH, Apps. |
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
UI[Mainsail / Fluidd / Grotti / Orca]
|
||||
UI --> MR[Moonraker]
|
||||
UI -.->|Start mit ACE/Bettnetz, Stop| MQTT[gkapi MQTT]
|
||||
MR --> GK[gklib GoKlipper]
|
||||
MQTT --> GK
|
||||
Touch[K3SysUi Touch] --> MQTT
|
||||
GK --> MCU[MCU]
|
||||
GK --> ACE[ACE]
|
||||
```
|
||||
|
||||
## A–Z
|
||||
|
||||
### ACE
|
||||
Anycubic Color Engine — Multimaterial-Box (vier Plätze). Ansteuerung in gklib (`ACE_*`-G-codes); Zuordnung Farbe→Platz oft über Sidecar **`.acm`** und/oder MQTT **`ams_settings`**. In Moonraker erscheint das bei Rinkhals oft als Objekt **`mmu`** (`gate_color`, …).
|
||||
|
||||
### Fluidd
|
||||
Web-UI für Klipper/Moonraker, Alternative zu Mainsail. Gleiche API, anderes Aussehen. Bei Rinkhals typisch Port **4408**.
|
||||
|
||||
### FIRMWARE_RESTART
|
||||
Klipper-Befehl: Host + MCU neu laden. Auf **GoKlipper** deadlockt gklib oft (Rinkhals #32). Grotti und Rinkhals lehnen ihn ab → Display-Reboot oder Strom.
|
||||
|
||||
### gklib / GoKlipper
|
||||
Anycubics Klipper-Host in Go (Open Source: [Klipper-go](https://github.com/ANYCUBIC-3D/Klipper-go)). Entspricht grob dem klassischen `klippy`. Dateiname auf dem Drucker: `gklib`.
|
||||
|
||||
### gkapi
|
||||
Geschlossener Anycubic-Dienst neben gklib. Betreibt den lokalen MQTT-Broker, Druck-Tasks, Credentials (`:18910`), Anbindung Touch/Cloud. Hier sitzt der Task, der bei Abbruch **10101** verursacht, wenn nur Moonraker-cancel kommt.
|
||||
|
||||
### Grotti
|
||||
Dieses Tool: lokale deutsche Seite für mehrere Moonraker-Drucker — Wand, Warteschlange „wenn frei“, Abräumen (Kobra 3), Material, Kosten, Telegram. Kein Slicer, keine Cloud.
|
||||
|
||||
### K3SysUi
|
||||
Anycubic-Touch-Oberfläche (geschlossen). Rinkhals patcht sie, um das eigene Menü einzuhängen.
|
||||
|
||||
### Klipper
|
||||
Open-Source-Firmware-Architektur: schwere Berechnung auf dem Host (Linux), MCU führt Bewegungen aus. Vanilla-Klipper ist Python (`klippy`); auf der Kobra 3 läuft die Go-Variante.
|
||||
|
||||
### Mainsail
|
||||
Beliebte Web-UI für Moonraker: Status, Temp, G-code-Konsole, Dateien, Webcam. Bei Rinkhals oft Port **80** / **4409**. Fühlt sich „direkter“ an als Grotti, weil die Konsole offen ist.
|
||||
|
||||
### Moonraker
|
||||
API-Server vor Klipper/gklib: HTTP und WebSocket. Upload, `print/start`, Pause, `gcode/script`, `objects/query`, Kamera-Proxy. **OctoPrint-Äquivalent** in der Klipper-Welt. Grotti und Mainsail sind Clients davon — Moonraker ist nicht die schöne Oberfläche selbst.
|
||||
|
||||
### MQTT (hier)
|
||||
Protokoll zu **gkapi**, nicht zu Moonraker. Topics wie `…/slicer/printer/{modelId}/{deviceId}/print`. Genutzt für Druck **start/stop**, Info-Query, optional Temp/Speed/Licht. Ports: lokal oft **2883**, von außen TLS **9883**.
|
||||
|
||||
### OctoPrint
|
||||
Klassische Host-Software für (meist) Marlin-Drucker: Web-UI, Plugins, oft G-code-**Streaming** Zeile für Zeile. Bei Klipper/Rinkhals ersetzt durch **Moonraker + Mainsail/Fluidd** (Datei komplett hochladen, Host spielt ab).
|
||||
|
||||
### Orca / AnycubicSlicerNext
|
||||
Slicer auf dem PC. Schicken fertige `.gcode` per Moonraker (oder USB). Kein Teil der Drucker-Firmware.
|
||||
|
||||
### printer.cfg / printer.generated.cfg
|
||||
Klipper-Konfiguration. Auf Anycubic oft generiert/neu geschrieben; Rinkhals warnt vor wildem Editieren (Boot-Risiko). Z-Offset u. a. in `printer_mutable.cfg`.
|
||||
|
||||
### Repetier-Server
|
||||
Host-Software ähnlich OctoPrint (eigene UI, oft Streaming/direktes G-code). Gleicher Kontrast: auf der Kobra ist der Host **gklib**, die API **Moonraker**.
|
||||
|
||||
### Rinkhals
|
||||
Community-Overlay auf Stock-Kobra-OS: Moonraker, Mainsail/Fluidd, SSH, App-Store, ohne die Stock-Firmware zu ersetzen. Installiert der Nutzer selbst (SWU). Docs: [rinkhals-community/Rinkhals](https://github.com/rinkhals-community/Rinkhals).
|
||||
|
||||
### SSH
|
||||
Root-Shell auf dem Drucker-Linux (Rinkhals: Port 22, `root` / `rockchip`). Zum Debuggen, Logs, App-Properties — **nicht** der normale Weg für Drucksteuerung (das bleibt Moonraker).
|
||||
|
||||
### SWU
|
||||
Anycubic-Update-Paket auf USB (Ordner `aGVscF9zb3Nf`). Darüber kommen Stock-Updates und Rinkhals/Installer.
|
||||
|
||||
### virtual_sdcard
|
||||
Klipper-Modul: G-code liegt als Datei auf dem Host und wird von gklib abgespielt. Deshalb Upload + Start statt Streaming über WLAN.
|
||||
|
||||
### 10101
|
||||
Anycubic-MQTT-Fehler: „Druck-Task existiert schon“. Typisch nach Abbruch nur über Moonraker, ohne MQTT `action: stop`.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Haftung
|
||||
|
||||
**Entwurf.** Kein anwaltlich geprüfter Text. Vor einem Verkauf mit Preis, Abo oder Shop kommen Impressum, Datenschutz und AGB dazu. Diese Seiten nennen keinen Preis.
|
||||
|
||||
Stand **14.10.2026**. Was die Drucker können müssen, steht unter [Voraussetzungen](Voraussetzungen.md).
|
||||
|
||||
## Grundsatz
|
||||
|
||||
Grotti flasht nicht, schickt keine Firmware und beschreibt keine Signatur-Umgehung, keinen Root-Exploit und keine Umgehung einer Downgrade-Sperre.
|
||||
|
||||
Der Nutzer richtet seinen eigenen Drucker ein, bevor er Grotti nutzt. Verlinkt wird nur die Installationsseite von Rinkhals: <https://github.com/rinkhals-community/Rinkhals>. Die Warnung, die der Hersteller selbst einblendet, bleibt seine.
|
||||
|
||||
Anycubic schließt ungenehmigte Änderungen von der Garantie aus. Rinkhals ist ein Community-Aufsatz; die ursprüngliche Software bleibt darunter, der Aufsatz lässt sich wieder entfernen. Ob Anycubic einen Fall annimmt, entscheidet Anycubic.
|
||||
|
||||
Creality lässt beim offiziellen Root den Hardware-Service stehen und gibt dafür keine Software-Unterstützung. Fremde Firmware ist von der Garantie ausgenommen (<https://wiki.creality.com/en/warranty-policy>).
|
||||
|
||||
Bambu Lab deckt Schäden durch inoffizielle Firmware nicht ab. Der Entwicklermodus ist eine eigene Funktion von Bambu Lab, mit der Warnung, die Bambu Lab selbst einblendet.
|
||||
|
||||
Die gesetzliche Mängelhaftung für den Drucker bleibt beim Verkäufer des Druckers. Ein Disclaimer Grotti wischt Verletzung, Vorsatz und grobe Fahrlässigkeit nicht weg.
|
||||
|
||||
Unbeaufsichtigtes Drucken, Hitze und Brandgefahr stehen vor dem ersten Start, nicht im Kleingedruckten.
|
||||
|
||||
Es gibt kein Auftrags-Flashen und keine vorgeflashten Drucker.
|
||||
|
||||
## Vor dem ersten Start
|
||||
|
||||
Düse und Bett werden heiß. Den ersten Lauf behält der Nutzer im Blick. Der Satz dazu steht oben, nicht erst hier: Unbeaufsichtigtes Drucken, Hitze und Brandgefahr stehen vor dem ersten Start, nicht im Kleingedruckten.
|
||||
|
||||
## Was Grotti beim Start schon verlangt
|
||||
|
||||
Druckstarts brauchen eine Bestätigung (`confirm: true`). Es gibt keine freie G-code-Konsole und kein `FIRMWARE_RESTART`.
|
||||
@@ -0,0 +1,30 @@
|
||||
# MCP-Server
|
||||
|
||||
Stand **15.10.2026**. Agenten steuern Grotti nur über die HTTP-API mit einem API-Token.
|
||||
|
||||
## Start
|
||||
|
||||
```powershell
|
||||
$env:GROTTI_URL = "http://127.0.0.1:8770"
|
||||
$env:GROTTI_TOKEN = "grt_…" # unter Einstellungen → API-Tokens
|
||||
$env:GROTTI_MCP_READ_ONLY = "1" # optional: nur lesen
|
||||
.\.venv\Scripts\pip install mcp
|
||||
.\.venv\Scripts\python.exe -m grotti.mcp_server
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | Schreibend | Confirm |
|
||||
| --- | --- | --- |
|
||||
| `list_printers`, `get_printer`, `list_running`, `list_queue`, `list_events`, `list_files`, `list_spools`, `get_version` | nein | — |
|
||||
| `pause_printer`, `resume_printer` | ja | — |
|
||||
| `cancel_printer`, `clear_bed`, `enqueue_*` | ja | `confirm=true` |
|
||||
| `steer_temp`, `steer_speed`, `steer_fan` | ja | — |
|
||||
|
||||
Nicht exponiert: freie G-code, Firmware-Restart, E-Stop, User/Token/Settings.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- Token mit Rolle Operator reicht für den Alltag; Admin-Token vermeiden.
|
||||
- Read-only-Flag für vorsichtige Agents.
|
||||
- Server ideal nur lokal; Grotti selbst hinter Login/TLS.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Grotti Ops: Queue, Alerts, Steuerung
|
||||
|
||||
Stand 14.10.2026.
|
||||
|
||||
## Einstellungen
|
||||
|
||||
Seite `/einstellungen`: Druckernamen/Host/Familie/gesperrt (PostgreSQL `printers`, `drucker.json` nur Seed), Automatik (`auto_queue` in `config.json`), Telegram, Energie. Live-API und Wand nutzen die DB-Namen. Gesperrte Drucker und `auto_queue: false` verhindern neue „wenn frei“-Starts; laufende Abläufe laufen weiter.
|
||||
|
||||
## Live-Quelle
|
||||
|
||||
`StateWatcher` pollt die Drucker (ca. 10 s). `GET /drucker?live=1` und der Print-Queue-Dispatcher lesen diesen Stand. Nur wenn der Cache älter als ~60 s / 30 s ist, wird einmal direkt abgefragt. Lange Ablauf-Schritte (Upload, Schieben, Tasten) laufen in Worker-Threads.
|
||||
|
||||
## Druckwarteschlange „wenn frei“
|
||||
|
||||
Dateien → „Wenn frei“ oder „Nächster freier“ → `when_free` in `POST /api/v1/senden`. Einträge in `print_queue`; Dispatcher startet, sobald der Host (oder ein freier Drucker) `standby`/`complete`/`cancelled` ist, Platte frei und nicht gesperrt. **Alle freien Drucker im selben Tick** (Upload/Start je Host im Worker parallel) — nicht einer alle ~8 s. Sidebar und Seite `/warteschlange`. Sofort-Senden bleibt über die Send-Queue (mehrere Worker). Hängender Fehler wird nur geräumt, wenn für den Host ein Auftrag wartet. Ablauf: Phase `starting` vor Upload; Timeout 10 min ohne `print_active`.
|
||||
|
||||
## Spulen
|
||||
|
||||
Ort = Regal oder Drucker (+ `ace_slot`). Unique-Index `(printer_host, ace_slot)`. Beim Start löst Grotti die Spule(n) aus Host + `ace_map` auf; Materialtyp der Datei muss passen. `sends` speichert `ace_map` und `bed_leveling`. Nach „fertig“ synct der Watcher das Protokoll und zieht Spulen ab (ACE anteilig).
|
||||
|
||||
## Telegram / Ereignisse
|
||||
|
||||
Jedes Ereignis landet in `events` und auf der Seite `/aktivitaet`. Telegram ist pro Art abschaltbar und wird je Host und Art entprellt (Watcher 60 s, Queue 30 s). Das Speichern wird nie entprellt. Gemeinsamer Weg: `notify.record()`.
|
||||
|
||||
| Art | Woher | Alert | Telegram-Standard |
|
||||
| --- | --- | --- | --- |
|
||||
| `fertig` | Watcher, `printing`→`complete` | nein, Platte unter „Aufgaben“ | an |
|
||||
| `fehler` | Watcher, Zustand `error` | ja | an |
|
||||
| `abbruch` | Watcher, `printing`/`paused`→`cancelled`/`standby` | ja | wie `fehler` |
|
||||
| `offline` | Watcher, ≥2 Polls weg; auch „wieder erreichbar“ | ja | an |
|
||||
| `spule` | Watcher, Rest unter Job-Gewicht | ja | an |
|
||||
| `queue` | Dispatcher: Queue-Fehler, Ablauf gestoppt | ja | an |
|
||||
| `start` | Watcher: Druck startet, Pause, Fortsetzen | nein | aus |
|
||||
| `ablauf` | Dispatcher: Start, Schritte, Wiederholung, fertig; App: eingereiht, von Hand abgebrochen | nein | aus |
|
||||
|
||||
„Alert“ heißt: ungelesen, steht in der Sidebar. `start`, `ablauf` und `fertig` werden gleich als gelesen gespeichert (`store.QUIET_EVENT_KINDS`), damit unter Alerts nur Probleme stehen.
|
||||
|
||||
„Aufgaben“ (Sidebar, `GET /api/v1/aufgaben`): Drucker mit `bed_status.needs_clear`, ohne laufenden Queue-Eintrag und nicht am Drucken. Knopf „geräumt“ ruft `POST /api/v1/drucker/<host>/abraeumen` mit `confirm: true` (Zwei-Klick), fährt nichts.
|
||||
|
||||
API: `GET /api/v1/ereignisse?limit=&host=&kind=a,b&since=<ISO>&unread=1`, `POST /api/v1/ereignisse/gelesen`.
|
||||
|
||||
Bei `print_stats.state=error` ist `message` auf Anycubic oft leer. Grotti ergänzt dann nur aus dem G-code-Log (echte `Must home`-/Fehlerzeilen) oder „Druck sofort abgebrochen“. Leeres `homed_axes` allein gilt nicht als Fehler — Idle schaltet die Stepper ab, das ist normal.
|
||||
|
||||
Nach Fehler: Watcher schaltet Bett/Düse/Lüfter aus (nicht weiter heizen). Vor Start und zwischen Ablauf-Schritten: hängender `print_stats=error` wird per `SDCARD_RESET_FILE` geräumt und der Druck gestartet. Kein Homing-Zwang vorher — der Slice-Start macht `G28`. Nur mitten im Druck (`print_active`) bricht ein error den Ablauf ab.
|
||||
|
||||
## Steuerung
|
||||
|
||||
Wand-Details: Düse/Bett, Speed/Flow/Fan, E-Stop und Exclude-Object über `POST /api/v1/drucker/<host>/steuern` (Whitelist, keine freie Konsole; `exclude_object` braucht `confirm` + `name`). Abbruch weiterhin Moonraker-cancel + MQTT-stop.
|
||||
|
||||
**Kein Firmware-Restart:** Auf GoKlipper/Rinkhals deadlocked `FIRMWARE_RESTART` gklib bis Power-Cycle ([Rinkhals #32](https://github.com/jbatonnet/Rinkhals/issues/32)). Grotti lehnt den Befehl ab. `printer.cfg` nur über Display-Reboot oder Strom. Hängenden `print_stats=error`: Wand **Fehler löschen** (`SDCARD_RESET_FILE` + Heizung aus).
|
||||
@@ -0,0 +1,5 @@
|
||||
# Interne Technik-Notizen
|
||||
|
||||
Diese Dateien sind für Entwicklung und Agenten — **nicht** unter `/doku` in der App.
|
||||
|
||||
Nutzer-Handbuch: `docs/Anleitung-*.md`.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Grotti: Senden und Start dauert
|
||||
|
||||
Stand **15.10.2026** (Stack-Quellen und Task-Hygiene in [Anycubic-Stack](Anycubic-Stack)). Spulen kommen vom Ziel-Drucker zur Startzeit (`ace_map` + eingelegte Rolle), nicht aus einem freien Dropdown. `sends` speichert `ace_map` und Bettnetz für „Nochmal“.
|
||||
|
||||
## Warum Sekunden / Minuten
|
||||
|
||||
Über Grotti-App (`Dateien` → Starten) läuft der Aufruf nicht nur lokal: die Datei wird als **ein synchroner Multipart-POST** an Moonraker hochgeladen (`/server/files/upload`), danach startet `/printer/print/start`. Der HTTP-Request endet erst, wenn Moonraker die Datei geschrieben und oft Metadaten/MMU-Preprocess angeschoben hat — bis dahin wirkt die Queue „still“.
|
||||
|
||||
Messung 12.10.2026, `tulip pla.gcode` (~**50,4 MB** in `data/eingang`, typisch daneben ~2 MB): Upload auf `da26` (`10.10.1.60`) **~67 s** laut Moonraker-Log (`201 POST … 67106 ms`), plus kurze `.acm`-Sidecar (~87 ms) und Start. Gesamter Queue-Job ~**96 s**. Kleine Dateien bleiben im Sekundenbereich.
|
||||
|
||||
13.10.2026: Die lange Pause bei „50/50 MB“ ist Rinkhals `mmu_ace_metadata.py`. Der liest die ganze Datei auf der Kobra, bevor der Upload-HTTP antwortet, und schreibt sie bei gefundenen Werkzeugen noch einmal um. Grotti setzt vorher die Kopfzeile `; processed by MmuAcePatcher`. Bei Prusa, Super, Orca, Bambu oder AnycubicSlicerNext und Werkzeugen (`T0`, `MMU_CHANGE_TOOL`) hängt sie `; referenced_tools = …` an — dieselbe Zeile, die der Drucker sonst selbst schreibt. Danach überspringt er diesen Durchlauf. Stehen die Bytes, wechselt die Anzeige auf „liest die Datei…“. Grotti neu starten (`use_reloader=False`).
|
||||
|
||||
Vorher prüft Grotti Online-Status und ob schon gedruckt wird — laufende Drucke werden nicht abgebrochen. Die Rinkhals-Touch-UI können wir nicht umbauen; Fortschritt betrifft Grotti unter `:8770`.
|
||||
|
||||
## Queue (Grotti)
|
||||
|
||||
Ab 12.10.2026: Start legt Hintergrund-Aufträge an (`pending` → `running` → `done`/`error`). Pro gewähltem Drucker ein Queue-Job; mehrere Worker. UI pollt ~500 ms. Beim Hochladen zeigt die Queue jetzt **MB-Fortschritt** (urllib liest den Body gestreamt); Timeout skaliert mit Dateigröße (ca. 180–600 s). Bestätigung „Druck wirklich starten“ bleibt Pflicht. Nach Python-Änderung Grotti neu starten (`use_reloader=False`).
|
||||
|
||||
## Slice-Ordner / Upload
|
||||
|
||||
`watch_dir` in `config.json` zeigt auf den Slice-Ordner der Bibliothek. Ohne Ordner geht Hochladen über die Dateien-Seite trotzdem.
|
||||
|
||||
## ACE / `.acm`
|
||||
|
||||
Drucker mit ACE/MMU-Plätzen (`mmu.gate_color` / `gate_material`, Grotti-`slots`) brauchen vor `print/start` eine Sidecar-Datei `*.gcode.acm`. In der UI unter Optionen → ACE-Zuordnung (Datei-Farbe → Platz). Ohne passende `.acm` lehnt der Drucker oft mit „cannot parse the file“ ab — Details hier, nicht als Banner in der App:
|
||||
|
||||
```json
|
||||
{"use_ams":true,"ams_box_mapping":[{"paint_index":0,"paint_color":[r,g,b],"material_type":"PLA","ams_index":1,"ams_color":[r,g,b]}]}
|
||||
```
|
||||
|
||||
`paint_index` = Farbe in der Slice-Datei (0-basiert), `ams_index` = ACE-Platz 0-basiert. Externe Spule / keine Slots: kein `.acm`. Keine Community-Makros (`ACE_SET_SLOT` / `G9111`).
|
||||
|
||||
AnycubicSlicerNext schreibt die Farben oft als `; paint_info: [{...}]` statt `filament_type` — Grotti liest das seit 12.10.2026 mit.
|
||||
|
||||
## Bettnetz / auto_leveling beim Start (12.10.2026)
|
||||
|
||||
Rinkhals `kobra.py` `mqtt_print_file` baut den Anycubic-MQTT-Start so (Topic `…/slicer/printer/{modelId}/{deviceId}/print`, lokal `127.0.0.1:2883`):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "print",
|
||||
"action": "start",
|
||||
"msgid": "<uuid>",
|
||||
"timestamp": 1660201929871,
|
||||
"data": {
|
||||
"filename": "job.gcode",
|
||||
"filepath": "/",
|
||||
"taskid": "123456",
|
||||
"task_mode": 1,
|
||||
"filetype": 1,
|
||||
"task_settings": {
|
||||
"auto_leveling": 1,
|
||||
"vibration_compensation": 0,
|
||||
"flow_calibration": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`auto_leveling` ist **0/1** (Integer). `1` löst die Anycubic-Nivellierfolge beim Jobstart aus (LeviQ / Netz messen) — nicht über G-code `LEVIQ_*` / `BED_MESH_CALIBRATE` / `SAVE_CONFIG` von Grotti. Ohne Grotti-Flag kommt der Wert aus der **globalen** App-Property `40-moonraker` → `mqtt_print_auto_leveling` (Default `False`). Extra-Felder an Moonraker `POST /printer/print/start` werden ignoriert. App-Property setzen geht nur per SSH (`set_app_property 40-moonraker mqtt_print_auto_leveling True`), keine HTTP-API.
|
||||
|
||||
### Grotti-Verhalten
|
||||
|
||||
| Checkbox / ACE | Startweg |
|
||||
| --- | --- |
|
||||
| kein Bettnetz, keine ACE-Map | Upload + Moonraker `print/start` → Rinkhals MQTT (globale `auto_leveling`, oft 0) |
|
||||
| ACE-Map gesetzt | Upload + `.acm` (Basename + Stamm-Variante) + **Grotti-MQTT** mit `ams_settings` aus der Map; `auto_leveling` nur 1 wenn Bettnetz an |
|
||||
| Bettnetz an | wie ACE-Map-Pfad, `auto_leveling:1` |
|
||||
|
||||
Credentials holt Grotti ohne SSH: `GET :18910/info` → signiertes `POST :18910/ctrl` → AES-Decrypt (Username/Password/`deviceId`). Port **2883** ist vom PC zu; **9883** (TLS, Cert-Check aus) ist offen. Mit Grotti-MQTT liegt `ams_box_mapping` explizit in der Payload (kein Moonraker-Identity-Fallback). Ohne `; referenced_tools`-Trailer: Warnung in UI/Queue, kein Fake-Trailer.
|
||||
|
||||
**Abbruch:** Grotti `abbrechen` = Moonraker `/printer/print/cancel` **plus** MQTT `action: stop` / `taskid: "-1"` (gleicher Topic wie Start). Nur Moonraker-cancel lässt den Anycubic-Task stehen → nächster MQTT-Start mit **10101**. 13.10.2026: Gridfinity auf da26 so hängen geblieben, per MQTT-stop freigemacht (`data.state: free`).
|
||||
|
||||
### Task-Hygiene vor dem Start (15.10.2026)
|
||||
|
||||
Vor jedem Start (MQTT und reiner Moonraker-Pfad) räumt Grotti einen hängenden gkapi-Task best-effort — **Kobra 3 und S1**: `print_info` → ggf. MQTT-stop → poll. Kommt trotzdem **10101**, einmal cancel + 1,5 s + Retry (wie Rinkhals). Ist gkapi kurz unerreichbar, läuft der Moonraker-Start trotzdem (negativer Cache ~45 s). Live zeigt die Wand `anycubic_task` aus demselben `info/query` (Cache ~10 s). Details: [Anycubic-Stack](Anycubic-Stack) Abschnitt Task-Hygiene.
|
||||
|
||||
**Start-Report verspätet:** 13.10.2026 ~21:35, A2 (`10.10.1.59`), Ablauf 2/5 direkt nach der Bettnetz-Prüfung. Innerhalb von 30 s kam kein `print/report`, der Druck lief trotzdem an. `info/query` (Topic `…/slicer/printer/{modelId}/{deviceId}/info`, Antwort auf `…/info/report`) zeigte `project.task_id` = Grotti-`taskid`, `state: auto_leveling`. Moonraker meldet in dieser Phase noch `print_stats.state: complete` vom Vorauftrag. Grotti prüft deshalb bei einem Start-Timeout bis zu dreimal `info/query`. Steht dort die eigene `taskid`, gilt der Start als erfolgreich (`anycubic_lan.print_info`).
|
||||
|
||||
Fallback ohne MQTT: global in Rinkhals Touch → Manage apps → 40-moonraker → Auto leveling (gilt dann für alle Moonraker-Starts inkl. Mainsail/Orca).
|
||||
@@ -0,0 +1,39 @@
|
||||
# Voraussetzungen
|
||||
|
||||
Stand **14.10.2026**.
|
||||
|
||||
Grotti steuert Drucker, die im eigenen Netz schon Moonraker sprechen. Bewährt ist das auf der Kobra 3 und der Kobra S1, nachdem Rinkhals läuft. Moonraker liegt auf Port 80. Den Aufsatz installiert der Nutzer selbst. Grotti liefert keine Firmware und keine Schraubanleitung.
|
||||
|
||||
Verlinkt wird nur die Installationsseite von Rinkhals: <https://github.com/rinkhals-community/Rinkhals>. Die Warnung, die der Hersteller selbst einblendet, bleibt seine.
|
||||
|
||||
Andere Drucker nur, wenn Moonraker dort schon erreichbar ist. Dafür gibt es keine eigene Anleitung. Bambu Lab, Prusa und Creality Cloud bleiben bei deren eigenen Programmen.
|
||||
|
||||
Der Ablauf Abkühlen, Schieben, Tasten ist für die Kobra 3. Die Kobra S1 ist geschlossen, Abräumen dort ist offen.
|
||||
|
||||
Einrichtung der Software (Python, PostgreSQL, Start) steht im [README](../README.md).
|
||||
|
||||
## Vor dem ersten Start
|
||||
|
||||
Unbeaufsichtigtes Drucken, Hitze und Brandgefahr stehen vor dem ersten Start, nicht im Kleingedruckten. Düse und Bett werden heiß. Den ersten Lauf behält der Nutzer im Blick.
|
||||
|
||||
## Grundsatz
|
||||
|
||||
**Entwurf.** Kein anwaltlich geprüfter Text. Vor einem Verkauf mit Preis, Abo oder Shop kommen Impressum, Datenschutz und AGB dazu. Diese Seiten nennen keinen Preis.
|
||||
|
||||
Grotti flasht nicht, schickt keine Firmware und beschreibt keine Signatur-Umgehung, keinen Root-Exploit und keine Umgehung einer Downgrade-Sperre.
|
||||
|
||||
Der Nutzer richtet seinen eigenen Drucker ein, bevor er Grotti nutzt. Verlinkt wird nur die Installationsseite von Rinkhals: <https://github.com/rinkhals-community/Rinkhals>. Die Warnung, die der Hersteller selbst einblendet, bleibt seine.
|
||||
|
||||
Anycubic schließt ungenehmigte Änderungen von der Garantie aus. Rinkhals ist ein Community-Aufsatz; die ursprüngliche Software bleibt darunter, der Aufsatz lässt sich wieder entfernen. Ob Anycubic einen Fall annimmt, entscheidet Anycubic.
|
||||
|
||||
Creality lässt beim offiziellen Root den Hardware-Service stehen und gibt dafür keine Software-Unterstützung. Fremde Firmware ist von der Garantie ausgenommen (<https://wiki.creality.com/en/warranty-policy>).
|
||||
|
||||
Bambu Lab deckt Schäden durch inoffizielle Firmware nicht ab. Der Entwicklermodus ist eine eigene Funktion von Bambu Lab, mit der Warnung, die Bambu Lab selbst einblendet.
|
||||
|
||||
Die gesetzliche Mängelhaftung für den Drucker bleibt beim Verkäufer des Druckers. Ein Disclaimer Grotti wischt Verletzung, Vorsatz und grobe Fahrlässigkeit nicht weg.
|
||||
|
||||
Unbeaufsichtigtes Drucken, Hitze und Brandgefahr stehen vor dem ersten Start, nicht im Kleingedruckten.
|
||||
|
||||
Es gibt kein Auftrags-Flashen und keine vorgeflashten Drucker.
|
||||
|
||||
Ausführlich derselbe Hinweis: [Haftung](Haftung.md).
|
||||
@@ -0,0 +1,9 @@
|
||||
# Grotti-Wand: Bettnetz
|
||||
|
||||
Stand **13.10.2026**.
|
||||
|
||||
Die Heatmap im Drucker-Cockpit (unter dem Kamerabild, neben dem 3D-Pfad) zeigt das **aktuelle** Moonraker-Objekt `bed_mesh` je Drucker (`probed_matrix`, sonst `mesh_matrix`), nicht ein Netz zum laufenden G-code.
|
||||
|
||||
Drei Drucker mit derselben Datei (z. B. Gridfinity) haben deshalb **drei verschiedene** Netze — eines pro Bett. Die Zeile am 3D-Viewer ist der Auftragspfad (`3D-Pfad · …`), nicht die Netz-Identität.
|
||||
|
||||
Grotti merkt sich das zuletzt gelesene Netz im Speicher. Offline oder leeres `bed_mesh` → Anzeige mit Hinweis „offline gespeichert“ und Uhrzeit der letzten erfolgreichen Abfrage. Neu nivellieren am Drucker aktualisiert das Cockpit beim nächsten Poll (~5 s).
|
||||
Reference in new issue
Block a user