From 9c8207354090850e8b1679a74d36de50c83d4f03 Mon Sep 17 00:00:00 2001 From: viewit Date: Tue, 2 Jun 2026 13:31:47 +0200 Subject: [PATCH] build: sources for v0.9.19 --- CHANGELOG.de.md | 63 +- CHANGELOG.md | 63 +- Dockerfile | 1 + VERSION | 2 +- data/orca_filaments.json | 4478 +-------------------------------- kobrax_moonraker_bridge.py | 272 +- orca_filaments.py | 147 ++ web/themes/default/app.js | 148 +- web/themes/default/index.html | 43 + web/translations/de.json | 13 + web/translations/en.json | 13 + web/translations/es.json | 13 + web/translations/zh-cn.json | 13 + 13 files changed, 876 insertions(+), 4393 deletions(-) create mode 100644 orca_filaments.py diff --git a/CHANGELOG.de.md b/CHANGELOG.de.md index 9b90eb1..2adc293 100644 --- a/CHANGELOG.de.md +++ b/CHANGELOG.de.md @@ -1,5 +1,64 @@ # Changelog +## [0.9.19] – 2026-06-02 + +### Neu +- **🎯 Filament-Sync mit OrcaSlicer matched jetzt das richtige Preset** + statt immer auf „Generic PLA" zu landen. Voraussetzung: ein + OrcaSlicer-Build mit dem + [PR #13719](https://github.com/SoftFever/OrcaSlicer/pull/13719) + Empfangs-Patch (im OrcaSlicer-KX-Build dabei). Die Bridge sendet pro + AMS-Slot jetzt `name` + `vendor_name` im Lane-Pfad UND + `gate_filament_name` im Happy-Hare-MMU-Pfad (OrcaSlicer wechselt bei + AMS-Setups automatisch auf den HH-Pfad). +- **Eigene OrcaSlicer-Profile in die Bridge importieren (Issue #41).** + Settings-Tab → „OrcaSlicer-Profile" oder direkt im Slot-Edit-Dialog + („★ Eigene Profile importieren…") lädst du deine `.json`-Files aus + `~/.config/OrcaSlicer/user//filament/` hoch — einzeln oder als + ZIP. Erscheint dann im Slot-Dropdown unter „★ Eigene Profile" und + wird beim Sync an Orca als User-Match weitergegeben. Funktioniert + über HTTP, also auch wenn die Bridge im Docker auf Raspi/NAS läuft + und OrcaSlicer auf dem Desktop. Auch reine Override-Profile mit nur + `inherits: "Generic PLA @System"` + ein paar Tweaks (z.B. + „Bert - PLA") werden korrekt erkannt — die Bridge resolved die + vererbten Felder aus dem System-Parent. + +### Fixes +- **AMS-Sync landete hartnäckig auf „Generic PLA":** das Orca- + Datenmodell hat 68 duplikate `filament_id`-Werte (`OGFL99` allein + 136 mal), und die Bridge wählte oft eine ID die für den Kobra X + nicht `is_compatible` war (z.B. `GFL92` aus dem Kobra-2-Profil → + Orca verwarf es). Generator priorisiert jetzt Kobra-X-Varianten und + filtert Phantom-Profile (Cross-Vendor-Overrides) raus — + `orca_filaments.json` von 1035 → 400 saubere Profile. +- **Slot ohne expliziten Override sendet jetzt `Generic `** statt + einer impliziten Vendor-Annahme. Library-Generic-Profile haben + `compatible_printers: []` (= alle Drucker), sind also immer sichtbar + und matchen verlässlich. +- **Slot-Karte zeigt den Hersteller direkt nach dem Speichern** — + ohne Browser-Reload. `poll()` war async, das Re-Render kam erst + beim nächsten Tick. +- **ACE-Trockner-Toggle warf 502-Fehler obwohl der Trockner ein-/aus- + ging (PR #42 von @gangoke):** `setDry` jetzt fire-and-forget wie + `setAutoFeed`. Der Drucker antwortet auf diesem Push-Topic mit + `code: 0` statt `code: 200`, das hat die Bridge fälschlich als + Fehler interpretiert. + +### Datenmodell / API +- `orca_filaments.json` regeneriert: nur echte Vendor-Profile und + OrcaFilamentLibrary-Profile bleiben drin. Bambu/Polymaker/SUNLU- + Library-Profile dabei, Qidi-Cross-Bundles raus. +- Neue Endpoints: `POST /kx/filament/profiles/user` (ZIP/JSON-Upload), + `GET /kx/filament/profiles/user` (Liste der User-Imports), + `DELETE /kx/filament/profiles/user[?vendor=…&name=…]`. Persistenz + in `/orca_filaments.user.json` (Volume — überlebt + Image-Updates). + +### Build +- Neues Modul `bridge/orca_filaments.py` (gemeinsame Parser-Helfer + für Generator und Import-Endpoint). +- Dockerfile + release.sh um `orca_filaments.py` erweitert. + ## [0.9.18] – 2026-05-31 ### Neu @@ -11,8 +70,8 @@ (`slicer/printer/…`) gesendet, der Drucker hat ihn stillschweigend ignoriert. Jetzt geht er über `web/printer/…` wie der Anycubic Slicer Next es macht (verifiziert via Live-MQTT-Sniff + - Workbench-Vue-Source). **Achtung:** der aktiv geladene Slot kann - während des Drucks nicht umgeschrieben werden — vorher ausziehen. + Workbench-Vue-Source). **Achtung:** der Drucker muss im Idle-Zustand + sein, und leere Slots lassen sich nicht beschriften. - **Mehrsprachiges UI – spanische Übersetzung von Muttersprachler überarbeitet (PR #40 von @pezfisk):** fehlende Akzente (impresión, cámara, después, animación, …), Begriffe vereinheitlicht diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fad354..6b88260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,64 @@ # Changelog +## [0.9.19] – 2026-06-02 + +### New +- **🎯 Filament sync with OrcaSlicer now picks the right preset** + instead of always falling back to "Generic PLA". Requires an + OrcaSlicer build with the + [PR #13719](https://github.com/SoftFever/OrcaSlicer/pull/13719) + receive-side patch (included in the OrcaSlicer-KX build). The bridge + sends `name` + `vendor_name` per AMS slot on the lane path AND + `gate_filament_name` per gate on the Happy-Hare MMU path (OrcaSlicer + switches to the HH path automatically for AMS setups). +- **Import your own OrcaSlicer profiles into the bridge (issue #41).** + Settings → "OrcaSlicer Profiles" or directly in the slot-edit dialog + ("★ Import own profiles…") lets you upload `.json` files from + `~/.config/OrcaSlicer/user//filament/` — single files or as a + ZIP. They show up in the slot dropdown under "★ Own profiles" and + are passed through to Orca on sync as user matches. Works over HTTP + so the bridge can run in Docker on a Raspi/NAS while OrcaSlicer + lives on a desktop. Override-only profiles with just + `inherits: "Generic PLA @System"` + a few tweaks (e.g. "Bert - PLA") + are detected correctly — the bridge resolves the inherited fields + from the system parent. + +### Fixes +- **AMS sync stuck on "Generic PLA":** the Orca data model has 68 + duplicate `filament_id` values (`OGFL99` alone shared by 136 + profiles), and the bridge often picked an ID that was not + `is_compatible` with the Kobra X (e.g. `GFL92` from the Kobra-2 + profile → Orca rejected it). The generator now prioritises Kobra-X + variants and filters out phantom profiles (cross-vendor overrides) — + `orca_filaments.json` dropped from 1035 to 400 clean profiles. +- **Slot without an explicit override now sends `Generic `** + instead of an implicit vendor guess. Library generic profiles have + `compatible_printers: []` (= all printers), so they are always + visible and match reliably. +- **Slot card shows the vendor right after save** without a browser + reload. `poll()` was async, the re-render only happened on the next + tick. +- **ACE dryer toggle threw a 502 even though the dryer worked + (PR #42 by @gangoke):** `setDry` is now fire-and-forget like + `setAutoFeed`. The printer answers on that push topic with + `code: 0` instead of `code: 200`, which the bridge wrongly treated + as an error. + +### Data model / API +- `orca_filaments.json` regenerated: only real vendor profiles and + OrcaFilamentLibrary profiles. Bambu/Polymaker/SUNLU library profiles + in, Qidi cross-bundles out. +- New endpoints: `POST /kx/filament/profiles/user` (ZIP/JSON upload), + `GET /kx/filament/profiles/user` (list user imports), + `DELETE /kx/filament/profiles/user[?vendor=…&name=…]`. Persisted in + `/orca_filaments.user.json` (volume — survives image + updates). + +### Build +- New module `bridge/orca_filaments.py` (shared parser helpers used by + the generator and the import endpoint). +- Dockerfile + release.sh updated to include `orca_filaments.py`. + ## [0.9.18] – 2026-05-31 ### New @@ -10,8 +69,8 @@ sent over the wrong MQTT topic (`slicer/printer/…`) and the printer silently dropped it. It now goes via `web/printer/…` like the Anycubic Slicer Next does (verified by live MQTT sniff + - Workbench-Vue source). **Note:** the currently loaded slot can not - be overwritten during a print — unload it first. + Workbench-Vue source). **Note:** the printer must be idle, and + empty slots can not be labelled. - **Spanish translation reviewed by a native speaker (PR #40 by @pezfisk):** missing accents (impresión, cámara, después, animación, …) and term consistency (Pause → Pausa, Start → diff --git a/Dockerfile b/Dockerfile index 2c2de12..18ac4f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ COPY data/ ./static/ COPY config_loader.py . COPY env_loader.py . COPY kobrax_client.py . +COPY orca_filaments.py . COPY VERSION . COPY anycubic_slicer.crt . COPY anycubic_slicer.key . diff --git a/VERSION b/VERSION index 7a50b68..f752268 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.18 +0.9.19 diff --git a/data/orca_filaments.json b/data/orca_filaments.json index 1fba337..b0761c6 100644 --- a/data/orca_filaments.json +++ b/data/orca_filaments.json @@ -1,1299 +1,4 @@ [ - { - "id": "GFB99", - "name": "Anker Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Anker Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "Anker Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "Anker Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Anker Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Anker Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Anker Generic PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Anker Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL96", - "name": "Anker Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL95", - "name": "Anker Generic PLA+", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Anker Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "Anker Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "Anker Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Anycubic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFA99", - "name": "Anycubic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Anycubic Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Anycubic Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "Anycubic Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "Anycubic Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Anycubic Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Anycubic Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Anycubic Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Anycubic Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "Anycubic Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "Anycubic Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "Anycubic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Anycubic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Anycubic PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Anycubic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Anycubic PLA+", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "Anycubic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Artillery Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Artillery Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFG99", - "name": "Artillery Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Artillery Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Artillery Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFU99", - "name": "Artillery Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "BSFI004", - "name": "Blocks Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "BSFI005", - "name": "Blocks Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "BSFI010", - "name": "Blocks Generic ASA-CF", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "BSFI006", - "name": "Blocks Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "BSFI007", - "name": "Blocks Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "BSFI008", - "name": "Blocks Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "BSFI002", - "name": "Blocks Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "BSFI001", - "name": "Blocks Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "BSFI010", - "name": "Blocks Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "BSFI009", - "name": "Blocks Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "BSFI003", - "name": "Blocks Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "C1 Generic High Flow PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "C1 Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "C1 Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Chuanying ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Chuanying Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Chuanying Generic HIPS", - "vendor": "Generic", - "type": "HIPS", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying Generic HS PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "Chuanying Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Chuanying Generic PETG-CF10", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying Generic PLA-CF10", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying Generic PLA-Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Chuanying Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFG99", - "name": "Chuanying Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying HS PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "Chuanying PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Chuanying PLA-SILK", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Comgrow Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFG99", - "name": "Comgrow Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Comgrow Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Comgrow T300 PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "CoPrint Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "CoPrint Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "CoPrint Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "CoPrint Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Creality Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Creality Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB98", - "name": "Creality Generic ASA-CF", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN98", - "name": "Creality Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Creality Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Creality Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Creality Generic PETG-CF", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality Generic PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality Generic PLA Matte", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality Generic PLA Wood", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Creality Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFU99", - "name": "Creality Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality HF Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Creality HF Generic Speed PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "DeltaMaker Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "DeltaMaker Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "DeltaMaker Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Dremel Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "DFL99", - "name": "Désactivé", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Elegoo PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge ABS Basic", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge ABS-CF", - "vendor": "Generic", - "type": "ABS-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge ASA Basic", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge ASA-CF", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge Generic HIPS", - "vendor": "Generic", - "type": "HIPS", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge Generic HS PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge Generic PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge Generic PETG-CF10", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge Generic PLA-CF10", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge Generic PLA-SILK", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge Generic PLA-Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge HIPS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge HS PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge HS PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge HS PLA Burnt Ti", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PAHT-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FlashForge PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge PETG Basic", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge PETG Pro", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge PETG Transparent", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Basic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Buint Ti", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Color Change", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Galaxy", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Luminous", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Matte", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Metal", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Pro", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "FFG01", - "name": "Flashforge PLA Sparkle", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FlashForge PPS", - "vendor": "Generic", - "type": "PPS", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PPS", - "vendor": "Generic", - "type": "PPS", - "color": "" - }, - { - "id": "GFB99", - "name": "FlashForge PPS-CF", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Flashforge PPS-CF", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge TPU 65D", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "Flashforge TPU 95A", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "FLSun Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "FLSun Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "FLSun Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "FLSun Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "FLSun Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "FLSun Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "FLSun Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "FLSun Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "FLSun Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "FLSun S1 ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "FLSun S1 ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFG99", - "name": "FLSun S1 PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun S1 PLA Generic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun S1 PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun S1 PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "FLSun S1 TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "FLSun T1 ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "FLSun T1 ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFG99", - "name": "FLSun T1 PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun T1 PLA Generic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun T1 PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "FLSun T1 PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "FLSun T1 TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "FlyingBear Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFN98", - "name": "FlyingBear Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "FlyingBear Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "FlyingBear Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "FlyingBear Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "FlyingBear Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PAHT-CF", - "vendor": "Generic", - "type": "PAHT-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PET-CF", - "vendor": "Generic", - "type": "PET-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic S-Multi", - "vendor": "Generic", - "type": "PET-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic S-PAHT", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock PAHT", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock PAHT-CF", - "vendor": "Generic", - "type": "PAHT-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock PET", - "vendor": "Generic", - "type": "PET", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock PET-CF", - "vendor": "Generic", - "type": "PET-CF", - "color": "" - }, - { - "id": "OGFB99", - "name": "Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL504", - "name": "Generic ABS HT", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, { "id": "OGFB98", "name": "Generic ASA", @@ -1302,7 +7,7 @@ "color": "" }, { - "id": "GFS97", + "id": "OGFS97", "name": "Generic BVOH", "vendor": "Generic", "type": "BVOH", @@ -1316,2217 +21,117 @@ "color": "" }, { - "id": "GFR99", + "id": "OGFR99", "name": "Generic EVA", "vendor": "Generic", "type": "EVA", "color": "" }, { - "id": "GFS98", + "id": "OGFS98", "name": "Generic HIPS", "vendor": "Generic", "type": "HIPS", "color": "" }, { - "id": "OGFN99", - "name": "Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "OGFN98", - "name": "Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "Generic PCCF @E3NG v1.2S", - "name": "Generic PCCF", - "vendor": "Generic", - "type": "PC-CF", - "color": "" - }, - { - "id": "GFG97", + "id": "OGFG97", "name": "Generic PCTG", "vendor": "Generic", "type": "PCTG", "color": "" }, { - "id": "GFP99", + "id": "OGFP99", "name": "Generic PE", "vendor": "Generic", "type": "PE", "color": "" }, { - "id": "GFP98", + "id": "OGFP99", "name": "Generic PE-CF", "vendor": "Generic", - "type": "PE-CF", + "type": "PE", "color": "" }, { - "id": "GFB99", - "name": "Generic PET", - "vendor": "Generic", - "type": "PET", - "color": "" - }, - { - "id": "GFG99", - "name": "Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Generic PETG Basic", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG96", - "name": "Generic PETG HF", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Generic PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFG99", - "name": "Generic PETG-CF10", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFR98", + "id": "OGFR98", "name": "Generic PHA", "vendor": "Generic", "type": "PHA", "color": "" }, { - "id": "GFL99", + "id": "OGFL99", "name": "Generic PLA", "vendor": "Generic", "type": "PLA", "color": "" }, { - "id": "GFL95", + "id": "OGFL95", "name": "Generic PLA High Speed", "vendor": "Generic", "type": "PLA", "color": "" }, { - "id": "GFL96", + "id": "OGFL99", + "name": "Generic PLA Matte", + "vendor": "Generic", + "type": "PLA", + "color": "" + }, + { + "id": "OGFL96", "name": "Generic PLA Silk", "vendor": "Generic", "type": "PLA", "color": "" }, { - "id": "GFL99", - "name": "Generic PLA+", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", + "id": "OGFL98", "name": "Generic PLA-CF", "vendor": "Generic", "type": "PLA-CF", "color": "" }, { - "id": "GFL99", - "name": "Generic PLA-CF10", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFP97", + "id": "OGFP97", "name": "Generic PP", "vendor": "Generic", "type": "PP", "color": "" }, { - "id": "GFP96", + "id": "OGFP97", "name": "Generic PP-CF", "vendor": "Generic", "type": "PP-CF", "color": "" }, { - "id": "GFP95", + "id": "OGFP97", "name": "Generic PP-GF", "vendor": "Generic", "type": "PP-GF", "color": "" }, { - "id": "GFN97", - "name": "Generic PPA-CF", - "vendor": "Generic", - "type": "PPA-CF", - "color": "" - }, - { - "id": "GFN96", - "name": "Generic PPA-GF", - "vendor": "Generic", - "type": "PPA-GF", - "color": "" - }, - { - "id": "GFT97", - "name": "Generic PPS", - "vendor": "Generic", - "type": "PPS", - "color": "" - }, - { - "id": "GFT98", - "name": "Generic PPS-CF", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "GFS99", + "id": "OGFS99", "name": "Generic PVA", "vendor": "Generic", "type": "PVA", "color": "" }, { - "id": "BFLSBS99", + "id": "OFLSBS99", "name": "Generic SBS", "vendor": "Generic", "type": "SBS", "color": "" }, - { - "id": "GFU99", - "name": "Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "Generic TPU 85A", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "QD_1_0_50", - "name": "Generic TPU 95A", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFU98", - "name": "Generic TPU for AMS", - "vendor": "Generic", - "type": "TPU-AMS", - "color": "" - }, - { - "id": "GFB99", - "name": "InfiMech Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFN98", - "name": "InfiMech Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "InfiMech Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "InfiMech Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "InfiMech Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "InfiMech Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Lulzbot 2.85mm ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFG99", - "name": "Lulzbot 2.85mm PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Lulzbot 2.85mm PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "MM Generic PEEK", - "vendor": "Generic", - "type": "PEEK", - "color": "" - }, - { - "id": "GFB99", - "name": "OrcaArena Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "OrcaArena Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "OrcaArena Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "OrcaArena Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "OrcaArena Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "OrcaArena Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "OrcaArena Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFA05", - "name": "OrcaArena Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "OrcaArena Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "OrcaArena Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "OrcaArena Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFN99", - "name": "PA6 CF20 (Performance)", - "vendor": "Generic", - "type": "PA6-CF", - "color": "" - }, - { - "id": "GFSL99", - "name": "Peopoly Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFPETG-1", - "name": "Peopoly Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Peopoly Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "PETG ESD (Performance)", - "vendor": "Generic", - "type": "PETG-ESD", - "color": "" - }, - { - "id": "GFL99", - "name": "Phrozen PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1393866034", - "name": "PolyLite Dual PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1393866034", - "name": "PolyLite J1 PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1393866034", - "name": "PolyLite PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Polymaker CoPA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFL99", - "name": "Polymaker PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "37895926870", - "name": "PolyTerra PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFN99", - "name": "PPS Carbone (Performance)", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "Prusa Generic ABS @CORE One 0.6", - "name": "Prusa Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99_6", - "name": "Prusa Generic ABS HF", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98_5", - "name": "Prusa Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB98_6", - "name": "Prusa Generic ASA HF", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFU99", - "name": "Prusa Generic FLEX", - "vendor": "Generic", - "type": "FLEX", - "color": "" - }, - { - "id": "GFN99_4", - "name": "Prusa Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98_4", - "name": "Prusa Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99_4", - "name": "Prusa Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFC99_5", - "name": "Prusa Generic PC HF", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "Prusa Generic PETG @CORE One 0.6", - "name": "Prusa Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99_6", - "name": "Prusa Generic PETG HF", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "Prusa Generic PLA @CORE One 0.6", - "name": "Prusa Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99_6", - "name": "Prusa Generic PLA HF", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "Prusa Generic PLA Silk @CORE One 0.6", - "name": "Prusa Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98_5", - "name": "Prusa Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99_4", - "name": "Prusa Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFS99_5", - "name": "Prusa Generic PVA HF", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "Prusa Generic TPU @CORE One 0.6", - "name": "Prusa Generic TPU", - "vendor": "Generic", - "type": "FLEX", - "color": "" - }, - { - "id": "GFU99_3", - "name": "Prusa Generic TPU HF", - "vendor": "Generic", - "type": "FLEX", - "color": "" - }, - { - "id": "GFN98", - "name": "Prusament PA-CF", - "vendor": "Generic", - "type": "PA11-CF", - "color": "" - }, - { - "id": "GFRH06", - "name": "Prusament PC-CF", - "vendor": "Generic", - "type": "PC-CF", - "color": "" - }, - { - "id": "GFS98", - "name": "Prusament PVB", - "vendor": "Generic", - "type": "PVB", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS Odorless", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS Rapido", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS Rapido Metal", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS-GF", - "vendor": "Generic", - "type": "ABS-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS-GF10", - "vendor": "Generic", - "type": "ABS-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ABS-GF25", - "vendor": "Generic", - "type": "ABS-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi ASA-Aero", - "vendor": "Generic", - "type": "ASA-AERO", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI ASA-CF", - "vendor": "Generic", - "type": "ASA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "Qidi Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "Qidi Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Qidi Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Qidi Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Qidi Generic PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFL99", - "name": "Qidi Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Qidi Generic PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFA05", - "name": "Qidi Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Qidi Generic PLA+", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Qidi Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "Qidi Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi Generic TPU 95A", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PA-Ultra", - "vendor": "Generic", - "type": "UltraPA", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PA12-CF", - "vendor": "Generic", - "type": "PA12-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PAHT-CF", - "vendor": "Generic", - "type": "PAHT-CF", - "color": "" - }, - { - "id": "GFL98", - "name": "QIDI PAHT-GF", - "vendor": "Generic", - "type": "PAHT-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi PC-ABS-FR", - "vendor": "Generic", - "type": "PC-ABS-FR", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PET-CF", - "vendor": "Generic", - "type": "PET-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PET-GF", - "vendor": "Generic", - "type": "PET-GF", - "color": "" - }, - { - "id": "GFG99", - "name": "QIDI PETG Basic", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "QIDI PETG Rapido", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "QIDI PETG Tough", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "QIDI PETG Translucent", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PETG-GF", - "vendor": "Generic", - "type": "PETG-GF", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Basic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Matte Basic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Rapido", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Rapido Matte", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Rapido Metal", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI PLA Rapido Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "QIDI PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFL98", - "name": "Qidi PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PPS-CF", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI PPS-GF", - "vendor": "Generic", - "type": "PPS-GF", - "color": "" - }, - { - "id": "QD_0_1_32", - "name": "QIDI Support For PAHT", - "vendor": "Generic", - "type": "PAHT-S", - "color": "" - }, - { - "id": "QD_0_1_33", - "name": "QIDI Support For PET/PA", - "vendor": "Generic", - "type": "PA-S", - "color": "" - }, - { - "id": "GFB99", - "name": "Qidi TPU 95A-HF", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI TPU-Aero", - "vendor": "Generic", - "type": "TPU-AERO", - "color": "" - }, - { - "id": "GFB99", - "name": "QIDI UltraPA-CF25", - "vendor": "Generic", - "type": "UltraPA-CF25", - "color": "" - }, - { - "id": "GFL99", - "name": "QIDI WOOD Rapido", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "RatRig BigNozzle ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "RatRig BigNozzle ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFC99", - "name": "RatRig BigNozzle PCTG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "RatRig BigNozzle PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "RatRig BigNozzle PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "RatRig BigNozzle TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "RatRig Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "RatRig Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "RatRig Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "RatRig Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "RatRig Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFC99", - "name": "RatRig Generic PCTG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "RatRig Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "RatRig Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "RatRig Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "RatRig Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "RatRig Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "re3D Greengate rPETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "re3D PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "re3D PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "re3D PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFG99", - "name": "re3D rPP", - "vendor": "Generic", - "type": "PP", - "color": "" - }, - { - "id": "GFB99", - "name": "SecKit Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "SecKit Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "SecKit Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "SecKit Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "SecKit Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "SecKit Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "SecKit Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "SecKit Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "SecKit Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "SecKit Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "3811508002", - "name": "Snapmaker ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "1682237920", - "name": "Snapmaker ABS Benchy", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "2742961008", - "name": "Snapmaker ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "168223792", - "name": "Snapmaker Dual ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "168223792", - "name": "Snapmaker Dual ABS Benchy", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "1247172706", - "name": "Snapmaker Dual ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "1207881278", - "name": "Snapmaker Dual Breakaway", - "vendor": "Generic", - "type": "Breakaway Support", - "color": "" - }, - { - "id": "3493177425", - "name": "Snapmaker Dual PA-CF", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "2128577941", - "name": "Snapmaker Dual PET", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "2209001062", - "name": "Snapmaker Dual PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "1042511226", - "name": "Snapmaker Dual PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "1417031127", - "name": "Snapmaker Dual PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "200803790", - "name": "Snapmaker Dual PLA Eco", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "3503790988", - "name": "Snapmaker Dual PLA Matte", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "2029994346", - "name": "Snapmaker Dual PLA Metal", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1181363872", - "name": "Snapmaker Dual PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1702147325", - "name": "Snapmaker Dual PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "3104636980", - "name": "Snapmaker Dual PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "2971656290", - "name": "Snapmaker Dual TPE", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "2971656290", - "name": "Snapmaker Dual TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "2971656290", - "name": "Snapmaker Dual TPU High-Flow", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "1223824394", - "name": "Snapmaker J1 ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "1223824394", - "name": "Snapmaker J1 ABS Benchy", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "144877656", - "name": "Snapmaker J1 ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "3492897526", - "name": "Snapmaker J1 Breakaway", - "vendor": "Generic", - "type": "Breakaway Support", - "color": "" - }, - { - "id": "1210173120", - "name": "Snapmaker J1 PA-CF", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "1009481135", - "name": "Snapmaker J1 PET", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "1172603684", - "name": "Snapmaker J1 PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "4235401834", - "name": "Snapmaker J1 PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "377675245", - "name": "Snapmaker J1 PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "3383257822", - "name": "Snapmaker J1 PLA Eco", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1192769348", - "name": "Snapmaker J1 PLA Matte", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "4012961186", - "name": "Snapmaker J1 PLA Metal", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1528786603", - "name": "Snapmaker J1 PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "3806593857", - "name": "Snapmaker J1 PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "4227461134", - "name": "Snapmaker J1 PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "4092268632", - "name": "Snapmaker J1 TPE", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "4092268632", - "name": "Snapmaker J1 TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "4092268632", - "name": "Snapmaker J1 TPU High-Flow", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "34931774250", - "name": "Snapmaker PA-CF", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "2128577941", - "name": "Snapmaker PET", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "1895495477", - "name": "Snapmaker PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "10425112260", - "name": "Snapmaker PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "14170311270", - "name": "Snapmaker PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "2008037900", - "name": "Snapmaker PLA Eco", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "20299943460", - "name": "Snapmaker PLA Metal", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "1655727393", - "name": "Snapmaker PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "17021473250", - "name": "Snapmaker PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "1344609062", - "name": "Snapmaker PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "29716562900", - "name": "Snapmaker TPE", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "29716562900", - "name": "Snapmaker TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "297165629001", - "name": "Snapmaker TPU 95A", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "29716562900", - "name": "Snapmaker TPU High-Flow", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 ACE ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 ACE PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 ACE PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 ACE TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 Plus ACE ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 Plus ACE PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 Plus ACE PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV06 Plus ACE TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV07 PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV08 ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV08 PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV08 PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol SV08 TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PETG HS Nozzle", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PLA Basic", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PLA Basic HS Nozzle", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero PLA Silk HS Nozzle", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Sovol Zero TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL99", - "name": "SUNLU PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFB99", - "name": "Tiertime Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Tiertime Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFS97", - "name": "Tiertime Generic BVOH", - "vendor": "Generic", - "type": "BVOH", - "color": "" - }, - { - "id": "GFR99", - "name": "Tiertime Generic EVA", - "vendor": "Generic", - "type": "EVA", - "color": "" - }, - { - "id": "GFS98", - "name": "Tiertime Generic HIPS", - "vendor": "Generic", - "type": "HIPS", - "color": "" - }, - { - "id": "GFN99", - "name": "Tiertime Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "Tiertime Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Tiertime Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG97", - "name": "Tiertime Generic PCTG", - "vendor": "Generic", - "type": "PCTG", - "color": "" - }, - { - "id": "GFP99", - "name": "Tiertime Generic PE", - "vendor": "Generic", - "type": "PE", - "color": "" - }, - { - "id": "GFP98", - "name": "Tiertime Generic PE-CF", - "vendor": "Generic", - "type": "PE-CF", - "color": "" - }, - { - "id": "GFG99", - "name": "Tiertime Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Tiertime Generic PETG-CF", - "vendor": "Generic", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFR98", - "name": "Tiertime Generic PHA", - "vendor": "Generic", - "type": "PHA", - "color": "" - }, - { - "id": "GFL99", - "name": "Tiertime Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL95", - "name": "Tiertime Generic PLA High Speed", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL96", - "name": "Tiertime Generic PLA Silk", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Tiertime Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFP97", - "name": "Tiertime Generic PP", - "vendor": "Generic", - "type": "PP", - "color": "" - }, - { - "id": "GFP96", - "name": "Tiertime Generic PP-CF", - "vendor": "Generic", - "type": "PP-CF", - "color": "" - }, - { - "id": "GFP95", - "name": "Tiertime Generic PP-GF", - "vendor": "Generic", - "type": "PP-GF", - "color": "" - }, - { - "id": "GFN97", - "name": "Tiertime Generic PPA-CF", - "vendor": "Generic", - "type": "PPA-CF", - "color": "" - }, - { - "id": "GFN96", - "name": "Tiertime Generic PPA-GF", - "vendor": "Generic", - "type": "PPA-GF", - "color": "" - }, - { - "id": "GFT97", - "name": "Tiertime Generic PPS", - "vendor": "Generic", - "type": "PPS", - "color": "" - }, - { - "id": "GFT98", - "name": "Tiertime Generic PPS-CF", - "vendor": "Generic", - "type": "PPS-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "Tiertime Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFL99", - "name": "Tiertime Generic SBS", - "vendor": "Generic", - "type": "SBS", - "color": "" - }, - { - "id": "GFU99", - "name": "Tiertime Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFG99", - "name": "Tinmorry PETG-ECO", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFU99", - "name": "TwoTrees Generic 95A TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFL100", - "name": "TwoTrees Generic HS PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic ABS Ultra", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic ABS Ultra (Performance)", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic ASA Ultra", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic ASA Ultra (Performance)", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFU99", - "name": "Volumic FLEX93 Ultra", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFU99", - "name": "Volumic FLEX93 Ultra (Performance)", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, - { - "id": "GFN99", - "name": "Volumic NYLON Ultra", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN99", - "name": "Volumic NYLON Ultra (Performance)", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFC99", - "name": "Volumic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFC99", - "name": "Volumic PC (Performance)", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Volumic PCTG Ultra (Performance)", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Volumic PETG Ultra", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG99", - "name": "Volumic PETG Ultra (Performance)", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Volumic PETG Ultra carbone", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFG98", - "name": "Volumic PETG Ultra carbone (Performance)", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Volumic PLA Ultra", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Volumic PLA Ultra (Performance)", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic PP Ultra", - "vendor": "Generic", - "type": "PP", - "color": "" - }, - { - "id": "GFB99", - "name": "Volumic PP Ultra (Performance)", - "vendor": "Generic", - "type": "PP", - "color": "" - }, - { - "id": "GFS99", - "name": "Volumic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFS99", - "name": "Volumic PVA-BVOH (Performance)", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFL99", - "name": "Volumic UNIVERSAL Ultra", - "vendor": "Generic", - "type": "UNIV", - "color": "" - }, - { - "id": "GFL99", - "name": "Volumic UNIVERSAL Ultra (Performance)", - "vendor": "Generic", - "type": "UNIV", - "color": "" - }, - { - "id": "GFB99", - "name": "Vzbot Generic ABS", - "vendor": "Generic", - "type": "ABS", - "color": "" - }, - { - "id": "GFB98", - "name": "Vzbot Generic ASA", - "vendor": "Generic", - "type": "ASA", - "color": "" - }, - { - "id": "GFN99", - "name": "Vzbot Generic PA", - "vendor": "Generic", - "type": "PA", - "color": "" - }, - { - "id": "GFN98", - "name": "Vzbot Generic PA-CF", - "vendor": "Generic", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Vzbot Generic PC", - "vendor": "Generic", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Vzbot Generic PETG", - "vendor": "Generic", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Vzbot Generic PLA", - "vendor": "Generic", - "type": "PLA", - "color": "" - }, - { - "id": "GFL98", - "name": "Vzbot Generic PLA-CF", - "vendor": "Generic", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS99", - "name": "Vzbot Generic PVA", - "vendor": "Generic", - "type": "PVA", - "color": "" - }, - { - "id": "GFU99", - "name": "Vzbot Generic TPU", - "vendor": "Generic", - "type": "TPU", - "color": "" - }, { "id": "GFB00", "name": "Afinia ABS", @@ -3605,14 +210,14 @@ "color": "" }, { - "id": "GFB99", + "id": "GFABS", "name": "Anycubic ABS", "vendor": "Anycubic", "type": "ABS", "color": "" }, { - "id": "GFA99", + "id": "GFASA", "name": "Anycubic ASA", "vendor": "Anycubic", "type": "ASA", @@ -3626,28 +231,28 @@ "color": "" }, { - "id": "GFG99", + "id": "GFPETG", "name": "Anycubic PETG", "vendor": "Anycubic", "type": "PETG", "color": "" }, { - "id": "GFL92", + "id": "GFPLA", "name": "Anycubic PLA", "vendor": "Anycubic", "type": "PLA", "color": "" }, { - "id": "GFL98", + "id": "GFPLA Glow", "name": "Anycubic PLA Glow", "vendor": "Anycubic", "type": "PLA", "color": "" }, { - "id": "GFL96", + "id": "GFPLA High Speed", "name": "Anycubic PLA High Speed", "vendor": "Anycubic", "type": "PLA", @@ -3661,7 +266,7 @@ "color": "" }, { - "id": "GFL95", + "id": "GFPLA Matte", "name": "Anycubic PLA Matte", "vendor": "Anycubic", "type": "PLA", @@ -3675,7 +280,7 @@ "color": "" }, { - "id": "GFL99", + "id": "GFPLA Silk", "name": "Anycubic PLA Silk", "vendor": "Anycubic", "type": "PLA", @@ -3689,7 +294,7 @@ "color": "" }, { - "id": "GFL93", + "id": "GFPLA+", "name": "Anycubic PLA+", "vendor": "Anycubic", "type": "PLA", @@ -3933,13 +538,6 @@ "type": "PET-CF", "color": "" }, - { - "id": "GFG99", - "name": "Bambu PETG", - "vendor": "Bambu Lab", - "type": "PETG", - "color": "" - }, { "id": "OGFG00", "name": "Bambu PETG Basic", @@ -3968,13 +566,6 @@ "type": "PETG-CF", "color": "" }, - { - "id": "GFL99", - "name": "Bambu PLA", - "vendor": "Bambu Lab", - "type": "PLA", - "color": "" - }, { "id": "OGFA11", "name": "Bambu PLA Aero", @@ -4017,13 +608,6 @@ "type": "PLA", "color": "" }, - { - "id": "GFA18", - "name": "Bambu PLA Lite", - "vendor": "Bambu Lab", - "type": "PLA", - "color": "" - }, { "id": "OGFA07", "name": "Bambu PLA Marble", @@ -4073,20 +657,6 @@ "type": "PLA", "color": "" }, - { - "id": "GFA10", - "name": "Bambu PLA Tough+", - "vendor": "Bambu Lab", - "type": "PLA", - "color": "" - }, - { - "id": "GFA17", - "name": "Bambu PLA Translucent", - "vendor": "Bambu Lab", - "type": "PLA", - "color": "" - }, { "id": "OGFA16", "name": "Bambu PLA Wood", @@ -4108,13 +678,6 @@ "type": "PPA-CF", "color": "" }, - { - "id": "OGFT02", - "name": "Bambu PPS-CF", - "vendor": "Bambu Lab", - "type": "PPS-CF", - "color": "" - }, { "id": "OGFS04", "name": "Bambu PVA", @@ -4164,20 +727,6 @@ "type": "PLA", "color": "" }, - { - "id": "GFU04", - "name": "Bambu TPU 85A", - "vendor": "Bambu Lab", - "type": "TPU", - "color": "" - }, - { - "id": "GFU03", - "name": "Bambu TPU 90A", - "vendor": "Bambu Lab", - "type": "TPU", - "color": "" - }, { "id": "OGFU01", "name": "Bambu TPU 95A", @@ -4192,321 +741,6 @@ "type": "TPU", "color": "" }, - { - "id": "GFU02", - "name": "Bambu TPU for AMS", - "vendor": "Bambu Lab", - "type": "TPU-AMS", - "color": "" - }, - { - "id": "BABB00", - "name": "BETA ABS", - "vendor": "BETA", - "type": "ABS", - "color": "" - }, - { - "id": "BASB00", - "name": "BETA ASA", - "vendor": "BETA", - "type": "ASA", - "color": "" - }, - { - "id": "BHIB00", - "name": "BETA HIPS", - "vendor": "BETA", - "type": "HIPS", - "color": "" - }, - { - "id": "BPAB00", - "name": "BETA PAHT-CF", - "vendor": "BETA", - "type": "PA-CF", - "color": "" - }, - { - "id": "BPBB00", - "name": "BETA PEBA 90A", - "vendor": "BETA", - "type": "TPU", - "color": "" - }, - { - "id": "BPGB00", - "name": "BETA PETG", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB02", - "name": "BETA PETG Fluorescence", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB03", - "name": "BETA PETG Glitter", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB04", - "name": "BETA PETG Glow", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB05", - "name": "BETA PETG Gradient", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB01", - "name": "BETA PETG Heat Color Change", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB06", - "name": "BETA PETG HF", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB07", - "name": "BETA PETG Marble", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB08", - "name": "BETA PETG Matte", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB09", - "name": "BETA PETG Metallic", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB10", - "name": "BETA PETG Transparent", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB11", - "name": "BETA PETG UV Color Change", - "vendor": "BETA", - "type": "PETG", - "color": "" - }, - { - "id": "BPGB12", - "name": "BETA PETG-CF", - "vendor": "BETA", - "type": "PETG-CF", - "color": "" - }, - { - "id": "BPGB13", - "name": "BETA PETG-GF", - "vendor": "BETA", - "type": "PETG-CF", - "color": "" - }, - { - "id": "BPLB00", - "name": "BETA PLA Basic", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB02", - "name": "BETA PLA Chameleon", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB04", - "name": "BETA PLA Fluorescence", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB05", - "name": "BETA PLA Glitter", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB06", - "name": "BETA PLA Glow", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB07", - "name": "BETA PLA Gradient", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB03", - "name": "BETA PLA Heat Color Change", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB20", - "name": "BETA PLA High Speed", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB18", - "name": "BETA PLA High Temp", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB08", - "name": "BETA PLA Marble", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB09", - "name": "BETA PLA Matte", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB10", - "name": "BETA PLA Metal", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB11", - "name": "BETA PLA Metallic", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB12", - "name": "BETA PLA PRO", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB13", - "name": "BETA PLA Silk", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB01", - "name": "BETA PLA Silk+", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB14", - "name": "BETA PLA Transparent", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB15", - "name": "BETA PLA UV Color Change", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB19", - "name": "BETA PLA Wood", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB16", - "name": "BETA PLA Youth", - "vendor": "BETA", - "type": "PLA", - "color": "" - }, - { - "id": "BPLB17", - "name": "BETA PLA-CF", - "vendor": "BETA", - "type": "PLA-CF", - "color": "" - }, - { - "id": "BTUB00", - "name": "BETA TPU 90A", - "vendor": "BETA", - "type": "TPU", - "color": "" - }, - { - "id": "BTUB02", - "name": "BETA TPU 95A", - "vendor": "BETA", - "type": "TPU", - "color": "" - }, - { - "id": "BTUB03", - "name": "BETA TPU 98A", - "vendor": "BETA", - "type": "TPU", - "color": "" - }, - { - "id": "BTUB01", - "name": "BETA TPU Matte", - "vendor": "BETA", - "type": "TPU", - "color": "" - }, { "id": "CXABSB01", "name": "COEX ABS", @@ -4535,13 +769,6 @@ "type": "PA-CF", "color": "" }, - { - "id": "CXPAUB21", - "name": "COEX NYLEX UNFILLED", - "vendor": "COEX 3D", - "type": "PA", - "color": "" - }, { "id": "CXPCTB15", "name": "COEX PCTG PRIME", @@ -5424,6 +1651,41 @@ "type": "ABS", "color": "" }, + { + "id": "GFB99", + "name": "FlyingBear Generic ABS", + "vendor": "FlyingBear", + "type": "ABS", + "color": "" + }, + { + "id": "GFN98", + "name": "FlyingBear Generic PA-CF", + "vendor": "FlyingBear", + "type": "PA-CF", + "color": "" + }, + { + "id": "GFC99", + "name": "FlyingBear Generic PC", + "vendor": "FlyingBear", + "type": "PC", + "color": "" + }, + { + "id": "GFG99", + "name": "FlyingBear Generic PETG", + "vendor": "FlyingBear", + "type": "PETG", + "color": "" + }, + { + "id": "GFU99", + "name": "FlyingBear Generic TPU", + "vendor": "FlyingBear", + "type": "TPU", + "color": "" + }, { "id": "GFN98", "name": "FlyingBear PA-CF", @@ -5488,59 +1750,59 @@ "color": "" }, { - "id": "GFB99", - "name": "Flashforge ASA-CF", - "vendor": "FusRock", - "type": "ASA", + "id": "OGFB99", + "name": "Generic ABS", + "vendor": "FlyingBear", + "type": "ABS", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PA12-CF", - "vendor": "FusRock", + "id": "OGFN99", + "name": "Generic PA", + "vendor": "FlyingBear", + "type": "PA", + "color": "" + }, + { + "id": "OGFN98", + "name": "Generic PA-CF", + "vendor": "FlyingBear", "type": "PA-CF", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PA6-CF", - "vendor": "FusRock", - "type": "PA6-CF", + "id": "OGFC99", + "name": "Generic PC", + "vendor": "FlyingBear", + "type": "PC", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PA66-CF", - "vendor": "FusRock", - "type": "PA-CF", + "id": "OGFG99", + "name": "Generic PETG", + "vendor": "FlyingBear", + "type": "PETG", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PET-CF", - "vendor": "FusRock", - "type": "PET-CF", + "id": "OGFG99", + "name": "Generic PETG HF", + "vendor": "FlyingBear", + "type": "PETG", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PPA-CF", - "vendor": "FusRock", - "type": "PPA-CF", + "id": "OGFG99", + "name": "Generic PETG-CF", + "vendor": "FlyingBear", + "type": "PETG", "color": "" }, { - "id": "GFB99", - "name": "Flashforge PPA-GF", - "vendor": "FusRock", - "type": "PPA-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "Flashforge PPS-CF", - "vendor": "FusRock", - "type": "PPS-CF", + "id": "OGFU99", + "name": "Generic TPU", + "vendor": "FlyingBear", + "type": "TPU", "color": "" }, { @@ -5550,55 +1812,6 @@ "type": "ABS-GF", "color": "" }, - { - "id": "GFB99", - "name": "FusRock Generic NexPA-CF25", - "vendor": "FusRock", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PAHT-CF", - "vendor": "FusRock", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PAHT-GF", - "vendor": "FusRock", - "type": "PAHT-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PET-CF", - "vendor": "FusRock", - "type": "PET-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic PET-GF", - "vendor": "FusRock", - "type": "PET-GF", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic S-Multi", - "vendor": "FusRock", - "type": "S-Multi", - "color": "" - }, - { - "id": "GFB99", - "name": "FusRock Generic S-PAHT", - "vendor": "FusRock", - "type": "S-PAHT", - "color": "" - }, { "id": "OGFGG300", "name": "GreenGate3D PETG", @@ -5606,34 +1819,6 @@ "type": "PETG", "color": "" }, - { - "id": "GFB99", - "name": "HATCHBOX ABS", - "vendor": "HATCHBOX", - "type": "ABS", - "color": "" - }, - { - "id": "GFG99", - "name": "HATCHBOX PETG", - "vendor": "HATCHBOX", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "HATCHBOX PLA", - "vendor": "HATCHBOX", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "FlyingBear PLA Hyper", - "vendor": "InfiMech", - "type": "PLA", - "color": "" - }, { "id": "GFB99", "name": "InfiMech ABS", @@ -5697,104 +1882,6 @@ "type": "TPU", "color": "" }, - { - "id": "IQM1", - "name": "Fiberthree PACF Pro P1", - "vendor": "iQ Materials", - "type": "PACF Pro", - "color": "#000000" - }, - { - "id": "IQM7", - "name": "Fiberthree PACF Pro P2", - "vendor": "iQ Materials", - "type": "PACF Pro", - "color": "#000000" - }, - { - "id": "IQM1", - "name": "Grauts HPP4GF25 P1", - "vendor": "iQ Materials", - "type": "HPP4GF25", - "color": "#000000" - }, - { - "id": "IQM2", - "name": "Material4Print ABS Natur P1", - "vendor": "iQ Materials", - "type": "ABS Material4Print Natur", - "color": "#FFFFFF" - }, - { - "id": "IQM3", - "name": "Polymaker PETG Polymax black P1", - "vendor": "iQ Materials", - "type": "PETG Polymax", - "color": "#000000" - }, - { - "id": "IQM1011", - "name": "VXL90 TiQ2 P2", - "vendor": "iQ Materials", - "type": "VXL90 Xioneer", - "color": "#FFFFFF" - }, - { - "id": "LHF_abs", - "name": "LHS ABS", - "vendor": "LH Stinger", - "type": "ASA", - "color": "" - }, - { - "id": "LHF_asa", - "name": "LHS ASA", - "vendor": "LH Stinger", - "type": "ASA", - "color": "" - }, - { - "id": "LHF_pccf", - "name": "LHS PC CF", - "vendor": "LH Stinger", - "type": "PC", - "color": "" - }, - { - "id": "LHF_pctg", - "name": "LHS PCTG", - "vendor": "LH Stinger", - "type": "PCTG", - "color": "" - }, - { - "id": "LHF_petg", - "name": "LHS PETG", - "vendor": "LH Stinger", - "type": "PETG", - "color": "" - }, - { - "id": "LHF_pla", - "name": "LHS PLA", - "vendor": "LH Stinger", - "type": "PLA", - "color": "" - }, - { - "id": "LHF_ptpu_pl", - "name": "LHS TPU", - "vendor": "LH Stinger", - "type": "TPU", - "color": "" - }, - { - "id": "LHF_ftpuf", - "name": "LHS TPU Foamy 78A", - "vendor": "LH Stinger", - "type": "TPU", - "color": "" - }, { "id": "NIT01", "name": "NIT ABS", @@ -5823,202 +1910,6 @@ "type": "PLA", "color": "" }, - { - "id": "GFB00", - "name": "Arena ABS", - "vendor": "Orca Arena", - "type": "ABS", - "color": "" - }, - { - "id": "GFN03", - "name": "Arena PA-CF", - "vendor": "Orca Arena", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFN04", - "name": "Arena PAHT-CF", - "vendor": "Orca Arena", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC00", - "name": "Arena PC", - "vendor": "Orca Arena", - "type": "PC", - "color": "" - }, - { - "id": "GFT01", - "name": "Arena PET-CF", - "vendor": "Orca Arena", - "type": "PET-CF", - "color": "" - }, - { - "id": "GFG00", - "name": "Arena PETG Basic", - "vendor": "Orca Arena", - "type": "PETG", - "color": "" - }, - { - "id": "GFG50", - "name": "Arena PETG-CF", - "vendor": "Orca Arena", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFA00", - "name": "Arena PLA Basic", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA03", - "name": "Arena PLA Impact", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA07", - "name": "Arena PLA Marble", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA01", - "name": "Arena PLA Matte", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA02", - "name": "Arena PLA Metal", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA05", - "name": "Arena PLA Silk", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA08", - "name": "Arena PLA Sparkle", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA09", - "name": "Arena PLA Tough", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFA50", - "name": "Arena PLA-CF", - "vendor": "Orca Arena", - "type": "PLA-CF", - "color": "" - }, - { - "id": "GFS01", - "name": "Arena Support G", - "vendor": "Orca Arena", - "type": "PA", - "color": "" - }, - { - "id": "GFS00", - "name": "Arena Support W", - "vendor": "Orca Arena", - "type": "PLA", - "color": "" - }, - { - "id": "GFU01", - "name": "Arena TPU 95A", - "vendor": "Orca Arena", - "type": "TPU", - "color": "" - }, - { - "id": "GFG98", - "name": "OrcaArena Generic PETG-CF", - "vendor": "Orca Arena", - "type": "PETG-CF", - "color": "" - }, - { - "id": "GFB99", - "name": "Other ABS", - "vendor": "Other", - "type": "ABS", - "color": "" - }, - { - "id": "GFN98", - "name": "Other PA-CF", - "vendor": "Other", - "type": "PA-CF", - "color": "" - }, - { - "id": "GFC99", - "name": "Other PC", - "vendor": "Other", - "type": "PC", - "color": "" - }, - { - "id": "GFG99", - "name": "Other PETG", - "vendor": "Other", - "type": "PETG", - "color": "" - }, - { - "id": "GFL99", - "name": "Other PLA", - "vendor": "Other", - "type": "PLA", - "color": "" - }, - { - "id": "GFL99", - "name": "Other PLA Hyper", - "vendor": "Other", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "Other TPU", - "vendor": "Other", - "type": "TPU", - "color": "" - }, - { - "id": "GFB99", - "name": "Overture ABS", - "vendor": "Overture", - "type": "ABS", - "color": "" - }, { "id": "OVTABS08", "name": "Overture ABS Basic", @@ -6299,6 +2190,13 @@ "type": "ASA", "color": "" }, + { + "id": "OGFL00", + "name": "PolyLite Dual PLA", + "vendor": "Polymaker", + "type": "PLA", + "color": "" + }, { "id": "OGFG60", "name": "PolyLite PETG", @@ -6307,7 +2205,7 @@ "color": "" }, { - "id": "GFL99", + "id": "OGFL00", "name": "PolyLite PLA", "vendor": "Polymaker", "type": "PLA", @@ -6320,20 +2218,6 @@ "type": "PLA", "color": "" }, - { - "id": "GFB99", - "name": "Polymaker Generic CoPA", - "vendor": "Polymaker", - "type": "PA", - "color": "" - }, - { - "id": "GFB99", - "name": "Polymaker Generic S1", - "vendor": "Polymaker", - "type": "PA", - "color": "" - }, { "id": "OGFPM017", "name": "Polymaker HT-PLA", @@ -6348,20 +2232,6 @@ "type": "PLA", "color": "" }, - { - "id": "PMPE01", - "name": "Polymaker PETG", - "vendor": "Polymaker", - "type": "PETG", - "color": "" - }, - { - "id": "PMPL03", - "name": "Polymaker PLA Pro", - "vendor": "Polymaker", - "type": "PLA", - "color": "" - }, { "id": "OGFL00-1", "name": "PolyTerra Dual PLA", @@ -6370,89 +2240,12 @@ "color": "" }, { - "id": "GFL01", - "name": "PolyTerra J1 PLA", - "vendor": "Polymaker", - "type": "PLA", - "color": "" - }, - { - "id": "GFL01", + "id": "OGFL01", "name": "PolyTerra PLA", "vendor": "Polymaker", "type": "PLA", "color": "" }, - { - "id": "1417031127011", - "name": "Snapmaker PLA Lite", - "vendor": "Polymaker", - "type": "PLA", - "color": "" - }, - { - "id": "Prusa Generic ASA @CORE One 0.6", - "name": "Prusa Generic ASA", - "vendor": "Prusa Polymers", - "type": "ASA", - "color": "" - }, - { - "id": "Prusament ASA @CORE One 0.6", - "name": "Prusament ASA", - "vendor": "Prusa Polymers", - "type": "ASA", - "color": "" - }, - { - "id": "Prusament PA-CF @CORE One 0.6", - "name": "Prusament PA-CF", - "vendor": "Prusa Polymers", - "type": "PA", - "color": "" - }, - { - "id": "Prusament PC Blend @CORE One 0.6", - "name": "Prusament PC Blend", - "vendor": "Prusa Polymers", - "type": "PC", - "color": "" - }, - { - "id": "Prusament PC-CF @CORE One 0.6", - "name": "Prusament PC-CF", - "vendor": "Prusa Polymers", - "type": "PC", - "color": "" - }, - { - "id": "Prusament PETG @CORE One 0.6", - "name": "Prusament PETG", - "vendor": "Prusa Polymers", - "type": "PETG", - "color": "" - }, - { - "id": "Prusament PLA @CORE One 0.6", - "name": "Prusament PLA", - "vendor": "Prusa Polymers", - "type": "PLA", - "color": "" - }, - { - "id": "Prusament PVB @CORE One 0.6", - "name": "Prusament PVB", - "vendor": "Prusa Polymers", - "type": "PVB", - "color": "" - }, - { - "id": "Prusament rPLA @CORE One 0.6", - "name": "Prusament rPLA", - "vendor": "Prusa Polymers", - "type": "PLA", - "color": "" - }, { "id": "QD_1_1_14", "name": "QIDI ABS Odorless", @@ -6762,49 +2555,49 @@ "color": "" }, { - "id": "GFSNL08", + "id": "OGFSNL08", "name": "SUNLU PETG", "vendor": "SUNLU", "type": "PETG", "color": "" }, { - "id": "GFSNL06", + "id": "OGFSNL06", "name": "SUNLU PLA Marble", "vendor": "SUNLU", "type": "PLA", "color": "" }, { - "id": "GFSNL02", + "id": "OGFSNL02", "name": "SUNLU PLA Matte", "vendor": "SUNLU", "type": "PLA", "color": "" }, { - "id": "GFSNL03", + "id": "OGFSNL03", "name": "SUNLU PLA+", "vendor": "SUNLU", "type": "PLA", "color": "" }, { - "id": "GFSNL04", + "id": "OGFSNL04", "name": "SUNLU PLA+ 2.0", "vendor": "SUNLU", "type": "PLA", "color": "" }, { - "id": "GFSNL05", + "id": "OGFSNL05", "name": "SUNLU Silk PLA+", "vendor": "SUNLU", "type": "PLA", "color": "" }, { - "id": "GFSNL07", + "id": "OGFSNL07", "name": "SUNLU Wood PLA", "vendor": "SUNLU", "type": "PLA", @@ -6908,6 +2701,20 @@ "type": "PLA-CF", "color": "#124943" }, + { + "id": "OGFN97", + "name": "Generic PPA-CF", + "vendor": "WonderMaker", + "type": "PPA-CF", + "color": "" + }, + { + "id": "OGFN96", + "name": "Generic PPA-GF", + "vendor": "WonderMaker", + "type": "PPA-GF", + "color": "" + }, { "id": "GFB00", "name": "WonderMaker ABS", @@ -6991,26 +2798,5 @@ "vendor": "WonderMaker", "type": "TPU", "color": "" - }, - { - "id": "GFG99", - "name": "YUMI PETG", - "vendor": "Yumi", - "type": "PETG", - "color": "" - }, - { - "id": "GFU99", - "name": "YUMI PLA Bowden", - "vendor": "Yumi", - "type": "PLA", - "color": "" - }, - { - "id": "GFU99", - "name": "YUMI PLA Direct Drive", - "vendor": "Yumi", - "type": "PLA", - "color": "" } ] diff --git a/kobrax_moonraker_bridge.py b/kobrax_moonraker_bridge.py index 37b8f29..6e02e48 100644 --- a/kobrax_moonraker_bridge.py +++ b/kobrax_moonraker_bridge.py @@ -1494,12 +1494,30 @@ class KobraXBridge: self._push_status_update() # OrcaSlicer filament preset IDs (MoonrakerPrinterAgent.cpp mapping) + # Default-Mapping pro Material-Typ wenn der User keinen Slot-Profil- + # Override gesetzt hat. Für den Kobra X bevorzugen wir Anycubic-eigene + # Filament-IDs aus den `@Anycubic Kobra X 0.4 nozzle`-Profilen — die + # sind druckerspezifisch is_compatible und werden von OrcaSlicer direkt + # gematched. Library-Fallbacks (OGF*) nur für Material-Typen ohne + # Kobra-X-spezifisches Anycubic-Profil — deren @System-Profile haben + # `compatible_printers: []` (= mit allen Druckern kompatibel). _TRAY_INFO_IDX = { - "PLA": "OGFL99", "PLA-CF": "OGFL98", "PLA SILK": "OGFL96", - "PETG": "OGFG99", "PETG-CF": "OGFG98", - "ABS": "OGFB99", "ASA": "OGFB98", - "TPU": "OGFT99", "PA": "OGFP99", "PA-CF": "OGFP98", - "PC": "OGFC99", "HIPS": "OGFH99", "PVA": "OGFV99", + # Anycubic-eigene Kobra-X-Profile + "PLA": "GFPLA", + "PLA+": "GFPLA+", + "PLA SILK": "GFPLA Silk", + "PETG": "GFPETG", + "ABS": "GFABS", + "ASA": "GFASA", + "TPU": "GFTPU 95A", + "PVA": "GFPVA", + # Kein Anycubic-Kobra-X-Profil → Library-Fallback + "PLA-CF": "OGFL98", + "PETG-CF": "OGFG98", + "PA": "OGFN99", + "PA-CF": "OGFN98", + "PC": "OGFC99", + "HIPS": "OGFS98", } def _build_lane_data(self) -> dict: @@ -1556,9 +1574,13 @@ class KobraXBridge: fila_name = user_profile.get("name", "") tray_info_idx = user_profile.get("id") or self._TRAY_INFO_IDX.get(material, "OGFL99") else: - vendor = "" - fila_name = "" - tray_info_idx = self._TRAY_INFO_IDX.get(material, "OGFL99") + # Default: Library-Generic-Profil (siehe _default_filament_name) — + # ist mit allen Druckern kompatibel und garantiert sichtbar. + # Der User wählt pro Slot bewusst eine konkrete Marke wenn er + # eine will; Default bleibt neutral. + fila_name = self._default_filament_name(material) + vendor = "Generic" if fila_name.startswith("Generic ") else "" + tray_info_idx = self._lookup_filament_id(vendor, fila_name) or self._TRAY_INFO_IDX.get(material, "OGFL99") tray_array.append({ "id": str(slot_id), "tag_uid": "0000000000000000", @@ -1566,17 +1588,20 @@ class KobraXBridge: "tray_type": material, "tray_color": color_hex, "tray_sub_brands": vendor, + # OrcaSlicer-Empfangs-Patch PR #13719 erwartet `name` + + # `vendor_name` pro Lane (Stufen-Matching: Vendor+Name → Name → + # filament_id_by_type). Wir senden beide Schreibweisen mit + # damit ältere Patch-Varianten + zukünftige Upstream-PRs beide + # bedient sind. + "name": fila_name, + "vendor_name": vendor, + # Aliase für ältere Patch-Varianten (Variante 2, + # MoonrakerPrinterAgent.cpp): filament_id direkt (exakt), + # sonst preset-Name per find_preset() auflösen. + "filament_id": tray_info_idx, "filament_vendor": vendor, - # Für den OrcaSlicer-Empfangs-Patch (Variante 2, - # MoonrakerPrinterAgent.cpp): `filament_id` direkt - # übernehmen (exakt), sonst `preset`-Name per - # find_preset() auflösen. tray_info_idx ist im Orca- - # Datenmodell nicht eindeutig (z.B. OGFL99 für 136 - # Profile), aber der Bare-Name aus orca_filaments.json - # ist eindeutig — find_preset() parsed @-Suffixe weg. - "filament_id": tray_info_idx, - "preset": fila_name, - "filament_name": fila_name, # ältere Aliase + "filament_name": fila_name, + "preset": fila_name, }) else: tray_array.append({ @@ -1695,6 +1720,7 @@ class KobraXBridge: "TPU": 220, "PA": 260, "PC": 270, "HIPS": 220} num_gates = len(slots) gate_status, gate_material, gate_color, gate_temperature, gate_color_rgb = [], [], [], [], [] + gate_filament_name = [] for _global_index, slot in slots: occupied = slot.get("status") == 5 gate_status.append(1 if occupied else 0) @@ -1706,6 +1732,17 @@ class KobraXBridge: gate_color.append("{:02X}{:02X}{:02X}".format(*c[:3]) if occupied else "") gate_color_rgb.append([round(c[0]/255, 3), round(c[1]/255, 3), round(c[2]/255, 3)] if occupied else [0.0, 0.0, 0.0]) gate_temperature.append(_TEMP.get(material, 210) if occupied else 0) + # gate_filament_name aus User-Override oder Material-Default für den + # HH-Pfad in OrcaSlicer (fetch_hh_filament_info). Wenn Orca den + # HH-Pfad wählt (MMU-Erkennung), wertet PR #13719 dieses Feld als + # Preset-Namen aus → 'Anycubic PLA' matched das druckerspezifische + # Preset, leerer String führte vorher auf Generic PLA. + if occupied: + user_profile = self._filament_profiles.get(_global_index) or {} + fila_name = user_profile.get("name") or self._default_filament_name(material) + gate_filament_name.append(fila_name) + else: + gate_filament_name.append("") loaded_index_map = {global_index: idx for idx, (global_index, _) in enumerate(slots)} active_gate = loaded_index_map.get(int(self._ams_loaded_slot), -1) @@ -1717,13 +1754,36 @@ class KobraXBridge: "gate_color": gate_color, "gate_temperature": gate_temperature, "gate_color_rgb": gate_color_rgb, - "gate_filament_name": [""] * num_gates, + "gate_filament_name": gate_filament_name, "gate_spool_id": [-1] * num_gates, "ttg_map": list(range(num_gates)), "tool": active_gate, "gate": active_gate, } + def _default_filament_name(self, material: str) -> str: + """Default-Name für `gate_filament_name`/`name` in lane_data wenn kein + User-Override gesetzt ist. Bewusste Designentscheidung: **immer + Generic ** als Default — das Library-Profil ist `compatible_printers:[]` + (= mit jedem Drucker kompatibel) und damit garantiert sichtbar. + + OrcaSlicer matcht dann das neutrale Generic-Preset und der User + kann pro Slot eine konkrete Marke setzen wenn er das will.""" + if not material: + return "" + mat = material.upper().strip() + profs = self._load_orca_filaments() + def _match_type(p: dict) -> bool: + pt = (p.get("type") or "").upper() + return pt == mat or pt.startswith(mat + "-") or pt.startswith(mat + " ") + # Library-Generic-Profil (immer is_visible+is_compatible) + for p in profs: + if p.get("vendor") == "Generic" and p.get("name", "").startswith("Generic ") and _match_type(p): + return p.get("name", "") + # Falls die Library-Generic für diesen exotischen Material-Typ fehlt, + # liefern wir nichts — OrcaSlicer fällt auf filament_id_by_type zurück. + return "" + def _build_printer_objects(self) -> dict: s = self._state return { @@ -1946,6 +2006,128 @@ class KobraXBridge: profiles = [p for p in profiles if p.get("vendor", "") == vendor_filter] return self._json_cors({"result": profiles}) + async def handle_kx_filament_profiles_user_list(self, request): + """GET /kx/filament/profiles/user — nur die User-importierten Profile, + für den Settings-Tab (Verwaltung mit Lösch-Buttons).""" + path = self._orca_filaments_user_path() + if not os.path.isfile(path): + return self._json_cors({"result": []}) + try: + with open(path, encoding="utf-8") as f: + user_profiles = json.load(f) or [] + except Exception: + user_profiles = [] + return self._json_cors({"result": user_profiles}) + + async def handle_kx_filament_profiles_import(self, request): + """POST /kx/filament/profiles/user — multipart-Upload mit einer + ZIP-Datei oder mehreren `.json`-Files aus + ~/.config/OrcaSlicer/user//filament/. + + Bestehende User-Profile mit gleichem (vendor, name)-Key werden + überschrieben. Geparste Profile haben dasselbe Schema wie + orca_filaments.json (id, name, vendor, type, color).""" + import io, zipfile + from orca_filaments import parse_profile_bytes + added: list[dict] = [] + skipped: int = 0 + # System-Index für Inherits-Resolve: User-Profile referenzieren + # System-Parents via "inherits" (z.B. "Generic PLA @System"). Damit + # können wir filament_id/vendor/type/color aus dem System-Parent + # ziehen wenn das User-Profil sie selbst nicht setzt. + sys_idx = [p for p in self._load_orca_filaments() if not p.get("is_user")] + try: + reader = await request.multipart() + except Exception: + return self._json_cors({"error": "expected multipart"}, status=400) + async for part in reader: + if part.name not in ("file", "files", "upload"): + continue + blob = await part.read() + fn = (part.filename or "").lower() + if fn.endswith(".zip"): + try: + with zipfile.ZipFile(io.BytesIO(blob)) as zf: + for inner in zf.namelist(): + if not inner.lower().endswith(".json"): + continue + try: + with zf.open(inner) as zf_in: + p = parse_profile_bytes(zf_in.read(), source_name=inner, system_index=sys_idx) + except Exception: + skipped += 1 + continue + if p: + added.append(p) + else: + skipped += 1 + except zipfile.BadZipFile: + return self._json_cors({"error": "bad zip"}, status=400) + elif fn.endswith(".json"): + p = parse_profile_bytes(blob, source_name=fn, system_index=sys_idx) + if p: + added.append(p) + else: + skipped += 1 + + if not added: + return self._json_cors({"result": "ok", "added": 0, "skipped": skipped}) + + # Merge mit existierender User-JSON (gleicher (vendor,name) → ersetzen) + path = self._orca_filaments_user_path() + existing: list[dict] = [] + if os.path.isfile(path): + try: + with open(path, encoding="utf-8") as f: + existing = json.load(f) or [] + except Exception: + existing = [] + by_key = {(p.get("vendor"), p.get("name")): p for p in existing} + for p in added: + by_key[(p.get("vendor"), p.get("name"))] = p + merged = sorted(by_key.values(), key=lambda x: (x.get("vendor",""), x.get("name",""))) + try: + with open(path, "w", encoding="utf-8") as f: + json.dump(merged, f, indent=2, ensure_ascii=False) + f.write("\n") + except Exception as e: + return self._json_cors({"error": f"write failed: {e}"}, status=500) + self._invalidate_filaments_cache() + return self._json_cors({"result": "ok", + "added": len(added), + "skipped": skipped, + "total_user": len(merged)}) + + async def handle_kx_filament_profiles_user_delete(self, request): + """DELETE /kx/filament/profiles/user — löscht entweder einen einzelnen + Eintrag (?vendor=…&name=…) oder alle wenn keine Query angegeben.""" + vendor = request.rel_url.query.get("vendor", "").strip() + name = request.rel_url.query.get("name", "").strip() + path = self._orca_filaments_user_path() + if not os.path.isfile(path): + return self._json_cors({"result": "ok", "removed": 0}) + try: + with open(path, encoding="utf-8") as f: + existing = json.load(f) or [] + except Exception: + existing = [] + before = len(existing) + if vendor and name: + existing = [p for p in existing + if not (p.get("vendor") == vendor and p.get("name") == name)] + else: + existing = [] + try: + with open(path, "w", encoding="utf-8") as f: + json.dump(existing, f, indent=2, ensure_ascii=False) + f.write("\n") + except Exception as e: + return self._json_cors({"error": str(e)}, status=500) + self._invalidate_filaments_cache() + return self._json_cors({"result": "ok", + "removed": before - len(existing), + "total_user": len(existing)}) + def _find_orca_filaments_json(self) -> str | None: """Findet die statische JSON-Datei. Liegt analog zu web/ unter _WEB_BASE/data/ — in allen 3 Deployment-Modi: @@ -2022,21 +2204,45 @@ class KobraXBridge: "id": entry.get("id", "")}) def _load_orca_filaments(self) -> list[dict]: - """Lädt orca_filaments.json einmalig in den Cache. Bei wiederholten - Aufrufen wird die Liste aus dem RAM geliefert.""" + """Lädt System- + User-Profile aus dem Cache. System-Profile kommen + aus bridge/data/orca_filaments.json (Image-embedded), User-Profile + aus /orca_filaments.user.json (Volume-persistent — + überlebt Image-Updates). User-Profile bekommen ein `is_user: True`- + Flag damit das Frontend sie markieren kann.""" if getattr(self, "_orca_filaments_cache", None) is not None: return self._orca_filaments_cache - self._orca_filaments_cache = [] - data_path = self._find_orca_filaments_json() - if not data_path or not os.path.isfile(data_path): - return self._orca_filaments_cache - try: - with open(data_path, encoding="utf-8") as f: - self._orca_filaments_cache = json.load(f) or [] - except Exception as e: - log.warning(f"orca_filaments.json read error: {e}") + merged: list[dict] = [] + # System + sys_path = self._find_orca_filaments_json() + if sys_path and os.path.isfile(sys_path): + try: + with open(sys_path, encoding="utf-8") as f: + merged.extend(json.load(f) or []) + except Exception as e: + log.warning(f"orca_filaments.json read error: {e}") + # User + usr_path = self._orca_filaments_user_path() + if usr_path and os.path.isfile(usr_path): + try: + with open(usr_path, encoding="utf-8") as f: + for p in (json.load(f) or []): + p["is_user"] = True + merged.append(p) + except Exception as e: + log.warning(f"orca_filaments.user.json read error: {e}") + self._orca_filaments_cache = merged return self._orca_filaments_cache + def _orca_filaments_user_path(self) -> str: + """Pfad zur User-Profile-JSON. Liegt im Volume-Mount (KX_DATA_DIR), + damit Image-Updates die Daten nicht zerstören.""" + data_dir = os.environ.get("KX_DATA_DIR") or os.path.join(_WEB_BASE, "data") + os.makedirs(data_dir, exist_ok=True) + return os.path.join(data_dir, "orca_filaments.user.json") + + def _invalidate_filaments_cache(self): + self._orca_filaments_cache = None + def _lookup_filament_id(self, vendor: str, name: str) -> str: """Sucht in orca_filaments.json die filament_id zu einem (vendor,name)- Tupel. Liefert '' wenn nicht gefunden.""" @@ -4439,6 +4645,12 @@ def build_app(bridge: KobraXBridge) -> web.Application: r.add_get("/kx/filament/slots", bridge.handle_kx_filament_slots) r.add_get("/kx/filament/profiles", bridge.handle_kx_filament_profiles) r.add_post("/kx/filament/slots/{idx}/profile", bridge.handle_kx_filament_slot_profile) + # Custom-Profile-Import (Issue #41) — User lädt eigene Orca-Filament- + # Profile als ZIP/JSON hoch (z.B. aus ~/.config/OrcaSlicer/user//filament/), + # weil die Bridge typischerweise nicht auf demselben Host wie OrcaSlicer läuft. + r.add_get("/kx/filament/profiles/user", bridge.handle_kx_filament_profiles_user_list) + r.add_post("/kx/filament/profiles/user", bridge.handle_kx_filament_profiles_import) + r.add_delete("/kx/filament/profiles/user", bridge.handle_kx_filament_profiles_user_delete) r.add_get("/kx/history", bridge.handle_kx_history) r.add_get("/kx/ui/{name:.*}", bridge.handle_kx_ui_asset) r.add_get("/kx/files/{id}/objects", bridge.handle_kx_file_objects) diff --git a/orca_filaments.py b/orca_filaments.py new file mode 100644 index 0000000..c8fa40f --- /dev/null +++ b/orca_filaments.py @@ -0,0 +1,147 @@ +"""OrcaSlicer Filament-Profil Parser. + +Geteilt zwischen dem Generator (tools/gen_orca_filament_list.py) und dem +Custom-Profile-Import-Endpoint (bridge/kobrax_moonraker_bridge.py). + +Liest Orca-Filament-JSON-Dateien (System- oder User-Profile) und gibt +sie als normalisierte Liste mit (id, name, vendor, type, color) zurück. +""" +from __future__ import annotations + +import json +import re + + +def first_str(value, default: str = "") -> str: + """Orca-Profile speichern manche Felder als ['wert']. Liefert erstes + Element als String.""" + if isinstance(value, list): + return str(value[0]) if value else default + if isinstance(value, str): + return value + return default + + +def clean_name(raw: str) -> str: + """Strippt printer-/varianten-spezifische Suffixe: + 'PolyTerra PLA @base' → 'PolyTerra PLA' + 'Anycubic PLA @Anycubic Kobra X 0.4 nozzle' → 'Anycubic PLA' + 'Anker Generic PLA 0.4 nozzle' → 'Anker Generic PLA' + """ + name = re.sub(r"\s*@.*$", "", raw).strip() + name = re.sub(r"\s+\d+(\.\d+)?\s*nozzle\s*$", "", name, flags=re.IGNORECASE).strip() + return name or raw + + +def parse_profile(data: dict, by_name: dict | None = None, + path_vendor: str | None = None, + source_path: str = "", + system_index: list | None = None) -> dict | None: + """Parsed ein einzelnes Orca-Filament-Profil zum Bridge-Schema. + + `by_name` ist optional ein {name: [profile, …]}-Index für Inherits-Resolve + aus dem rohen Source-Tree (Generator). Bei Single-File-Import (User-Datei + aus OrcaSlicer-User-Dir) reichen wir stattdessen `system_index` rein — + die fertige System-Profile-Liste aus orca_filaments.json. Damit können + wir filament_id/vendor/type/color über die `inherits`-Kette aus dem + System-Parent ableiten, auch wenn das User-Profil diese Felder nicht + selbst setzt (typisch: User-Override-Profile haben nur Tweaks). + + Liefert {id, name, vendor, type, color} oder None wenn das Profil + keine filament_id hat (z.B. abstrakte @base-Templates). + """ + if not isinstance(data, dict): + return None + # User-Profile aus dem OrcaSlicer-User-Dir setzen oft KEIN "type"-Feld — + # das kommt vom System-Parent. Wir akzeptieren das wenn entweder "type" + # explizit "filament" ist ODER ein "inherits" auf ein anderes Profil zeigt. + if data.get("type") not in (None, "filament") and not data.get("inherits"): + return None + if data.get("type") == "filament" and data.get("inherits") is None and not data.get("filament_id"): + # type=filament aber kein parent + keine ID → wertloses Stub + return None + inst = data.get("instantiation", "true") + if isinstance(inst, str) and inst.lower() == "false": + return None + + # Build system-name-Index für den fallback-Lookup wenn system_index gesetzt. + sys_by_name: dict[str, dict] = {} + if system_index: + for p in system_index: + if isinstance(p, dict) and p.get("name"): + sys_by_name[p["name"]] = p + + def _resolve(key: str, depth: int = 5): + cur_list = [data] + for _ in range(depth): + for cur in cur_list: + v = cur.get(key) + if v not in ("", [], None, [""]) and v is not None: + return v + # Erst raw-Inherits via by_name (Generator-Pfad) + if by_name: + next_list: list[dict] = [] + for cur in cur_list: + parent_name = cur.get("inherits") + if parent_name and parent_name in by_name: + next_list.extend(by_name[parent_name]) + if next_list: + cur_list = next_list + continue + break + return None + + def _resolve_via_system_index(key: str): + """Inherits-Kette über system_index (clean_name-Match).""" + parent_raw = data.get("inherits") + if not parent_raw or not sys_by_name: + return None + parent_clean = clean_name(parent_raw) + sys_p = sys_by_name.get(parent_clean) + if not sys_p: + return None + # System-JSON benutzt schon das normalisierte Schema + mapping = { + "filament_id": "id", + "filament_vendor": "vendor", + "filament_type": "type", + "default_filament_colour": "color", + } + return sys_p.get(mapping.get(key, key)) + + def _resolve_full(key: str): + v = _resolve(key) + if v not in ("", [], None, [""]) and v is not None: + return v + return _resolve_via_system_index(key) + + fid = _resolve_full("filament_id") + if not fid or not isinstance(fid, str): + return None + + name_raw = data.get("name", fid) + name = clean_name(name_raw) + vendor = first_str(_resolve_full("filament_vendor")) or (path_vendor or "Generic") + ftype = first_str(_resolve_full("filament_type"), "") + color = first_str(_resolve_full("default_filament_colour"), "") + + return { + "id": fid, + "name": name, + "vendor": vendor, + "type": ftype, + "color": color, + } + + +def parse_profile_bytes(blob: bytes, source_name: str = "", + system_index: list | None = None) -> dict | None: + """Liest ein einzelnes Profil aus JSON-Bytes. Für File-Upload-Pfad. + `system_index` ist optional die fertige Liste aus orca_filaments.json — + wird für die Inherits-Resolve von User-Profilen genutzt die das volle + Schema vom System-Parent erben.""" + try: + data = json.loads(blob.decode("utf-8", errors="replace")) + except Exception: + return None + return parse_profile(data, source_path=source_name, system_index=system_index) diff --git a/web/themes/default/app.js b/web/themes/default/app.js index 5e5c786..158dc44 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -312,6 +312,17 @@ function applyLang(){ setText('modal-sec-print',T.settings_print); setText('modal-sec-poll',T.settings_poll); setText('modal-sec-version',T.settings_version); + // Custom-Profile-Import (Issue #41) + setText('modal-sec-orca-profiles',T.orca_profile_section); + setText('orca-profiles-hint',T.orca_profile_hint); + setText('lbl-orca-profiles-import',T.orca_profile_import_btn); + setText('lbl-slot-profile-import',T.orca_profile_import_link); + setText('profile-import-title',T.orca_profile_import_title); + setText('profile-import-dropmsg',T.orca_profile_dropmsg); + setText('profile-import-list-label',T.orca_profile_list_label); + // Hilfe-Text mit Inline-HTML — innerHTML statt setText + var helpEl=document.getElementById('profile-import-help'); + if(helpEl && T.orca_profile_help_html) helpEl.innerHTML=T.orca_profile_help_html; setText('btn-save-settings',T.settings_save); setText('lbl-printer-name',T.settings_printer_name); setText('lbl-printer-ip',T.settings_printer_ip); @@ -903,11 +914,110 @@ function openSettings(){ var cl=document.getElementById('update-changelog');if(cl)cl.style.display='none'; _updateTag='';_updateUrl=''; document.getElementById('settings-modal').classList.add('open'); + // Custom-Profile-Liste laden (Issue #41 — Verwaltung von User-importierten + // OrcaSlicer-Filament-Profilen) + refreshUserProfileList(); } function closeSettings(){ document.getElementById('settings-modal').classList.remove('open'); } +// ── Custom Filament Profile Import (Issue #41) ── +function refreshUserProfileList(){ + var listEl=document.getElementById('orca-profiles-list'); + if(!listEl) return; + fetch(_apiUrl('/kx/filament/profiles/user')).then(function(r){return r.json();}).then(function(d){ + var profs=(d && d.result)||[]; + if(!profs.length){ + listEl.innerHTML=''+(tr('orca_profile_user_empty')||'– keine –')+''; + return; + } + listEl.innerHTML=profs.map(function(p){ + var label=p.vendor+' / '+p.name+' ('+p.type+')'; + return '
' + +'★ '+label+'' + +'' + +'
'; + }).join(''); + }).catch(function(){}); +} +function deleteUserProfile(vendor, name){ + fetch(_apiUrl('/kx/filament/profiles/user?vendor='+vendor+'&name='+name), {method:'DELETE'}) + .then(function(r){return r.json();}) + .then(function(){ + _orcaFilamentCache=null; + refreshUserProfileList(); + // Falls Import-Dialog offen ist, dort auch refreshen + refreshImportDialogList(); + }); +} +function openProfileImport(){ + document.getElementById('profile-import-status').textContent=''; + refreshImportDialogList(); + document.getElementById('profile-import-modal').classList.add('open'); +} +function closeProfileImport(){ + document.getElementById('profile-import-modal').classList.remove('open'); +} +function refreshImportDialogList(){ + var el=document.getElementById('profile-import-list'); + if(!el) return; + fetch(_apiUrl('/kx/filament/profiles/user')).then(function(r){return r.json();}).then(function(d){ + var profs=(d && d.result)||[]; + if(!profs.length){ + el.innerHTML=''+(tr('orca_profile_user_empty')||'– keine –')+''; + return; + } + el.innerHTML=profs.map(function(p){ + var label=p.vendor+' / '+p.name+' ('+p.type+')'; + return '
' + +'★ '+label+'' + +'' + +'
'; + }).join(''); + }).catch(function(){}); +} +function doProfileImportUpload(files){ + if(!files || !files.length) return; + var status=document.getElementById('profile-import-status'); + status.textContent=(tr('orca_profile_uploading')||'Lade hoch…'); + status.style.color='var(--txt2)'; + var done=0, totalAdded=0, totalSkipped=0; + function _one(idx){ + if(idx>=files.length){ + status.textContent=(tr('orca_profile_done')||'Importiert')+': '+totalAdded + +(totalSkipped?' / '+totalSkipped+' '+(tr('orca_profile_skipped')||'übersprungen'):''); + status.style.color='var(--ok)'; + _orcaFilamentCache=null; + refreshImportDialogList(); + refreshUserProfileList(); + // Wenn Slot-Edit offen ist, Dropdown gleich neu befüllen + var mat=document.getElementById('slot-edit-mat'); + if(mat && document.getElementById('slot-edit-modal').classList.contains('open')){ + _fillSlotProfileDropdown(mat.value, '', ''); + } + return; + } + var fd=new FormData(); + fd.append('file', files[idx]); + fetch(_apiUrl('/kx/filament/profiles/user'), {method:'POST', body:fd}) + .then(function(r){return r.json();}) + .then(function(d){ + totalAdded += (d.added||0); + totalSkipped += (d.skipped||0); + done++; + _one(idx+1); + }) + .catch(function(e){ + status.textContent='Fehler: '+e; + status.style.color='var(--err)'; + }); + } + _one(0); +} + // ── AMS Slot Edit ── var _slotEditIndex=-1; var _slotEditLoaded=false; @@ -949,21 +1059,31 @@ function _fillSlotProfileDropdown(material, currentVendor, currentName){ return matU==='' || pt===matU || pt.startsWith(matU+'-') || pt.startsWith(matU+' '); }); sel.innerHTML=''; - // Gruppieren nach Vendor + // User-Profile (is_user) zuerst — eigene Optgroup '★ Eigene' an erster Stelle. + var userProfs=matched.filter(function(p){return p.is_user;}); + var systemProfs=matched.filter(function(p){return !p.is_user;}); + function _appendOption(g, p){ + var o=document.createElement('option'); + o.value=_profileKey(p.vendor, p.name); + o.dataset.vendor=p.vendor; + o.dataset.name=p.name; + o.dataset.id=p.id || ''; + o.textContent=(p.is_user?'★ ':'')+p.name; + if(o.value===wantKey) o.selected=true; + g.appendChild(o); + } + if(userProfs.length){ + var gUser=document.createElement('optgroup'); + gUser.label='★ '+(tr('orca_profile_user_label')||'Eigene Profile'); + userProfs.forEach(function(p){ _appendOption(gUser, p); }); + sel.appendChild(gUser); + } + // System-Profile nach Vendor gruppieren var byVendor={}; - matched.forEach(function(p){ (byVendor[p.vendor]=byVendor[p.vendor]||[]).push(p); }); + systemProfs.forEach(function(p){ (byVendor[p.vendor]=byVendor[p.vendor]||[]).push(p); }); Object.keys(byVendor).sort().forEach(function(v){ var g=document.createElement('optgroup'); g.label=v; - byVendor[v].forEach(function(p){ - var o=document.createElement('option'); - o.value=_profileKey(p.vendor, p.name); - o.dataset.vendor=p.vendor; - o.dataset.name=p.name; - o.dataset.id=p.id || ''; - o.textContent=p.name; - if(o.value===wantKey) o.selected=true; - g.appendChild(o); - }); + byVendor[v].forEach(function(p){ _appendOption(g, p); }); sel.appendChild(g); }); }); @@ -1112,6 +1232,10 @@ function saveSlotEdit(){ closeSlotEdit(); var profSuffix=newProfName?(' ['+newProfVendor+' '+newProfName+']'):''; clog(tr('slot_edit_ok')+' '+(slotIdx+1)+': '+mat+' '+hex+profSuffix,'msg-ok'); + // Sofortiges Re-Render mit aktuellem _slotProfileMap (poll() ist async + // und re-rendert beim nächsten Tick — wir wollen aber dass die Vendor- + // Badge JETZT direkt sichtbar wird). + if(typeof applyState==='function') applyState(); if(typeof poll==='function') poll(); }) .catch(function(e){clog('Fehler: '+e,'msg-err');}); diff --git a/web/themes/default/index.html b/web/themes/default/index.html index 803d2af..5023291 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -121,6 +121,19 @@ + +
+ +
+ Eigene Profile aus OrcaSlicer importieren (User-Dir öffnen via Help → Show Configuration Folder) +
+
+ +
+
@@ -170,12 +183,42 @@
+ ★ Eigene Profile importieren…
+ + +