Fix Bambu Lab spool detection in Spoolman sync and AMS cards

The spool detection only checked tray_uuid and tag_uid, but some Bambu Lab
  spools have RFID read issues causing these to be missing while still having
  valid tray_info_idx (Bambu filament preset ID like "GFA00").

  Backend changes (backend/app/services/spoolman.py):
  - Add tray_info_idx to AMSTray dataclass
  - Parse tray_info_idx from raw MQTT data in parse_ams_tray()
  - Check tray_info_idx first in is_bambu_lab_spool() - most reliable indicator
  - Bambu Lab presets start with "GF" (GFA00, GFB00, GFL00, etc.)
  - Fall back to tray_uuid then tag_uid for unique spool identification
  - Add warning when Bambu spool detected but no unique ID for Spoolman

  Backend changes (backend/app/api/routes/spoolman.py):
  - Update /sync/{printer_id} and /sync-all to pass tray_info_idx
  - Guard against empty spool_tag when adding to tracking set

  Frontend changes (frontend/src/pages/PrintersPage.tsx):
  - Add isBambuLabSpool() helper with same detection logic as backend
  - Update all 4 vendor detection locations in AMS cards to use new helper

  Detection priority (same on frontend and backend):
  1. tray_info_idx starts with "GF" (Bambu preset ID)
  2. tray_uuid is valid 32-char hex (non-zero)
  3. tag_uid is valid 16-char hex (non-zero)
This commit is contained in:
maziggy
2026-01-15 16:23:09 +01:00
parent 6eedf55713
commit 61c6473eca
5 changed files with 470 additions and 415 deletions
+32 -3
View File
@@ -703,6 +703,35 @@ function getWifiStrength(rssi: number | null | undefined): { label: string; colo
return { label: 'Very weak', color: 'text-red-400', bars: 1 };
}
/**
* Check if a tray contains a Bambu Lab spool.
* Uses same logic as backend: tray_info_idx (GF*), tray_uuid, or tag_uid.
*/
function isBambuLabSpool(tray: {
tray_uuid?: string | null;
tag_uid?: string | null;
tray_info_idx?: string | null;
} | null | undefined): boolean {
if (!tray) return false;
// Check tray_info_idx first (most reliable - Bambu preset IDs start with "GF")
if (tray.tray_info_idx && tray.tray_info_idx.startsWith('GF')) {
return true;
}
// Check tray_uuid (32 hex chars, non-zero)
if (tray.tray_uuid && tray.tray_uuid !== '00000000000000000000000000000000') {
return true;
}
// Check tag_uid (16 hex chars, non-zero)
if (tray.tag_uid && tray.tag_uid !== '0000000000000000') {
return true;
}
return false;
}
function CoverImage({ url, printName }: { url: string | null; printName?: string }) {
const [loaded, setLoaded] = useState(false);
const [error, setError] = useState(false);
@@ -1921,7 +1950,7 @@ function PrinterCard({
// Build filament data for hover card
const filamentData = tray?.tray_type ? {
vendor: (tray.tray_uuid ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
vendor: (isBambuLabSpool(tray) ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
profile: cloudInfo?.name || tray.tray_sub_brands || tray.tray_type,
colorName: getBambuColorName(tray.tray_id_name) || hexToBasicColorName(tray.tray_color),
colorHex: tray.tray_color || null,
@@ -2068,7 +2097,7 @@ function PrinterCard({
// Build filament data for hover card
const filamentData = tray?.tray_type ? {
vendor: (tray.tray_uuid ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
vendor: (isBambuLabSpool(tray) ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
profile: cloudInfo?.name || tray.tray_sub_brands || tray.tray_type,
colorName: getBambuColorName(tray.tray_id_name) || hexToBasicColorName(tray.tray_color),
colorHex: tray.tray_color || null,
@@ -2242,7 +2271,7 @@ function PrinterCard({
// Build filament data for hover card
const extFilamentData = {
vendor: (extTray.tray_uuid ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
vendor: (isBambuLabSpool(extTray) ? 'Bambu Lab' : 'Generic') as 'Bambu Lab' | 'Generic',
profile: extCloudInfo?.name || extTray.tray_sub_brands || extTray.tray_type || 'Unknown',
colorName: getBambuColorName(extTray.tray_id_name) || hexToBasicColorName(extTray.tray_color),
colorHex: extTray.tray_color || null,