4 Commits

Author SHA1 Message Date
9f6b6a8518 release: v0.9.9 2026-05-14 17:23:05 +02:00
5eda8a241f docs: README.md englisch + README.de.md deutsch mit Sprach-Cross-Link 2026-05-12 19:41:16 +02:00
2aaaa5bbbe README.de.md aktualisiert 2026-05-12 17:20:38 +02:00
374457fb07 release: v0.9.8 2026-05-12 15:05:35 +02:00
10 changed files with 1890 additions and 322 deletions

View File

@@ -1,5 +1,37 @@
# Changelog # Changelog
## [0.9.9] 2026-05-14
### Fixes
- **„Failed to fetch"-Schleife in der UI (Issue #21):** Wenn die Web-UI über die LAN-IP geöffnet wurde, lieferte `/kx/printers` `bridge_url: http://localhost:7125` zurück. Der Browser machte daraufhin Cross-Origin-Requests von der LAN-IP nach `localhost` — die wurden vom Browser blockiert und produzierten eine Flut aus `TypeError: Failed to fetch`-Poll-Fehlern. Die Bridge liefert jetzt im Einzel-Drucker-Modus eine leere `bridge_url`, sodass das Frontend relative Pfade gegen dieselbe Origin wie die UI nutzt. Im Multi-Printer-Modus werden `localhost`/`127.0.0.1` als Bridge-Hosts herausgefiltert.
- **Windows-EXE crasht beim Start (Issue #21):** Die v0.9.8-`kx-bridge.exe` wurde mit einer veralteten `config_loader.py` aus einem früheren Release gebaut und stürzte mit `AttributeError: module 'config_loader' has no attribute 'list_printers'` ab. `release.sh` synct jetzt `config_loader.py` zusammen mit den anderen Quellen ins Windows-Build-Repository.
---
## [0.9.8] 2026-05-12
### Neu
- **Multi-Printer in einer Bridge-Instanz:** Ein Prozess verwaltet jetzt mehrere Drucker gleichzeitig — N MQTT-Verbindungen + N HTTP-Listener (Ports 7125, 7126, …), geteilte SQLite + GCode-Store. Konfiguration über `[printer_1]`-, `[printer_2]`-… Sektionen in `config.ini`. Einzel-Modus (`[connection]`) funktioniert unverändert weiter. `docker-compose.yml` exposed einen Port-Range `7125-7130`.
- **Drucker per UI hinzufügen:** „+ Drucker hinzufügen"-Button im Drucker-Tab — nur die IP eingeben, Zugangsdaten (Username, Passwort, Device-ID) werden automatisch vom Drucker geholt und entschlüsselt. Weitere Drucker bekommen den nächsten freien Port (7126, 7127, …).
- **Drucker per UI entfernen:** „✕"-Button auf jeder Drucker-Karte mit Bestätigung — entfernt die `[printer_N]`-Sektion und nummeriert die übrigen um. Beim Entfernen des letzten Druckers wird auch `[connection]` geleert (leerer Zustand).
- **GCode Store:** Hochgeladene Dateien werden in SQLite gespeichert, inkl. Thumbnail-Extraktion. Neue `/kx/files`-API.
- **Browser-Tab:** Grid-Ansicht aller hochgeladenen Dateien — Thumbnail, Status-Badge (✓/✗), letzte Druckdauer, plus Suche, Filter und Sortierung.
- **Druckhistorie:** Druckaufträge (Start/Ende/Status) werden in SQLite protokolliert, Status pro Datei im Browser-Tab sichtbar.
- **Filament-Dialog:** Per-Kanal-Remapping vor dem Druckstart — jeder GCode-Farbkanal wird einem physischen AMS-Slot zugewiesen (wie im Anycubic Slicer). Verfügbar im Browser-Tab und im Upload-Banner.
- **MMU-Emulation:** `GET /printer/objects/query?mmu` liefert eine Happy-Hare-kompatible Struktur, damit OrcaSlicers Filament-Sync die AMS-Slots erkennt.
- **Drucker-Tab:** Live-Status aller Drucker-Instanzen, IP auf jeder Karte, „Wechseln →"-Button.
- **Editierbarer Drucker-Name:** Eigener Name in den Einstellungen (gespeichert in `[bridge] printer_name`, hat Vorrang vor dem vom Drucker gemeldeten Namen).
- **Standalone-tauglich:** Linux-Binary / Windows-EXE laufen ohne Docker — `config/` und `data/` liegen neben dem Programm (portabel). Erststart ohne konfigurierten Drucker zeigt den Drucker-Tab mit „+ Drucker hinzufügen" statt des Einstellungs-Dialogs.
- **i18n:** Alle neuen UI-Elemente auf Deutsch und Englisch.
### Fixes
- **CORS:** CORS-Middleware auf allen Endpunkten — Cross-Instance-Fetches in der Multi-Printer-UI funktionieren zuverlässig.
- **Einstellungen / Update-Check** zeigen im Multi-Printer-Modus jetzt die aktive Bridge-Instanz (via `_apiUrl`).
- **Bridge-Neustart:** Config-abhängige Umgebungsvariablen werden vor einem Neustart gelöscht (der Config-Loader cachte sie, wodurch Config-Änderungen erst nach einem Kaltstart sichtbar wurden). Der Neustart ist jetzt plattformabhängig: Docker/systemd → Prozess-Exit (Supervisor startet neu), Linux standalone → `os.execv`, Windows → detachter Subprozess.
- **`--data-dir`-Default** ist jetzt plattformabhängig — der `/app/data`-Default greift nur in Docker (per `ENV` gesetzt), Standalone-Binaries nutzen `<exe-dir>/data`. Behebt einen Startup-Crash beim Ausführen ohne Docker.
---
## [0.9.7] 2026-05-08 ## [0.9.7] 2026-05-08
### Neu ### Neu

View File

@@ -1,5 +1,37 @@
# Changelog # Changelog
## [0.9.9] 2026-05-14
### Fixes
- **"Failed to fetch" loop in the UI (Issue #21):** When the web UI was opened via the LAN IP, `/kx/printers` was returning `bridge_url: http://localhost:7125`, which caused the browser to fire cross-origin requests from the LAN IP to `localhost` — these were silently blocked, producing a flood of `TypeError: Failed to fetch` poll errors. The bridge now sends an empty `bridge_url` in single-printer mode so the frontend uses relative paths against the same origin as the UI. In multi-printer mode, `localhost`/`127.0.0.1` are filtered out as bridge hosts.
- **Windows EXE startup crash (Issue #21):** The v0.9.8 `kx-bridge.exe` was built with a stale `config_loader.py` from an earlier release and crashed on startup with `AttributeError: module 'config_loader' has no attribute 'list_printers'`. `release.sh` now syncs `config_loader.py` into the Windows build repository together with the other source files.
---
## [0.9.8] 2026-05-12
### New
- **Multi-printer in a single bridge instance:** One process now manages multiple printers — N MQTT connections + N HTTP listeners (ports 7125, 7126, …), shared SQLite + GCode store. Configure via `[printer_1]`, `[printer_2]` … sections in `config.ini`. Single-printer mode (`[connection]` only) keeps working unchanged. `docker-compose.yml` exposes a port range `7125-7130`.
- **Add printer from the UI:** "+ Add printer" button in the Printers tab — just enter the printer IP, the credentials (username, password, device ID) are fetched and decrypted from the printer automatically. Adding more printers assigns the next free port (7126, 7127, …).
- **Remove printer from the UI:** "✕" button on each printer card with a confirmation dialog — removes the `[printer_N]` section and renumbers the rest. Removing the last printer clears `[connection]` too, leaving an empty state.
- **GCode Store:** Uploaded files are persisted in SQLite with thumbnail extraction. New `/kx/files` API.
- **Browser tab:** Grid view of all uploaded files — thumbnail, status badge (✓/✗), last print duration, plus search, filter and sort.
- **Print history:** Print jobs (start/end/status) are recorded in SQLite, status shown per file in the Browser tab.
- **Filament dialog:** Per-channel remapping before print start — assign each GCode color channel to a physical AMS slot (like the Anycubic Slicer does). Available in the Browser tab and the upload banner.
- **MMU emulation:** `GET /printer/objects/query?mmu` returns a Happy-Hare-compatible structure so OrcaSlicer's filament sync detects the AMS slots.
- **Printers tab:** Live status of all printer instances, IP shown on each card, "Switch →" button.
- **Editable printer name:** Set a custom name in Settings (stored in `[bridge] printer_name`, takes precedence over the MQTT-reported name).
- **Standalone friendly:** Linux binary / Windows EXE run without Docker — `config/` and `data/` are placed next to the executable (portable). First start with no printer configured shows the Printers tab with "+ Add printer" instead of the settings modal.
- **i18n:** All new UI elements available in German and English.
### Fixes
- **CORS:** CORS middleware added to all endpoints — cross-instance fetches in the multi-printer UI work reliably.
- **Settings / update check** now reflect the active bridge instance in multi-printer mode (via `_apiUrl`).
- **Bridge restart:** Config-dependent environment variables are cleared before a restart (the config loader cached them, which made config changes invisible until the next cold start). Restart is now platform-aware: Docker/systemd → process exit (supervisor restarts), Linux standalone → `os.execv`, Windows → detached subprocess.
- **`--data-dir` default** is now platform-dependent — the `/app/data` default only applies inside Docker (set via `ENV`), standalone binaries use `<exe-dir>/data`. Fixes a startup crash when running the binary without Docker.
---
## [0.9.7] 2026-05-08 ## [0.9.7] 2026-05-08
### New ### New

View File

@@ -16,7 +16,12 @@ COPY config/config.ini.example /app/config/config.ini.example
# config/ ist ein Volume-Mountpoint beim Start wird config.ini aus .env migriert # config/ ist ein Volume-Mountpoint beim Start wird config.ini aus .env migriert
# falls noch keine config.ini vorhanden ist. # falls noch keine config.ini vorhanden ist.
RUN mkdir -p /app/config RUN mkdir -p /app/config && mkdir -p /app/data
# Daten-Verzeichnis fest auf /app/data (sonst würde der Binary-Default <exe-dir>/data greifen)
# und Container-Erkennung für den Bridge-Restart (Supervisor startet neu statt subprocess).
ENV KX_DATA_DIR=/app/data
ENV KX_IN_DOCKER=1
EXPOSE 7125 EXPOSE 7125

View File

@@ -1,160 +1,182 @@
<p align="center"><img src="knlogo.png" alt="KX-Bridge Logo" width="180"/></p> <div align="center">
# KX-Bridge Anycubic Kobra X <img src="knlogo.png" alt="KX-Bridge" width="160"/>
**Version:** 0.9.7 # KX-Bridge
Steuere deinen **Anycubic Kobra X** mit OrcaSlicer — ohne Klipper, ohne Raspberry Pi. **Steuere deinen Anycubic Kobra X mit OrcaSlicer — ohne Klipper, ohne Raspberry Pi.**
KX-Bridge ist eine Moonraker-kompatible Bridge die direkt mit dem Drucker kommuniziert.
Eine Moonraker-kompatible Bridge, die direkt mit dem Drucker spricht.
<sub>🇬🇧 <a href="README.md">English version</a></sub>
<br>
[![Ko-fi](https://img.shields.io/badge/Ko--fi-Support%20this%20project-FF5E5B?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/viewitde)
&nbsp;
[![Releases](https://img.shields.io/badge/Download-Releases-2EA043?style=for-the-badge&logo=gitea&logoColor=white)](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases)
&nbsp;
[![Video](https://img.shields.io/badge/YouTube-Tutorial-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/watch?v=1Ql4wfH27fM)
<sub>Gefällt dir KX-Bridge? Ein Kaffee auf <a href="https://ko-fi.com/viewitde">Ko-fi</a> hält das Projekt am Leben. ☕</sub>
</div>
--- ---
## Schnellstart in 3 Schritten ## ✨ Was kann KX-Bridge?
### Schritt 1 Drucker vorbereiten | | Feature |
|---|---|
| 🖨️ | **Druckersteuerung** — Start, Pause, Resume, Abbruch, Temperaturen, Druckgeschwindigkeit |
| 📊 | **Live-Status** — Temperatur, Fortschritt, Layer, Restzeit, Kamera-Stream |
| 🎨 | **AMS / Multicolor** — Filament-Slots, Per-Kanal-Remapping, MMU-Emulation für OrcaSlicer Filament-Sync |
| 🗂️ | **GCode-Browser** — hochgeladene Dateien mit Thumbnail, Druckhistorie, Suche & Filter |
| 🧩 | **Multi-Printer** — mehrere Drucker in **einer** Bridge-Instanz, Umschalten per Dropdown |
| | **Drucker hinzufügen per Klick** — nur die IP eingeben, Zugangsdaten werden automatisch importiert |
| 🔄 | **Self-Update** — neue Versionen direkt im Browser installieren |
| 🌐 | **OrcaSlicer** — volles Moonraker-Protokoll (HTTP + WebSocket), DE/EN UI |
Den Kobra X in den LAN-Modus versetzen: ---
**Drucker-Display → Einstellungen → LAN-Modus einschalten**
### Schritt 2 Credentials holen ## 🚀 Schnellstart
Die MQTT-Zugangsdaten sind druckerspezifisch und an die Hardware gebunden. ### 1. Drucker vorbereiten
**Option A fetch_credentials (empfohlen):** LAN-Modus am Kobra X aktivieren:
**Drucker-Display → Einstellungen → LAN-Modus aktivieren**
### 2. Bridge starten
**Docker (empfohlen):**
```bash
docker compose up -d
```
**Linux-Binary (kein Docker):**
```bash
chmod +x kx-bridge && ./kx-bridge
```
**Windows-EXE (kein Docker):**
```
kx-bridge.exe
```
> `config\` und `data\` werden neben der EXE angelegt — portabel.
> Bei Linux- und Windows-Binary liegen `config/` und `data/` (Einstellungen, SQLite,
> GCode-Store) jeweils neben dem Programm. Einfach den ganzen Ordner kopieren = umziehen.
**Python direkt:**
```bash
pip install -r bridge/requirements.txt
python bridge/kobrax_moonraker_bridge.py
```
### 3. Drucker einrichten
Web-UI öffnen: **`http://BRIDGE-IP:7125`**
Beim Erststart erscheint der **Drucker-Tab** mit *„+ Drucker hinzufügen"* — einfach die
IP-Adresse des Druckers eingeben, der Rest (Username, Passwort, Device-ID) wird automatisch
vom Drucker geholt und entschlüsselt. Fertig.
> Mehrere Drucker? Einfach mehrfach *„+ Drucker hinzufügen"* — jeder bekommt seinen eigenen
> Port (7125, 7126, …) und ist im Header-Dropdown auswählbar.
### 4. OrcaSlicer verbinden
Drucker → Verbindungstyp **Moonraker** → Host: `http://BRIDGE-IP:7125`
> ⚠️ Verbindungstyp muss **Moonraker** sein (nicht „Bambu" oder „Klipper").
> Vollständige URL inkl. `http://` und Port `:7125` im Host-Feld eintragen.
---
## 📺 Video-Tutorial
[![KX-Bridge Setup & Usage](https://img.youtube.com/vi/1Ql4wfH27fM/hqdefault.jpg)](https://www.youtube.com/watch?v=1Ql4wfH27fM)
---
## 🔧 Zugangsdaten manuell ermitteln
Normalerweise nicht nötig — *„+ Drucker hinzufügen"* macht das automatisch. Falls doch:
```bash ```bash
fetch_credentials --ip 192.168.x.x --write-config fetch_credentials --ip 192.168.x.x --write-config
``` ```
Holt die Zugangsdaten per HTTP direkt vom Drucker und schreibt sie in `config/config.ini`.
Nur die Drucker-IP nötig, kein Slicer.
Holt die Credentials direkt per HTTP vom Drucker und schreibt sie automatisch in `config/config.ini`. Benötigt nur die Drucker-IP — kein Slicer nötig. Alternativ (wenn die IP unbekannt ist): AnycubicSlicerNext öffnen, Drucker verbinden,
dann `extract_credentials` ausführen → gibt Username, Passwort, Device-ID und IP aus.
**Option B extract_credentials (wenn Drucker-IP unbekannt):** > **Downloads:** [Releases](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases) → `fetch_credentials` / `extract_credentials` (Linux & Windows)
1. **AnycubicSlicerNext** öffnen und Drucker verbinden (bis Status angezeigt wird) ---
2. **`extract_credentials`** ausführen — gibt Username, Password, Device-ID und Drucker-IP aus
3. Werte im Web-UI eintragen (⚙-Menü)
> **Download:** [gitea.it-drui.de/viewit/KX-Bridge-Release/releases](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases) → `fetch_credentials` / `extract_credentials` (Linux & Windows) im jeweiligen Release-Asset ## ⚙️ Nützliche Befehle
### Schritt 3 Bridge starten
```bash ```bash
./start.sh docker compose logs -f # Logs anzeigen
``` docker compose down # Bridge stoppen
docker compose up -d --build # Bridge neu bauen & starten (nach Update)
Das Skript baut das Docker-Image automatisch beim ersten Aufruf.
**Web-UI öffnen:** `http://BRIDGE-IP:7125`
→ Das ⚙-Menü öffnet sich beim ersten Start automatisch
→ Bei Option B: Credentials aus Schritt 2 eintragen → **Speichern & Neustart**
**OrcaSlicer verbinden:**
Drucker → Verbindungstyp **Moonraker** → Host: `http://BRIDGE-IP:7125`
> **Wichtig:** Verbindungstyp muss **Moonraker** sein (nicht „Bambu" oder „Klipper").
> Im Host-Feld vollständige URL mit `http://` und Port `:7125` angeben.
---
## 📺 Video Tutorial
[![KX-Bridge Setup & Bedienung](https://img.youtube.com/vi/1Ql4wfH27fM/hqdefault.jpg)](https://www.youtube.com/watch?v=1Ql4wfH27fM)
---
## ⚠️ Update von 0.9.1 oder älter
Ab **0.9.2** speichert KX-Bridge Einstellungen in `config/config.ini` statt in `.env`.
**Migration erfolgt automatisch** — keine manuelle Aktion nötig:
- Beim ersten Start nach dem Update liest die Bridge die vorhandene `.env` und erstellt `config/config.ini` automatisch
- Einstellungen bleiben ab sofort nach `docker-compose restart` und zukünftigen Updates erhalten
- Die `.env`-Datei bleibt read-only gemountet als Migrationsquelle — kann liegen bleiben
- Zum manuellen Anlegen einer `config.ini`: Vorlage unter `config/config.ini.example` kopieren
---
## Was wird unterstützt?
| Funktion | Details |
|----------|---------|
| Druckerstatus | Temperatur, Fortschritt, Zustand, Restzeit |
| Drucksteuerung | Start, Pause, Fortsetzen, Abbrechen |
| Temperaturregelung | Nozzle und Bett während des Drucks |
| Druckgeschwindigkeit | Leise / Normal / Sport |
| AMS-Farbwechsel | Filament einziehen / ausziehen |
| Licht & Lüfter | Drucklicht und Lüfterdrehzahl |
| Web-UI | Dashboard, Achsensteuerung, Kameraansicht |
| Self-Update | Neue Versionen direkt im Browser installieren |
| OrcaSlicer | Moonraker-Protokoll (HTTP + WebSocket) |
---
## Alternativen zu Docker
**Linux Binary** (kein Docker nötig):
```bash
chmod +x kx-bridge
./kx-bridge
```
**Python direkt:**
```bash
pip install aiohttp
python bridge/kobrax_moonraker_bridge.py
```
Web-UI jeweils unter `http://localhost:7125` — ⚙-Menü führt durch die Erstkonfiguration.
---
## Nützliche Befehle
```bash
# Logs anzeigen
docker-compose logs -f
# Bridge stoppen
docker-compose down
# Bridge neu starten (nach Update)
./start.sh
``` ```
--- ---
## Fehlerbehebung ## 🩹 Troubleshooting
**„Falsche MQTT-Zugangsdaten"** beim Start: <details>
- `fetch_credentials --ip <Drucker-IP> --write-config` erneut ausführen und Bridge neu starten <summary><b>"Falsche MQTT-Zugangsdaten" beim Start</b></summary>
- Wenn IP unbekannt: AnycubicSlicerNext neu starten, Drucker verbinden, `extract_credentials` erneut ausführen
- Nur die IP-Adresse ins Feld eintragen, keinen Port (✗ `192.168.1.102:9883` → ✓ `192.168.1.102`)
**Drucker nicht gefunden / kein LAN-Modus:** - Drucker über *„+ Drucker hinzufügen"* erneut hinzufügen, oder
- Am Drucker-Display: Einstellungen → LAN-Modus einschalten `fetch_credentials --ip <ip> --write-config` ausführen und Bridge neu starten
- Nur die IP-Adresse eingeben, ohne Port (✗ `192.168.1.102:9883` → ✓ `192.168.1.102`)
</details>
<details>
<summary><b>Drucker nicht gefunden / kein LAN-Modus</b></summary>
- Am Drucker-Display: Einstellungen → LAN-Modus aktivieren
- Drucker und Bridge müssen im selben Netzwerk sein - Drucker und Bridge müssen im selben Netzwerk sein
</details>
<details>
<summary><b>Docker: Permission denied</b></summary>
**Docker: Permission denied:**
```bash ```bash
sudo usermod -aG docker $USER # dann neu einloggen sudo usermod -aG docker $USER # danach aus- und wieder einloggen
``` ```
</details>
<details>
<summary><b>Upgrade von 0.9.1 oder älter</b></summary>
Ab 0.9.2 speichert KX-Bridge die Einstellungen in `config/config.ini` statt `.env`.
Die Migration läuft automatisch beim ersten Start nach dem Upgrade — keine Aktion nötig.
</details>
--- ---
## Sicherheitshinweise ## 🔒 Sicherheit
- Die Bridge ist im lokalen Netzwerk erreichbar unter `http://<Host-IP>:7125` nicht ins Internet freigeben - Die Bridge ist im lokalen Netzwerk unter `http://<host-IP>:7125` erreichbar — **nicht** ins Internet exposen
- `config/config.ini` enthält Drucker-Credentials — nicht öffentlich teilen - `config/config.ini` enthält Drucker-Zugangsdaten — nicht öffentlich teilen
- Credentials haben keinen Zugang zu Anycubic-Cloud-Diensten - Die Zugangsdaten geben **keinen** Zugriff auf Anycubic-Cloud-Dienste
--- ---
## Lizenz & Rechtliches ## 📄 Lizenz
Interoperabilitätsforschung gem. §69e UrhG — ausschließlich private, nicht-kommerzielle Nutzung. Interoperabilitätsforschung gem. §69e UrhG — private, nicht-kommerzielle Nutzung.
<p align="center"> <div align="center">
<a href="https://ko-fi.com/viewitde"> <br>
<img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Ko-fi Support"/>
</a> **Wenn dir KX-Bridge hilft, freut sich das Projekt über Unterstützung:**
</p>
[![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/viewitde)
</div>

205
README.md
View File

@@ -1,47 +1,94 @@
<p align="center"><img src="knlogo.png" alt="KX-Bridge Logo" width="180"/></p> <div align="center">
# KX-Bridge Anycubic Kobra X <img src="knlogo.png" alt="KX-Bridge" width="160"/>
**Version:** 0.9.7 # KX-Bridge
Control your **Anycubic Kobra X** with OrcaSlicer — no Klipper, no Raspberry Pi. **Control your Anycubic Kobra X with OrcaSlicer — no Klipper, no Raspberry Pi.**
KX-Bridge is a Moonraker-compatible bridge that communicates directly with the printer.
A Moonraker-compatible bridge that talks directly to the printer.
<sub>🇩🇪 <a href="README.de.md">Deutsche Version</a></sub>
<br>
[![Ko-fi](https://img.shields.io/badge/Ko--fi-Support%20this%20project-FF5E5B?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/viewitde)
&nbsp;
[![Releases](https://img.shields.io/badge/Download-Releases-2EA043?style=for-the-badge&logo=gitea&logoColor=white)](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases)
&nbsp;
[![Video](https://img.shields.io/badge/YouTube-Tutorial-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/watch?v=1Ql4wfH27fM)
<sub>Like KX-Bridge? A coffee on <a href="https://ko-fi.com/viewitde">Ko-fi</a> keeps the project alive. ☕</sub>
</div>
--- ---
## Quick Start in 3 Steps ## ✨ Features
### Step 1 Prepare the printer | | |
|---|---|
| 🖨️ | **Printer control** — start, pause, resume, cancel, temperatures, print speed |
| 📊 | **Live status** — temperature, progress, layers, remaining time, camera stream |
| 🎨 | **AMS / multicolor** — filament slots, per-channel remapping, MMU emulation for OrcaSlicer filament sync |
| 🗂️ | **GCode browser** — uploaded files with thumbnails, print history, search & filter |
| 🧩 | **Multi-printer** — multiple printers in **one** bridge instance, switch via dropdown |
| | **Add a printer with one click** — just enter the IP, credentials are imported automatically |
| 🔄 | **Self-update** — install new versions directly in the browser |
| 🌐 | **OrcaSlicer** — full Moonraker protocol (HTTP + WebSocket), EN/DE UI |
---
## 🚀 Quick Start
### 1. Prepare the printer
Enable LAN mode on the Kobra X: Enable LAN mode on the Kobra X:
**Printer display → Settings → Enable LAN mode** **Printer display → Settings → Enable LAN mode**
### Step 2 Get credentials ### 2. Start the bridge
The MQTT credentials are printer-specific. Here's how to get them:
1. Open **AnycubicSlicerNext** and connect the printer (wait until status is shown)
2. Run **`extract_credentials.exe`** (Windows) or **`extract_credentials`** (Linux) — outputs Username, Password, Device ID and printer IP
3. Note / copy the values
> **Download:** [gitea.it-drui.de/viewit/KX-Bridge-Release/releases](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases) → `extract_credentials.exe` (Windows) / `extract_credentials` (Linux) in the release assets
### Step 3 Start the bridge
**Docker (recommended):**
```bash ```bash
./start.sh docker compose up -d
``` ```
The script builds the Docker image automatically on first run. **Linux binary (no Docker):**
```bash
chmod +x kx-bridge && ./kx-bridge
```
**Open Web-UI:** `http://BRIDGE-IP:7125` **Windows EXE (no Docker):**
→ The ⚙ menu opens automatically on first start ```
→ Enter credentials from Step 2 → **Save & Restart** kx-bridge.exe
```
> `config\` and `data\` are created next to the EXE — portable.
> With the Linux and Windows binaries, `config/` and `data/` (settings, SQLite, GCode store)
> live next to the program. Copy the whole folder = move the installation.
**Python directly:**
```bash
pip install -r bridge/requirements.txt
python bridge/kobrax_moonraker_bridge.py
```
### 3. Set up the printer
Open the Web UI: **`http://BRIDGE-IP:7125`**
On first start the **Printers tab** shows *"+ Add printer"* — just enter the printer's IP
address, the rest (username, password, device ID) is fetched from the printer and decrypted
automatically. Done.
> More than one printer? Just click *"+ Add printer"* again — each gets its own port
> (7125, 7126, …) and is selectable from the header dropdown.
### 4. Connect OrcaSlicer
**Connect OrcaSlicer:**
Printer → Connection type **Moonraker** → Host: `http://BRIDGE-IP:7125` Printer → Connection type **Moonraker** → Host: `http://BRIDGE-IP:7125`
> **Important:** Connection type must be **Moonraker** (not "Bambu" or "Klipper"). > ⚠️ Connection type must be **Moonraker** (not "Bambu" or "Klipper").
> Enter the full URL including `http://` and port `:7125` in the host field. > Enter the full URL including `http://` and port `:7125` in the host field.
--- ---
@@ -52,98 +99,84 @@ Printer → Connection type **Moonraker** → Host: `http://BRIDGE-IP:7125`
--- ---
## ⚠️ Upgrading from 0.9.1 or earlier ## 🔧 Getting credentials manually
Starting with **0.9.2**, KX-Bridge stores settings in `config/config.ini` instead of `.env`. Normally not needed — *"+ Add printer"* does this automatically. If you do need it:
**Migration is automatic** — no manual action required:
- On first start after upgrade, the bridge reads your existing `.env` and creates `config/config.ini` automatically
- Settings now survive `docker-compose restart` and future updates
- The `.env` file stays mounted read-only as a migration source — you can keep it in place
- If you want to create a `config.ini` manually: copy `config/config.ini.example`
---
## What's supported?
| Feature | Details |
|---------|---------|
| Printer status | Temperature, progress, state, remaining time |
| Print control | Start, pause, resume, cancel |
| Temperature control | Nozzle and bed during print |
| Print speed | Silent / Normal / Sport |
| AMS filament change | Load / unload filament |
| Light & fan | Print light and fan speed |
| Web-UI | Dashboard, motion control, camera view |
| Self-update | Install new versions directly in the browser |
| OrcaSlicer | Moonraker protocol (HTTP + WebSocket) |
---
## Alternatives to Docker
**Linux binary** (no Docker needed):
```bash ```bash
chmod +x kx-bridge fetch_credentials --ip 192.168.x.x --write-config
./kx-bridge
``` ```
Fetches the credentials directly from the printer via HTTP and writes them to `config/config.ini`.
Only the printer IP is required, no slicer.
**Python directly:** Alternatively (if the IP is unknown): open AnycubicSlicerNext, connect the printer, then run
```bash `extract_credentials` → outputs username, password, device ID and the printer IP.
pip install aiohttp
python bridge/kobrax_moonraker_bridge.py
```
Web-UI available at `http://localhost:7125` — the ⚙ menu guides through initial setup. > **Downloads:** [Releases](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases) → `fetch_credentials` / `extract_credentials` (Linux & Windows)
--- ---
## Useful commands ## ⚙️ Useful commands
```bash ```bash
# Show logs docker compose logs -f # show logs
docker-compose logs -f docker compose down # stop the bridge
docker compose up -d --build # rebuild & start (after an update)
# Stop bridge
docker-compose down
# Restart bridge (after update)
./start.sh
``` ```
--- ---
## Troubleshooting ## 🩹 Troubleshooting
**"Wrong MQTT credentials"** on start: <details>
- Restart AnycubicSlicerNext, reconnect the printer, run `extract_credentials` again <summary><b>"Wrong MQTT credentials" on start</b></summary>
- Re-add the printer via *"+ Add printer"*, or run
`fetch_credentials --ip <ip> --write-config` and restart the bridge
- Enter only the IP address, no port (✗ `192.168.1.102:9883` → ✓ `192.168.1.102`) - Enter only the IP address, no port (✗ `192.168.1.102:9883` → ✓ `192.168.1.102`)
</details>
<details>
<summary><b>Printer not found / no LAN mode</b></summary>
**Printer not found / no LAN mode:**
- On the printer display: Settings → Enable LAN mode - On the printer display: Settings → Enable LAN mode
- Printer and bridge must be on the same network - Printer and bridge must be on the same network
</details>
<details>
<summary><b>Docker: Permission denied</b></summary>
**Docker: Permission denied:**
```bash ```bash
sudo usermod -aG docker $USER # then log out and back in sudo usermod -aG docker $USER # then log out and back in
``` ```
</details>
<details>
<summary><b>Upgrading from 0.9.1 or earlier</b></summary>
Starting with 0.9.2, KX-Bridge stores settings in `config/config.ini` instead of `.env`.
Migration runs automatically on first start after the upgrade — no action required.
</details>
--- ---
## Security ## 🔒 Security
- The bridge is accessible on the local network at `http://<host-IP>:7125` — do not expose to the internet - The bridge is reachable on the local network at `http://<host-IP>:7125`**do not** expose it to the internet
- `config/config.ini` contains printer credentials — do not share publicly - `config/config.ini` contains printer credentials — do not share publicly
- Credentials do not grant access to Anycubic cloud services - The credentials do **not** grant access to Anycubic cloud services
--- ---
## License ## 📄 License
Interoperability research under §69e UrhG — private, non-commercial use only. Interoperability research under §69e UrhG — private, non-commercial use only.
<p align="center"> <div align="center">
<a href="https://ko-fi.com/viewitde"> <br>
<img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Ko-fi Support"/>
</a> **If KX-Bridge helps you, the project appreciates your support:**
</p>
[![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/viewitde)
</div>

View File

@@ -1 +1 @@
0.9.7 0.9.9

36
config/config.ini.example Normal file
View File

@@ -0,0 +1,36 @@
# KX-Bridge Konfigurationsdatei
# Kopiere diese Datei nach config.ini und trage deine Werte ein:
# cp config.ini.example config.ini
#
# Credentials automatisch eintragen:
# python3 tools/fetch_credentials.py --ip 192.168.x.x --write-config
# Alternativ (Windows, ohne Drucker-IP bekannt):
# extract_credentials.exe --write-env (liest aus laufendem AnycubicSlicerNext)
[connection]
# IP-Adresse des Druckers im lokalen Netzwerk
printer_ip = 192.168.x.x
# MQTT-Port (Anycubic Kobra X Standard: 9883)
mqtt_port = 9883
# MQTT-Zugangsdaten (druckerspezifisch, beginnt mit "user")
username = userXXXXXXXXXX
password = XXXXXXXXXXXXXXX
# Geräte-ID (32-stelliger Hex-String, druckerspezifisch)
device_id = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Modell-ID (Kobra X Standard: 20030)
mode_id = 20030
[print]
# Standard-AMS-Slot für Einfarbdruck (auto = alle belegten Slots, 0-3 = fixer Slot)
default_ams_slot = auto
# Auto-Leveling vor jedem Druck (1 = an, 0 = aus)
auto_leveling = 1
[bridge]
# Poll-Intervall in Sekunden
poll_interval = 3

View File

@@ -57,8 +57,9 @@ def _load_config_file(path: pathlib.Path):
"MQTT_PASSWORD": (CONFIG_SECTION_CONNECTION, "password"), "MQTT_PASSWORD": (CONFIG_SECTION_CONNECTION, "password"),
"MODE_ID": (CONFIG_SECTION_CONNECTION, "mode_id"), "MODE_ID": (CONFIG_SECTION_CONNECTION, "mode_id"),
"DEVICE_ID": (CONFIG_SECTION_CONNECTION, "device_id"), "DEVICE_ID": (CONFIG_SECTION_CONNECTION, "device_id"),
"DEFAULT_AMS_SLOT": (CONFIG_SECTION_PRINT, "default_ams_slot"), "DEFAULT_AMS_SLOT": (CONFIG_SECTION_PRINT, "default_ams_slot"),
"AUTO_LEVELING": (CONFIG_SECTION_PRINT, "auto_leveling"), "AUTO_LEVELING": (CONFIG_SECTION_PRINT, "auto_leveling"),
"BRIDGE_PRINTER_NAME": (CONFIG_SECTION_BRIDGE, "printer_name"),
} }
for env_key, (section, option) in mapping.items(): for env_key, (section, option) in mapping.items():
if env_key not in os.environ: if env_key not in os.environ:
@@ -128,6 +129,39 @@ elif _env_path:
_config_path = _target _config_path = _target
def list_printers() -> list[dict]:
"""Liest alle [printer_N]-Sektionen aus config.ini.
Jede Sektion kann folgende Keys haben:
name, printer_ip, mqtt_port, username, password, mode_id, device_id,
bridge_url, default_ams_slot, auto_leveling
Gibt eine leere Liste zurück wenn keine [printer_N]-Sektionen vorhanden sind
(Single-Printer-Betrieb via [connection]).
"""
path = _find_config_file()
if not path:
return []
cfg = configparser.ConfigParser()
cfg.read(path, encoding="utf-8")
printers: list[dict] = []
idx = 1
while True:
section = f"printer_{idx}"
if not cfg.has_section(section):
break
p = dict(cfg[section])
p.setdefault("id", str(idx))
if "mqtt_port" in p:
try:
p["mqtt_port"] = int(p["mqtt_port"])
except ValueError:
p["mqtt_port"] = 9883
printers.append(p)
idx += 1
return printers
def get(key: str, default: str = "") -> str: def get(key: str, default: str = "") -> str:
return os.environ.get(key, default) return os.environ.get(key, default)

View File

@@ -4,9 +4,10 @@ services:
build: . build: .
volumes: volumes:
- ./config:/app/config - ./config:/app/config
- ./data:/app/data
- ./.env:/app/.env:ro - ./.env:/app/.env:ro
ports: ports:
- "7125:7125" - "7125-7130:7125-7130"
restart: unless-stopped restart: unless-stopped
logging: logging:
driver: json-file driver: json-file

File diff suppressed because it is too large Load Diff