Files
grotti/docs/internal/Anycubic-Stack.md
T

8.0 KiB
Raw Permalink Blame History

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

  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).

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

{ "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).

.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.