forked from viewit/KX-Bridge-Release
release: v0.9.1-beta5
This commit is contained in:
247
README.en.md
247
README.en.md
@@ -1,25 +1,9 @@
|
|||||||
# KX-Bridge
|
# KX-Bridge – Anycubic Kobra X Moonraker Bridge
|
||||||
|
|
||||||
Connects the Anycubic Kobra X to OrcaSlicer – no Klipper, no Raspberry Pi required.
|
|
||||||
|
|
||||||
KX-Bridge runs on your PC or NAS and provides a Moonraker-compatible interface so OrcaSlicer can control the printer directly: print start, temperatures, progress, pause/resume/cancel, AMS filament changes, print speed, and more.
|
|
||||||
|
|
||||||
**Version:** 0.9.1-beta4
|
**Version:** 0.9.1-beta4
|
||||||
|
**Status:** Public Beta – suitable for home users, feedback welcome
|
||||||
|
|
||||||
---
|
KX-Bridge is a Moonraker-compatible HTTP/WebSocket bridge for the **Anycubic Kobra X** 3D printer. It allows you to control the printer through OrcaSlicer and other Moonraker-compatible software — no Klipper, no Raspberry Pi required.
|
||||||
|
|
||||||
## Included files
|
|
||||||
|
|
||||||
| File | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `kobrax_moonraker_bridge.py` | Bridge main program |
|
|
||||||
| `kx-bridge` | Pre-built Linux binary |
|
|
||||||
| `extract_credentials.exe` | Read credentials from AnycubicSlicerNext (Windows) |
|
|
||||||
| `extract_credentials` | Read credentials from AnycubicSlicerNext (Linux) |
|
|
||||||
| `kobra_x_orcaslicer_preset.zip` | OrcaSlicer printer profile for the Kobra X |
|
|
||||||
| `bridge.sh` | Linux service manager |
|
|
||||||
| `Dockerfile` / `docker-compose.yml` | Docker deployment |
|
|
||||||
| `.env.example` | Configuration template |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -40,93 +24,129 @@ KX-Bridge runs on your PC or NAS and provides a Moonraker-compatible interface s
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Anycubic Kobra X in LAN mode (printer must be reachable via LAN, not only through Anycubic Cloud)
|
- Anycubic Kobra X on your local network (LAN, no Wi-Fi client isolation)
|
||||||
- PC, NAS, or server on the same network (Windows or Linux)
|
- Printer MQTT credentials (→ see [Extracting credentials](#extracting-credentials))
|
||||||
- Docker or Python 3.9+
|
- Docker **or** Python 3.9+ **or** the pre-built Linux binary
|
||||||
- Printer MQTT credentials → [Step 1](#step-1-extract-credentials)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick start
|
## Quick start – Docker (recommended)
|
||||||
|
|
||||||
### Step 1: Extract credentials
|
|
||||||
|
|
||||||
The bridge needs printer-specific MQTT credentials.
|
|
||||||
|
|
||||||
> **Important:** The printer must be in LAN mode. The credentials can only be extracted when the printer is reachable directly over LAN (not solely through Anycubic Cloud).
|
|
||||||
|
|
||||||
Start AnycubicSlicerNext and connect to the printer (wait until the printer status is shown), then:
|
|
||||||
|
|
||||||
**Windows:**
|
|
||||||
```
|
|
||||||
extract_credentials.exe --write-env
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux:**
|
|
||||||
```bash
|
|
||||||
chmod +x extract_credentials
|
|
||||||
./extract_credentials --write-env
|
|
||||||
```
|
|
||||||
|
|
||||||
The credentials are saved automatically to `.env`.
|
|
||||||
|
|
||||||
> If the result looks uncertain: `--verbose` shows all found candidates. Enter the correct value manually in `.env`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Step 2: Check configuration
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 1. Create .env
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Open .env and verify the values
|
# Fill in your printer data (→ extract_credentials)
|
||||||
|
|
||||||
|
# 2. Start the bridge
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 3. In OrcaSlicer: add printer → "Moonraker" → http://BRIDGE-IP:7125
|
||||||
|
```
|
||||||
|
|
||||||
|
Check logs:
|
||||||
|
```bash
|
||||||
|
docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Update:
|
||||||
|
```bash
|
||||||
|
docker compose pull && docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Step 3: Start the bridge
|
## Quick start – Binary (Linux)
|
||||||
|
|
||||||
**Option A – Docker (recommended):**
|
|
||||||
```bash
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
Runs in the background and restarts automatically after a system reboot.
|
|
||||||
|
|
||||||
**Option B – Linux binary:**
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x kx-bridge
|
chmod +x kx-bridge
|
||||||
./kx-bridge
|
./kx-bridge --printer-ip 192.168.x.x --username userXXXX --password XXXXX \
|
||||||
# Or with the service manager:
|
--device-id XXXXX --mode-id 20030
|
||||||
./bridge.sh start
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option C – Python directly:**
|
Or place a `.env` file in the same directory — the bridge reads it automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start – Python directly
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install aiohttp
|
pip install aiohttp
|
||||||
|
python kobrax_moonraker_bridge.py --printer-ip 192.168.x.x ...
|
||||||
|
# Or fill in .env and start without arguments
|
||||||
python kobrax_moonraker_bridge.py
|
python kobrax_moonraker_bridge.py
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Step 4: Install OrcaSlicer profile
|
## Extracting credentials
|
||||||
|
|
||||||
1. Import `kobra_x_orcaslicer_preset.zip` into OrcaSlicer:
|
The MQTT credentials are printer-specific and are generated on first connection with AnycubicSlicerNext. The `extract_credentials` tool reads them from the memory of the running slicer.
|
||||||
File → Import → Import Configs → select ZIP
|
|
||||||
2. Select Anycubic Kobra X as your printer
|
**Requirement:** AnycubicSlicerNext must be running and connected to the printer.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```
|
||||||
|
extract_credentials.exe --write-env
|
||||||
|
```
|
||||||
|
|
||||||
|
Writes the found credentials directly to `.env`.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x extract_credentials
|
||||||
|
./extract_credentials --write-env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
```
|
||||||
|
[*] Process found: AnycubicSlicerNext.exe (PID 1234)
|
||||||
|
[*] 1986 memory segments read (738.8 MB)
|
||||||
|
[*] Analyzing ... 100% (739 MB)
|
||||||
|
|
||||||
|
=======================================================
|
||||||
|
RESULTS
|
||||||
|
=======================================================
|
||||||
|
Username userXXXXXXXXXX (hits: 47)
|
||||||
|
Password *************** (hits: 1046)
|
||||||
|
Device-ID xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (hits: 3504)
|
||||||
|
Printer IP 192.168.x.x (hits: 3036)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
Hint: pass --write-env to save credentials to '.env'.
|
||||||
|
```
|
||||||
|
|
||||||
|
All credentials are **processed locally only** — nothing is sent to external servers.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Step 5: Connect OrcaSlicer
|
## Configuration (.env)
|
||||||
|
|
||||||
1. Open printer settings
|
```env
|
||||||
|
PRINTER_IP=192.168.x.x # Printer IP address
|
||||||
|
MQTT_PORT=9883 # Default, do not change
|
||||||
|
MQTT_USERNAME=userXXXXXXXX # Starts with "user"
|
||||||
|
MQTT_PASSWORD=XXXXXXXXXXXXXX # ~15 characters, mixed case
|
||||||
|
DEVICE_ID=xxxxxxxx... # 32-character hex string
|
||||||
|
MODE_ID=20030 # Kobra X default
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OrcaSlicer setup
|
||||||
|
|
||||||
|
1. Add printer → **Anycubic Kobra X** (or generic Klipper printer)
|
||||||
2. Connection type: **Moonraker**
|
2. Connection type: **Moonraker**
|
||||||
3. Host: `http://BRIDGE-PC-IP:7125`
|
3. Host: `http://BRIDGE-HOST:7125`
|
||||||
4. Click "Test" — a success message confirms the connection
|
4. Test connection → should show "Online"
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Web UI
|
## Web UI
|
||||||
|
|
||||||
The bridge serves a web interface at `http://BRIDGE-IP:7125`:
|
The bridge serves a web interface at `http://BRIDGE-HOST:7125`:
|
||||||
|
|
||||||
| Section | Function |
|
| Section | Function |
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
@@ -136,7 +156,7 @@ The bridge serves a web interface at `http://BRIDGE-IP:7125`:
|
|||||||
| Print Speed | Silent / Normal / Sport |
|
| Print Speed | Silent / Normal / Sport |
|
||||||
| Fan / Light | Fan speed and work light |
|
| Fan / Light | Fan speed and work light |
|
||||||
| AMS | Load / unload filament |
|
| AMS | Load / unload filament |
|
||||||
| Camera | Live preview (if supported by the printer) |
|
| Camera | Live preview (if supported by printer) |
|
||||||
| ⚙ Settings | MQTT credentials, poll interval, self-update |
|
| ⚙ Settings | MQTT credentials, poll interval, self-update |
|
||||||
|
|
||||||
### Self-update
|
### Self-update
|
||||||
@@ -145,26 +165,32 @@ The ⚙ menu in the web UI lets you check for new versions and update the bridge
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## bridge.sh – Service manager (Linux)
|
## bridge.sh (Linux service manager)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bridge.sh start # Start in background
|
./bridge.sh start # Start bridge in background
|
||||||
./bridge.sh stop # Stop
|
./bridge.sh stop # Stop bridge
|
||||||
./bridge.sh restart # Restart
|
./bridge.sh restart # Restart
|
||||||
./bridge.sh status # Show status
|
./bridge.sh status # Check status and port
|
||||||
./bridge.sh log 50 # Show last 50 log lines
|
./bridge.sh log 50 # Show last 50 log lines
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Docker – Useful commands
|
## Printer states
|
||||||
|
|
||||||
```bash
|
The bridge translates internal Kobra states into Moonraker-compatible states:
|
||||||
docker compose up -d # Start
|
|
||||||
docker compose down # Stop
|
| Kobra state | Meaning |
|
||||||
docker compose logs -f # Follow logs
|
|-------------|---------|
|
||||||
docker compose pull && docker compose up -d # Update
|
| free | Ready |
|
||||||
```
|
| printing / busy | Printing |
|
||||||
|
| pausing / paused | Paused |
|
||||||
|
| resuming / resumed | Resuming |
|
||||||
|
| stopping / stoped | Stopping |
|
||||||
|
| finished | Complete |
|
||||||
|
| canceled | Cancelled |
|
||||||
|
| failed | Error |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -172,19 +198,14 @@ docker compose pull && docker compose up -d # Update
|
|||||||
|
|
||||||
**Port 7125 already in use:**
|
**Port 7125 already in use:**
|
||||||
```bash
|
```bash
|
||||||
./bridge.sh stop
|
./bridge.sh stop # or: fuser -k 7125/tcp
|
||||||
./bridge.sh start
|
./bridge.sh start
|
||||||
```
|
```
|
||||||
|
|
||||||
**OrcaSlicer connection test fails:**
|
**Invalid credentials / connection refused:**
|
||||||
- Check firewall: port 7125 must be reachable
|
- Start AnycubicSlicerNext, connect to the printer, then run `extract_credentials` again
|
||||||
- Check bridge log: `./bridge.sh log` or `docker compose logs`
|
- If the result looks uncertain: `extract_credentials --verbose` shows all candidates
|
||||||
- Is the printer IP in `.env` correct?
|
- Manually enter the correct candidate in `.env` and restart the bridge
|
||||||
|
|
||||||
**Credentials rejected:**
|
|
||||||
- Start AnycubicSlicerNext and connect to the printer
|
|
||||||
- Run `extract_credentials --verbose` and check all candidates
|
|
||||||
- Enter the correct value manually in `.env`, then restart the bridge
|
|
||||||
|
|
||||||
**Temperature changes are ignored:**
|
**Temperature changes are ignored:**
|
||||||
- During an active print, temperature changes are sent via a separate channel — this is normal and the bridge handles it automatically.
|
- During an active print, temperature changes are sent via a separate channel — this is normal and the bridge handles it automatically.
|
||||||
@@ -192,21 +213,26 @@ docker compose pull && docker compose up -d # Update
|
|||||||
**Docker: Permission denied:**
|
**Docker: Permission denied:**
|
||||||
```bash
|
```bash
|
||||||
sudo usermod -aG docker $USER
|
sudo usermod -aG docker $USER
|
||||||
# Log out and back in, then try again
|
# Log out and back in
|
||||||
|
```
|
||||||
|
|
||||||
|
**Docker: .env not found:**
|
||||||
|
```bash
|
||||||
|
# .env must be in the same directory as docker-compose.yml
|
||||||
|
cp .env.example .env && nano .env
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Configuration reference (.env)
|
## Logs
|
||||||
|
|
||||||
| Parameter | Description | Example |
|
```bash
|
||||||
|-----------|-------------|---------|
|
# Docker
|
||||||
| `PRINTER_IP` | Printer IP address | `192.168.1.100` |
|
docker compose logs -f kx-bridge
|
||||||
| `MQTT_PORT` | MQTT port (do not change) | `9883` |
|
|
||||||
| `MQTT_USERNAME` | Username (starts with "user") | `userXXXXXXXXXX` |
|
# Binary / Python
|
||||||
| `MQTT_PASSWORD` | Password (~15 characters) | `***` |
|
tail -f /tmp/bridge.log # when using bridge.sh
|
||||||
| `DEVICE_ID` | Device ID (32 hex characters) | `xxxxxxxx...` |
|
```
|
||||||
| `MODE_ID` | Model ID (Kobra X default) | `20030` |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -214,14 +240,11 @@ sudo usermod -aG docker $USER
|
|||||||
|
|
||||||
- The bridge binds to `0.0.0.0:7125` by default — use on your local network only
|
- The bridge binds to `0.0.0.0:7125` by default — use on your local network only
|
||||||
- `.env` contains printer credentials — do not share publicly
|
- `.env` contains printer credentials — do not share publicly
|
||||||
- All credentials are processed locally only — nothing is sent to external servers
|
- The credentials are printer-specific and have no access to Anycubic cloud services
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Disclaimer
|
## License & legal
|
||||||
|
|
||||||
This project is intended for private use and to enable interoperability between the Anycubic Kobra X and free software (OrcaSlicer).
|
This project was created through interoperability research under §69e UrhG (German copyright law).
|
||||||
|
For private, non-commercial use only.
|
||||||
`extract_credentials` only reads the memory of the AnycubicSlicerNext process running on your own PC. No data is transmitted or stored anywhere other than the local `.env` file.
|
|
||||||
|
|
||||||
This project is not affiliated with Anycubic and is not operated commercially.
|
|
||||||
|
|||||||
251
README.md
251
README.md
@@ -1,25 +1,9 @@
|
|||||||
# KX-Bridge
|
# KX-Bridge – Anycubic Kobra X Moonraker Bridge
|
||||||
|
|
||||||
Verbindet den Anycubic Kobra X mit OrcaSlicer – ohne Klipper, ohne Raspberry Pi.
|
|
||||||
|
|
||||||
KX-Bridge läuft auf deinem PC oder NAS und stellt eine Moonraker-kompatible Schnittstelle bereit, über die OrcaSlicer den Drucker direkt steuern kann: Druckstart, Temperatur, Fortschritt, Pause/Fortsetzen/Abbrechen, AMS-Farbwechsel, Druckgeschwindigkeit und mehr.
|
|
||||||
|
|
||||||
**Version:** 0.9.1-beta4
|
**Version:** 0.9.1-beta4
|
||||||
|
**Status:** Public Beta – für Heimanwender geeignet, Feedback willkommen
|
||||||
|
|
||||||
---
|
KX-Bridge ist eine Moonraker-kompatible HTTP/WebSocket-Bridge für den **Anycubic Kobra X** 3D-Drucker. Sie ermöglicht die Steuerung des Druckers über OrcaSlicer und andere Moonraker-kompatible Software, ohne dass Klipper oder ein Raspberry Pi benötigt wird.
|
||||||
|
|
||||||
## Enthaltene Dateien
|
|
||||||
|
|
||||||
| Datei | Beschreibung |
|
|
||||||
|-------|-------------|
|
|
||||||
| `kobrax_moonraker_bridge.py` | Bridge-Hauptprogramm |
|
|
||||||
| `kx-bridge` | Vorkompilierte Linux-Binary |
|
|
||||||
| `extract_credentials.exe` | Zugangsdaten aus AnycubicSlicerNext auslesen (Windows) |
|
|
||||||
| `extract_credentials` | Zugangsdaten aus AnycubicSlicerNext auslesen (Linux) |
|
|
||||||
| `kobra_x_orcaslicer_preset.zip` | OrcaSlicer-Druckerprofil für den Kobra X |
|
|
||||||
| `bridge.sh` | Service-Manager für Linux |
|
|
||||||
| `Dockerfile` / `docker-compose.yml` | Docker-Deployment |
|
|
||||||
| `.env.example` | Konfigurationsvorlage |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -40,93 +24,129 @@ KX-Bridge läuft auf deinem PC oder NAS und stellt eine Moonraker-kompatible Sch
|
|||||||
|
|
||||||
## Voraussetzungen
|
## Voraussetzungen
|
||||||
|
|
||||||
- Anycubic Kobra X im LAN-Modus (Drucker muss über LAN erreichbar sein, nicht nur über Anycubic-Cloud)
|
- Anycubic Kobra X im lokalen Netzwerk (LAN, nicht WLAN-Isolation)
|
||||||
- PC, NAS oder Server im gleichen Netzwerk (Windows oder Linux)
|
- MQTT-Credentials des Druckers (→ siehe [Credentials extrahieren](#credentials-extrahieren))
|
||||||
- Docker oder Python 3.9+
|
- Docker **oder** Python 3.9+ **oder** direkt die Linux-Binary
|
||||||
- MQTT-Zugangsdaten des Druckers → [Schritt 1](#schritt-1-zugangsdaten-ermitteln)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Schnellstart
|
## Schnellstart – Docker (empfohlen)
|
||||||
|
|
||||||
### Schritt 1: Zugangsdaten ermitteln
|
|
||||||
|
|
||||||
Die Bridge benötigt druckerspezifische MQTT-Zugangsdaten.
|
|
||||||
|
|
||||||
> **Wichtig:** Der Drucker muss sich im LAN-Modus befinden. Nur wenn der Drucker direkt über LAN (nicht ausschließlich über die Anycubic-Cloud) erreichbar ist, können die Zugangsdaten ermittelt und die Bridge genutzt werden.
|
|
||||||
|
|
||||||
AnycubicSlicerNext starten und mit dem Drucker verbinden (bis der Drucker-Status angezeigt wird), dann:
|
|
||||||
|
|
||||||
**Windows:**
|
|
||||||
```
|
|
||||||
extract_credentials.exe --write-env
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux:**
|
|
||||||
```bash
|
|
||||||
chmod +x extract_credentials
|
|
||||||
./extract_credentials --write-env
|
|
||||||
```
|
|
||||||
|
|
||||||
Die Zugangsdaten werden automatisch in `.env` gespeichert.
|
|
||||||
|
|
||||||
> Falls das Ergebnis unsicher wirkt: `--verbose` zeigt alle gefundenen Kandidaten. Den richtigen Wert manuell in `.env` eintragen.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Schritt 2: Konfiguration prüfen
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 1. .env anlegen
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# .env öffnen und Werte kontrollieren
|
# .env mit deinen Druckerdaten befüllen (→ extract_credentials)
|
||||||
|
|
||||||
|
# 2. Bridge starten
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 3. In OrcaSlicer: Drucker → "Moonraker" → http://BRIDGE-IP:7125
|
||||||
|
```
|
||||||
|
|
||||||
|
Logs prüfen:
|
||||||
|
```bash
|
||||||
|
docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Update:
|
||||||
|
```bash
|
||||||
|
docker compose pull && docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Schritt 3: Bridge starten
|
## Schnellstart – Binary (Linux)
|
||||||
|
|
||||||
**Option A – Docker (empfohlen):**
|
|
||||||
```bash
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
Läuft im Hintergrund, startet automatisch nach Systemneustart.
|
|
||||||
|
|
||||||
**Option B – Linux Binary:**
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x kx-bridge
|
chmod +x kx-bridge
|
||||||
./kx-bridge
|
./kx-bridge --printer-ip 192.168.x.x --username userXXXX --password XXXXX \
|
||||||
# Oder mit Service-Manager:
|
--device-id XXXXX --mode-id 20030
|
||||||
./bridge.sh start
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option C – Python direkt:**
|
Oder mit `.env`-Datei im gleichen Verzeichnis – die Bridge liest sie automatisch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schnellstart – Python direkt
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install aiohttp
|
pip install aiohttp
|
||||||
|
python kobrax_moonraker_bridge.py --printer-ip 192.168.x.x ...
|
||||||
|
# Oder .env befüllen, dann ohne Argumente starten
|
||||||
python kobrax_moonraker_bridge.py
|
python kobrax_moonraker_bridge.py
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Schritt 4: OrcaSlicer-Profil installieren
|
## Credentials extrahieren
|
||||||
|
|
||||||
1. `kobra_x_orcaslicer_preset.zip` in OrcaSlicer importieren:
|
Die MQTT-Zugangsdaten sind druckerspezifisch und werden beim ersten Verbindungsaufbau mit dem AnycubicSlicerNext generiert. Das Tool `extract_credentials` liest sie aus dem RAM des laufenden Slicers aus.
|
||||||
Datei → Konfigurationen importieren → ZIP auswählen
|
|
||||||
2. Anycubic Kobra X als Drucker auswählen
|
**Voraussetzung:** AnycubicSlicerNext muss gestartet und mit dem Drucker verbunden sein.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```
|
||||||
|
extract_credentials.exe --write-env
|
||||||
|
```
|
||||||
|
|
||||||
|
Schreibt die gefundenen Credentials direkt in `.env`.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x extract_credentials
|
||||||
|
./extract_credentials --write-env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ausgabe
|
||||||
|
|
||||||
|
```
|
||||||
|
[*] Prozess gefunden: AnycubicSlicerNext.exe (PID 1234)
|
||||||
|
[*] 1986 Speichersegmente gelesen (738.8 MB)
|
||||||
|
[*] Analysiere ... 100% (739 MB)
|
||||||
|
|
||||||
|
=======================================================
|
||||||
|
ERGEBNISSE
|
||||||
|
=======================================================
|
||||||
|
Username userXXXXXXXXXX (Treffer: 47)
|
||||||
|
Password *************** (Treffer: 1046)
|
||||||
|
Device-ID xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (Treffer: 3504)
|
||||||
|
Drucker-IP 192.168.x.x (Treffer: 3036)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
Hinweis: --write-env übergeben um Credentials in '.env' zu speichern.
|
||||||
|
```
|
||||||
|
|
||||||
|
Alle Credentials werden **ausschließlich lokal verarbeitet** — keine Übertragung an externe Server.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Schritt 5: OrcaSlicer verbinden
|
## Konfiguration (.env)
|
||||||
|
|
||||||
1. Drucker-Einstellungen öffnen
|
```env
|
||||||
|
PRINTER_IP=192.168.x.x # IP des Druckers
|
||||||
|
MQTT_PORT=9883 # Standard, nicht ändern
|
||||||
|
MQTT_USERNAME=userXXXXXXXX # Beginnt mit "user"
|
||||||
|
MQTT_PASSWORD=XXXXXXXXXXXXXX # ~15 Zeichen, gemischt
|
||||||
|
DEVICE_ID=xxxxxxxx... # 32-stelliger Hex-String
|
||||||
|
MODE_ID=20030 # Kobra X Standard
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OrcaSlicer verbinden
|
||||||
|
|
||||||
|
1. Drucker hinzufügen → **Anycubic Kobra X** (oder generischer Klipper-Drucker)
|
||||||
2. Verbindungstyp: **Moonraker**
|
2. Verbindungstyp: **Moonraker**
|
||||||
3. Adresse: `http://IP-DES-BRIDGE-PC:7125` eintragen
|
3. IP: `http://BRIDGE-HOST:7125`
|
||||||
4. Auf „Test" klicken – bei erfolgreicher Verbindung erscheint eine Bestätigungsmeldung
|
4. Verbindung testen → sollte "Online" anzeigen
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Web-UI
|
## Web-UI
|
||||||
|
|
||||||
Die Bridge stellt unter `http://BRIDGE-IP:7125` eine Web-Oberfläche bereit:
|
Die Bridge stellt unter `http://BRIDGE-HOST:7125` eine Web-Oberfläche bereit:
|
||||||
|
|
||||||
| Bereich | Funktion |
|
| Bereich | Funktion |
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
@@ -136,55 +156,56 @@ Die Bridge stellt unter `http://BRIDGE-IP:7125` eine Web-Oberfläche bereit:
|
|||||||
| Druckgeschwindigkeit | Leise / Normal / Sport |
|
| Druckgeschwindigkeit | Leise / Normal / Sport |
|
||||||
| Lüfter / Licht | Lüfterdrehzahl und Drucklicht |
|
| Lüfter / Licht | Lüfterdrehzahl und Drucklicht |
|
||||||
| AMS | Filament einziehen / ausziehen |
|
| AMS | Filament einziehen / ausziehen |
|
||||||
| Kamera | Live-Vorschau (falls vom Drucker unterstützt) |
|
| Kamera | Live-Vorschau (falls Drucker unterstützt) |
|
||||||
| ⚙ Einstellungen | MQTT-Zugangsdaten, Poll-Intervall, Self-Update |
|
| ⚙ Einstellungen | MQTT-Zugangsdaten, Poll-Intervall, Self-Update |
|
||||||
|
|
||||||
### Self-Update
|
### Self-Update
|
||||||
|
|
||||||
Über das ⚙-Menü in der Web-UI kann die Bridge auf neue Versionen prüfen und sich selbst aktualisieren — ohne Neuinstallation. Nach dem Download startet sie automatisch neu.
|
Über das ⚙-Menü in der Web-UI kann die Bridge auf neue Versionen prüfen und sich selbst aktualisieren — ohne Neuinstallation. Nach dem Download startet die Bridge automatisch mit der neuen Version neu.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## bridge.sh – Service-Manager (Linux)
|
## bridge.sh (Linux Service-Manager)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bridge.sh start # Im Hintergrund starten
|
./bridge.sh start # Bridge im Hintergrund starten
|
||||||
./bridge.sh stop # Beenden
|
./bridge.sh stop # Bridge beenden
|
||||||
./bridge.sh restart # Neustarten
|
./bridge.sh restart # Neustarten
|
||||||
./bridge.sh status # Status anzeigen
|
./bridge.sh status # Status und Port prüfen
|
||||||
./bridge.sh log 50 # Letzte 50 Log-Zeilen
|
./bridge.sh log 50 # Letzte 50 Log-Zeilen
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Docker – Nützliche Befehle
|
## Druckerzustände
|
||||||
|
|
||||||
```bash
|
Die Bridge übersetzt die internen Kobra-Zustände in Moonraker-kompatible Zustände:
|
||||||
docker compose up -d # Starten
|
|
||||||
docker compose down # Stoppen
|
| Kobra-Zustand | Bedeutung |
|
||||||
docker compose logs -f # Logs verfolgen
|
|---------------|-----------|
|
||||||
docker compose pull && docker compose up -d # Update
|
| free | Bereit |
|
||||||
```
|
| printing / busy | Druckt |
|
||||||
|
| pausing / paused | Pausiert |
|
||||||
|
| resuming / resumed | Wird fortgesetzt |
|
||||||
|
| stopping / stoped | Wird gestoppt |
|
||||||
|
| finished | Abgeschlossen |
|
||||||
|
| canceled | Abgebrochen |
|
||||||
|
| failed | Fehler |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Fehlerbehebung
|
## Fehlerbehebung
|
||||||
|
|
||||||
**Port 7125 belegt:**
|
**Port 7125 bereits belegt:**
|
||||||
```bash
|
```bash
|
||||||
./bridge.sh stop
|
./bridge.sh stop # oder: fuser -k 7125/tcp
|
||||||
./bridge.sh start
|
./bridge.sh start
|
||||||
```
|
```
|
||||||
|
|
||||||
**Verbindungstest in OrcaSlicer schlägt fehl:**
|
**Credentials ungültig / Verbindung abgelehnt:**
|
||||||
- Firewall prüfen: Port 7125 muss erreichbar sein
|
- AnycubicSlicerNext starten, mit Drucker verbinden, `extract_credentials` erneut ausführen
|
||||||
- Bridge-Log prüfen: `./bridge.sh log` oder `docker compose logs`
|
- Falls das Ergebnis unsicher wirkt: `extract_credentials --verbose` zeigt alle Kandidaten an
|
||||||
- Drucker-IP in `.env` korrekt?
|
- Den richtigen Kandidaten manuell in `.env` eintragen und Bridge neu starten
|
||||||
|
|
||||||
**Zugangsdaten werden abgelehnt:**
|
|
||||||
- AnycubicSlicerNext starten, mit Drucker verbinden
|
|
||||||
- `extract_credentials --verbose` ausführen und alle Kandidaten prüfen
|
|
||||||
- Richtigen Wert manuell in `.env` eintragen, Bridge neu starten
|
|
||||||
|
|
||||||
**Temperaturänderungen werden ignoriert:**
|
**Temperaturänderungen werden ignoriert:**
|
||||||
- Während eines laufenden Drucks werden Temperaturänderungen über einen separaten Kanal gesendet — das ist normal und wird von der Bridge automatisch erkannt.
|
- Während eines laufenden Drucks werden Temperaturänderungen über einen separaten Kanal gesendet — das ist normal und wird von der Bridge automatisch erkannt.
|
||||||
@@ -192,21 +213,26 @@ docker compose pull && docker compose up -d # Update
|
|||||||
**Docker: Permission denied:**
|
**Docker: Permission denied:**
|
||||||
```bash
|
```bash
|
||||||
sudo usermod -aG docker $USER
|
sudo usermod -aG docker $USER
|
||||||
# Neu einloggen, dann erneut versuchen
|
# Neu einloggen
|
||||||
|
```
|
||||||
|
|
||||||
|
**Docker: .env nicht gefunden:**
|
||||||
|
```bash
|
||||||
|
# .env muss im gleichen Verzeichnis wie docker-compose.yml liegen
|
||||||
|
cp .env.example .env && nano .env
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Konfigurationsreferenz (.env)
|
## Logs
|
||||||
|
|
||||||
| Parameter | Beschreibung | Beispiel |
|
```bash
|
||||||
|-----------|-------------|---------|
|
# Docker
|
||||||
| `PRINTER_IP` | IP-Adresse des Druckers | `192.168.1.100` |
|
docker compose logs -f kx-bridge
|
||||||
| `MQTT_PORT` | MQTT-Port (nicht ändern) | `9883` |
|
|
||||||
| `MQTT_USERNAME` | Benutzername (beginnt mit „user") | `userXXXXXXXXXX` |
|
# Binary / Python
|
||||||
| `MQTT_PASSWORD` | Passwort (~15 Zeichen) | `***` |
|
tail -f /tmp/bridge.log # bei Nutzung von bridge.sh
|
||||||
| `DEVICE_ID` | Geräte-ID (32 Hex-Zeichen) | `xxxxxxxx...` |
|
```
|
||||||
| `MODE_ID` | Modell-ID (Kobra X Standard) | `20030` |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -214,14 +240,11 @@ sudo usermod -aG docker $USER
|
|||||||
|
|
||||||
- Die Bridge bindet standardmäßig auf `0.0.0.0:7125` — nur im lokalen Netzwerk nutzen
|
- Die Bridge bindet standardmäßig auf `0.0.0.0:7125` — nur im lokalen Netzwerk nutzen
|
||||||
- `.env` enthält Drucker-Credentials — nicht öffentlich teilen
|
- `.env` enthält Drucker-Credentials — nicht öffentlich teilen
|
||||||
- Alle Zugangsdaten werden ausschließlich lokal verarbeitet — keine Übertragung an externe Server
|
- Die Credentials sind druckerspezifisch und haben keinen Zugang zu Anycubic-Cloud-Diensten
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Hinweis zur Nutzung
|
## Lizenz & Rechtliches
|
||||||
|
|
||||||
Dieses Projekt dient der privaten Nutzung und der Herstellung von Interoperabilität zwischen dem Anycubic Kobra X und freier Software (OrcaSlicer).
|
Dieses Projekt entstand durch Interoperabilitätsforschung gem. §69e UrhG.
|
||||||
|
Ausschließlich für private, nicht-kommerzielle Nutzung.
|
||||||
`extract_credentials` liest ausschließlich den Arbeitsspeicher des auf deinem eigenen PC laufenden AnycubicSlicerNext-Prozesses. Es werden keine Daten übertragen oder gespeichert, außer in die lokale `.env`-Datei.
|
|
||||||
|
|
||||||
Das Projekt steht in keiner Verbindung zu Anycubic und wird nicht kommerziell betrieben.
|
|
||||||
|
|||||||
@@ -394,14 +394,14 @@ class KobraXClient:
|
|||||||
def stop_camera(self) -> dict | None:
|
def stop_camera(self) -> dict | None:
|
||||||
return self.publish("video", "stopCapture")
|
return self.publish("video", "stopCapture")
|
||||||
|
|
||||||
def pause_print(self) -> dict | None:
|
def pause_print(self, taskid: str = "-1") -> dict | None:
|
||||||
return self.publish("print", "pause")
|
return self.publish("print", "pause", {"taskid": taskid})
|
||||||
|
|
||||||
def resume_print(self) -> dict | None:
|
def resume_print(self, taskid: str = "-1") -> dict | None:
|
||||||
return self.publish("print", "resume")
|
return self.publish("print", "resume", {"taskid": taskid})
|
||||||
|
|
||||||
def stop_print(self) -> dict | None:
|
def stop_print(self, taskid: str = "-1") -> dict | None:
|
||||||
return self.publish("print", "stop")
|
return self.publish("print", "stop", {"taskid": taskid})
|
||||||
|
|
||||||
# -- G-Code Upload -------------------------------------------------------
|
# -- G-Code Upload -------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ KOBRA_TO_KLIPPER_STATE = {
|
|||||||
"checking": "printing",
|
"checking": "printing",
|
||||||
"updated": "printing",
|
"updated": "printing",
|
||||||
"init": "printing",
|
"init": "printing",
|
||||||
|
"pausing": "paused",
|
||||||
|
"paused": "paused",
|
||||||
|
"resuming": "printing",
|
||||||
|
"resumed": "printing",
|
||||||
|
"stopping": "printing",
|
||||||
|
"stoped": "standby",
|
||||||
"finished": "complete",
|
"finished": "complete",
|
||||||
"failed": "error",
|
"failed": "error",
|
||||||
"canceled": "standby",
|
"canceled": "standby",
|
||||||
@@ -118,6 +124,9 @@ class KobraXBridge:
|
|||||||
self._state["print_state"] = KOBRA_TO_KLIPPER_STATE.get(kobra_state, "printing")
|
self._state["print_state"] = KOBRA_TO_KLIPPER_STATE.get(kobra_state, "printing")
|
||||||
if kobra_state:
|
if kobra_state:
|
||||||
self._state["kobra_state"] = kobra_state
|
self._state["kobra_state"] = kobra_state
|
||||||
|
if kobra_state in ("stoped", "canceled"):
|
||||||
|
self._state["progress"] = 0.0
|
||||||
|
self._state["filename"] = ""
|
||||||
self._state["filename"] = d.get("filename", self._state["filename"])
|
self._state["filename"] = d.get("filename", self._state["filename"])
|
||||||
if "progress" in d:
|
if "progress" in d:
|
||||||
self._state["progress"] = float(d["progress"]) / 100.0
|
self._state["progress"] = float(d["progress"]) / 100.0
|
||||||
@@ -519,17 +528,20 @@ class KobraXBridge:
|
|||||||
|
|
||||||
async def handle_print_pause(self, request):
|
async def handle_print_pause(self, request):
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
await loop.run_in_executor(None, self.client.pause_print)
|
taskid = self._state.get("taskid", "-1")
|
||||||
|
await loop.run_in_executor(None, lambda: self.client.pause_print(taskid))
|
||||||
return web.json_response({"result": "ok"})
|
return web.json_response({"result": "ok"})
|
||||||
|
|
||||||
async def handle_print_resume(self, request):
|
async def handle_print_resume(self, request):
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
await loop.run_in_executor(None, self.client.resume_print)
|
taskid = self._state.get("taskid", "-1")
|
||||||
|
await loop.run_in_executor(None, lambda: self.client.resume_print(taskid))
|
||||||
return web.json_response({"result": "ok"})
|
return web.json_response({"result": "ok"})
|
||||||
|
|
||||||
async def handle_print_cancel(self, request):
|
async def handle_print_cancel(self, request):
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
await loop.run_in_executor(None, self.client.stop_print)
|
taskid = self._state.get("taskid", "-1")
|
||||||
|
await loop.run_in_executor(None, lambda: self.client.stop_print(taskid))
|
||||||
return web.json_response({"result": "ok"})
|
return web.json_response({"result": "ok"})
|
||||||
|
|
||||||
async def handle_octoprint_version(self, request):
|
async def handle_octoprint_version(self, request):
|
||||||
@@ -1118,7 +1130,7 @@ function toggleTheme(){
|
|||||||
// ── i18n ──
|
// ── i18n ──
|
||||||
var LANG_DE={
|
var LANG_DE={
|
||||||
header_status_standby:'Bereit',header_status_printing:'Druckt',header_status_complete:'Fertig',header_status_error:'Fehler',
|
header_status_standby:'Bereit',header_status_printing:'Druckt',header_status_complete:'Fertig',header_status_error:'Fehler',
|
||||||
kobra_free:'Bereit',kobra_busy:'Beschäftigt',kobra_printing:'Druckt',kobra_preheating:'Aufheizen',kobra_auto_leveling:'Nivellierung',kobra_checking:'Prüfung',kobra_updated:'Aktualisierung',kobra_init:'Initialisierung',kobra_finished:'Abgeschlossen',kobra_failed:'Fehler',kobra_canceled:'Abgebrochen',kobra_offline:'Offline',
|
kobra_free:'Bereit',kobra_busy:'Beschäftigt',kobra_printing:'Druckt',kobra_preheating:'Aufheizen',kobra_auto_leveling:'Nivellierung',kobra_checking:'Prüfung',kobra_updated:'Aktualisierung',kobra_init:'Initialisierung',kobra_pausing:'Pausiert...',kobra_paused:'Pausiert',kobra_resuming:'Fortsetzen...',kobra_resumed:'Fortgesetzt',kobra_stopping:'Stoppt...',kobra_stoped:'Gestoppt',kobra_finished:'Abgeschlossen',kobra_failed:'Fehler',kobra_canceled:'Abgebrochen',kobra_offline:'Offline',
|
||||||
nav_dashboard:'Dashboard',nav_print:'Druck',nav_temps:'Temperaturen',nav_motion:'Achsen',nav_ams:'AMS',nav_extras:'Licht / Lüfter',nav_console:'Konsole',
|
nav_dashboard:'Dashboard',nav_print:'Druck',nav_temps:'Temperaturen',nav_motion:'Achsen',nav_ams:'AMS',nav_extras:'Licht / Lüfter',nav_console:'Konsole',
|
||||||
card_progress:'Fortschritt',card_temps:'Temperaturen',card_light_fan:'Lüfter',card_speed:'Druckgeschwindigkeit',card_cam:'Kamera',
|
card_progress:'Fortschritt',card_temps:'Temperaturen',card_light_fan:'Lüfter',card_speed:'Druckgeschwindigkeit',card_cam:'Kamera',
|
||||||
speed_silent:'🐢 Leise',speed_normal:'⚡ Normal',speed_sport:'🚀 Sport',
|
speed_silent:'🐢 Leise',speed_normal:'⚡ Normal',speed_sport:'🚀 Sport',
|
||||||
@@ -1143,7 +1155,7 @@ var LANG_DE={
|
|||||||
};
|
};
|
||||||
var LANG_EN={
|
var LANG_EN={
|
||||||
header_status_standby:'Ready',header_status_printing:'Printing',header_status_complete:'Complete',header_status_error:'Error',
|
header_status_standby:'Ready',header_status_printing:'Printing',header_status_complete:'Complete',header_status_error:'Error',
|
||||||
kobra_free:'Ready',kobra_busy:'Busy',kobra_printing:'Printing',kobra_preheating:'Preheating',kobra_auto_leveling:'Auto Leveling',kobra_checking:'Checking',kobra_updated:'Updating',kobra_init:'Initializing',kobra_finished:'Finished',kobra_failed:'Error',kobra_canceled:'Cancelled',kobra_offline:'Offline',
|
kobra_free:'Ready',kobra_busy:'Busy',kobra_printing:'Printing',kobra_preheating:'Preheating',kobra_auto_leveling:'Auto Leveling',kobra_checking:'Checking',kobra_updated:'Updating',kobra_init:'Initializing',kobra_pausing:'Pausing...',kobra_paused:'Paused',kobra_resuming:'Resuming...',kobra_resumed:'Resumed',kobra_stopping:'Stopping...',kobra_stoped:'Stopped',kobra_finished:'Finished',kobra_failed:'Error',kobra_canceled:'Cancelled',kobra_offline:'Offline',
|
||||||
nav_dashboard:'Dashboard',nav_print:'Print',nav_temps:'Temperatures',nav_motion:'Motion',nav_ams:'AMS',nav_extras:'Light / Fan',nav_console:'Console',
|
nav_dashboard:'Dashboard',nav_print:'Print',nav_temps:'Temperatures',nav_motion:'Motion',nav_ams:'AMS',nav_extras:'Light / Fan',nav_console:'Console',
|
||||||
card_progress:'Progress',card_temps:'Temperatures',card_light_fan:'Fan',card_speed:'Print Speed',card_cam:'Camera',
|
card_progress:'Progress',card_temps:'Temperatures',card_light_fan:'Fan',card_speed:'Print Speed',card_cam:'Camera',
|
||||||
speed_silent:'🐢 Silent',speed_normal:'⚡ Normal',speed_sport:'🚀 Sport',
|
speed_silent:'🐢 Silent',speed_normal:'⚡ Normal',speed_sport:'🚀 Sport',
|
||||||
|
|||||||
Reference in New Issue
Block a user