8.0 KiB
Anycubic-Stack: wie Druck, Abbruch und ACE wirklich laufen
Stand 15.10.2026. Quellen: Anycubic Klipper-go, 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
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) | Klipper-Host: Motion, Heater, virtual_sdcard, ACE-G-codes |
| MCU | teilweise (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
- Klipper-Pfad (Moonraker
POST /printer/print/start→ gklibvirtual_sdcard): setztprint_stats, lädt G-code in gklib. - Anycubic-Task (MQTT
type: print,action: startan 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).
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
taskidauf eine Zufallszahl; die Doc-Minimalbeispiel nutzt"-1"— beides kommt vor
MQTT Stop (belegt) — warum 10101
{ "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 keineams_settingsin der Payload, baut Identity-/TTG-Map aus den Gates und hängtams_settingsan - Liest/schreibt Sidecar
basename.acmneben dem G-code; ohne ACE kann sie nach.acm.disabledumbenannt 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).
.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).
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.