Procházet zdrojové kódy

Fix spool assignment applying wrong filament profile (#681)

  The Bambu Cloud API returns the base filament_id for versioned
  setting IDs (e.g. GFSL99 → GFL99 for all "Generic PLA" variants),
  so assigning a spool with a specific variant like "Generic PLA Silk"
  (GFSL99_01) would configure the AMS slot with the base "Generic PLA"
  profile (GFL99) instead of the correct one (GFL96).

  Added a post-resolution cross-check: if the resolved filament_id maps
  to a different name than the spool's stored preset name, reverse-lookup
  the correct filament_id from the built-in filament table.
maziggy před 2 měsíci
rodič
revize
c5791e0b54

+ 1 - 0
CHANGELOG.md

@@ -32,6 +32,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **HMS Notifications for Unknown/Phantom Error Codes** — Printers send many undocumented or phantom HMS error codes that don't correspond to real errors (e.g. calibration status codes after firmware updates). These triggered email/push notifications even though the printer card correctly filtered them out. Flipped the notification logic from "notify all, suppress specific codes" to "only notify for errors with known descriptions", matching the frontend behavior. Also fixed the log message reporting incorrect notification counts.
 - **HMS Notifications for Unknown/Phantom Error Codes** — Printers send many undocumented or phantom HMS error codes that don't correspond to real errors (e.g. calibration status codes after firmware updates). These triggered email/push notifications even though the printer card correctly filtered them out. Flipped the notification logic from "notify all, suppress specific codes" to "only notify for errors with known descriptions", matching the frontend behavior. Also fixed the log message reporting incorrect notification counts.
 - **Ethernet Badge Shown on WiFi Printers / MQTT Disconnecting** ([#585](https://github.com/maziggy/bambuddy/issues/585)) — Three bugs in the ethernet badge feature: (1) `home_flag` bit 18 is set on all printers regardless of connection type, so every ethernet-capable model showed the ethernet badge even when connected via WiFi. Replaced bit 18 detection with wifi_signal-based heuristic: printers on ethernet with WiFi disabled report a hardcoded `-90 dBm` sentinel, while real WiFi signals vary. (2) The lazy import used `from app.utils.printer_models` which crashes with `ModuleNotFoundError` in paho-mqtt's background thread (correct path is `backend.app.utils.printer_models`). This killed the MQTT thread entirely, causing all printers to go stale after 60s and repeatedly disconnect/reconnect. (3) WiFi-only models (A1, P1P, etc.) that don't have an ethernet port are excluded via model-based gating. Reported by @cadtoolbox.
 - **Ethernet Badge Shown on WiFi Printers / MQTT Disconnecting** ([#585](https://github.com/maziggy/bambuddy/issues/585)) — Three bugs in the ethernet badge feature: (1) `home_flag` bit 18 is set on all printers regardless of connection type, so every ethernet-capable model showed the ethernet badge even when connected via WiFi. Replaced bit 18 detection with wifi_signal-based heuristic: printers on ethernet with WiFi disabled report a hardcoded `-90 dBm` sentinel, while real WiFi signals vary. (2) The lazy import used `from app.utils.printer_models` which crashes with `ModuleNotFoundError` in paho-mqtt's background thread (correct path is `backend.app.utils.printer_models`). This killed the MQTT thread entirely, causing all printers to go stale after 60s and repeatedly disconnect/reconnect. (3) WiFi-only models (A1, P1P, etc.) that don't have an ethernet port are excluded via model-based gating. Reported by @cadtoolbox.
 - **Inventory Usage Tracker Missing External Spool Mapping** ([#677](https://github.com/maziggy/bambuddy/issues/677)) — When all higher-priority slot-to-tray mapping methods failed (MQTT mapping, print command mapping, queue mapping, color matching), the internal inventory usage tracker fell back to `slot_id - 1` which can never reach external spool IDs (254/255) or AMS-HT IDs (128+). Added position-based resolution using sorted available tray IDs from the printer's AMS state, matching the fix applied to Spoolman tracking in #686. Contributed by @shrunbr.
 - **Inventory Usage Tracker Missing External Spool Mapping** ([#677](https://github.com/maziggy/bambuddy/issues/677)) — When all higher-priority slot-to-tray mapping methods failed (MQTT mapping, print command mapping, queue mapping, color matching), the internal inventory usage tracker fell back to `slot_id - 1` which can never reach external spool IDs (254/255) or AMS-HT IDs (128+). Added position-based resolution using sorted available tray IDs from the printer's AMS state, matching the fix applied to Spoolman tracking in #686. Contributed by @shrunbr.
+- **Spool Assignment Applies Wrong Filament Profile** ([#681](https://github.com/maziggy/bambuddy/issues/681)) — Assigning a spool with a specific filament variant (e.g. "Generic PLA Silk") to an AMS slot applied the base profile instead (e.g. "Generic PLA"). The Bambu Cloud API returns only the base `filament_id` for versioned setting IDs (`GFSL99` → `GFL99`), ignoring variant suffixes (`GFSL99_01`). Added a cross-check that compares the resolved filament name against the spool's stored preset name and corrects the filament ID via reverse lookup when they don't match (e.g. `GFL99` → `GFL96` for "Generic PLA Silk"). Reported by @peter-k-de.
 
 
 ### Security
 ### Security
 - **PyJWT ≥2.12.0** — Bumped minimum version to address CVE-2026-32597.
 - **PyJWT ≥2.12.0** — Bumped minimum version to address CVE-2026-32597.

+ 23 - 1
backend/app/api/routes/inventory.py

@@ -31,7 +31,7 @@ from backend.app.schemas.spool import (
     SpoolUpdate,
     SpoolUpdate,
 )
 )
 from backend.app.schemas.spool_usage import SpoolUsageHistoryResponse
 from backend.app.schemas.spool_usage import SpoolUsageHistoryResponse
-from backend.app.utils.filament_ids import normalize_slicer_filament
+from backend.app.utils.filament_ids import filament_id_to_setting_id, normalize_slicer_filament
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
@@ -902,6 +902,7 @@ async def assign_spool(
                     # Official Bambu filament_id (e.g. "GFL05")
                     # Official Bambu filament_id (e.g. "GFL05")
                     tray_info_idx, setting_id = normalize_slicer_filament(sf)
                     tray_info_idx, setting_id = normalize_slicer_filament(sf)
                     logger.info("Spool assign: using official filament_id=%r", tray_info_idx)
                     logger.info("Spool assign: using official filament_id=%r", tray_info_idx)
+
                 else:
                 else:
                     # Could be a local preset ID or material type — try local DB
                     # Could be a local preset ID or material type — try local DB
                     try:
                     try:
@@ -928,6 +929,27 @@ async def assign_spool(
                         # Not a numeric ID — treat as material type string
                         # Not a numeric ID — treat as material type string
                         tray_info_idx, setting_id = normalize_slicer_filament(sf)
                         tray_info_idx, setting_id = normalize_slicer_filament(sf)
 
 
+            # Cross-check: the cloud API returns the base filament_id for
+            # versioned setting_ids (e.g. GFSL99 → GFL99 for all PLA variants).
+            # If the spool has a specific preset name (e.g. "Generic PLA Silk"),
+            # reverse-lookup the correct filament_id from the built-in table.
+            if tray_info_idx and spool.slicer_filament_name:
+                from backend.app.api.routes.cloud import _BUILTIN_FILAMENT_NAMES
+
+                expected_name = _BUILTIN_FILAMENT_NAMES.get(tray_info_idx, "")
+                if expected_name and expected_name != spool.slicer_filament_name:
+                    for fid, fname in _BUILTIN_FILAMENT_NAMES.items():
+                        if fname == spool.slicer_filament_name:
+                            logger.info(
+                                "Spool assign: corrected filament_id %r→%r (name=%r)",
+                                tray_info_idx,
+                                fid,
+                                spool.slicer_filament_name,
+                            )
+                            tray_info_idx = fid
+                            setting_id = filament_id_to_setting_id(fid)
+                            break
+
             if not tray_info_idx:
             if not tray_info_idx:
                 # Fallback: reuse slot's existing tray_info_idx or generic ID
                 # Fallback: reuse slot's existing tray_info_idx or generic ID
                 if (
                 if (

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
static/assets/index-C-iDXnGm.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-Dbccwufc.js"></script>
+    <script type="module" crossorigin src="/assets/index-C-iDXnGm.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-BgeMokkR.css">
     <link rel="stylesheet" crossorigin href="/assets/index-BgeMokkR.css">
   </head>
   </head>
   <body>
   <body>

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů