BambuStudio encodes virtual tray IDs (254/255) as -1 in the flat
ams_mapping array — a convention already documented in
bambu_mqtt.py:start_print(). The spoolman tracking helper was treating
-1 as "unmapped, use position-based default", which mapped slot_id=1
to AMS tray 0 and credited external-spool prints to whatever Spoolman
spool happened to be linked to AMS slot 0. The reporter's TPU prints
on an H2S were credited to a PLA spool for ~49g over 4 prints before
being noticed (regression of #853).
When slot_to_tray[slot_id-1] == -1 and ams_trays contains 254/255,
return the external tray ID directly. Prefers 254 over 255 (matches
single-nozzle tray_now reporting + the vir_slot id=255->254 remap in
bambu_mqtt.py:864). Legacy fall-through preserved for callers that
don't pass ams_trays.
Root cause investigation and patch by @ojimpo.
Spoolman had two mutually-exclusive weight paths gated on the
`disable_weight_sync` flag. The default (False) used AMS remain%
x tray_weight auto-sync, which silently dropped non-BL spools
because the AMS doesn't report tray_weight without RFID. The
inventory_remaining fallback would have covered it, but the
spool_assignment table it reads from is wiped on Spoolman
activation, so non-BL spools got no weight updates at all.
Match the internal Filament Inventory: per-print tracking always
runs, AMS auto-sync no longer writes remaining_weight (it still
maintains spool metadata and slot assignments). The setting
becomes a no-op; left in the schema and UI for backwards compat.
- store_print_data: drop the disable_weight_sync early return
- sync_ams_tray callsites in main.py + routes/spoolman.py: force
disable_weight_sync=True so weight is never written by AMS sync
- new regression test confirming tracking runs with flag=false
feat(spoolman-inventory): squashed feature work for rebase onto dev
Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
feat(spoolman-inventory): squashed feature work for rebase onto dev
Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
feat(inventory): replace Spoolman iframe with internal inventory UI
When Spoolman is enabled, the Inventory page now uses the same internal
UI (spool list, create/edit modal, archive, delete, weight sync) backed
by a new proxy layer instead of opening an iframe.
Backend:
- Add dual external spool support for H2D (vt_tray as list: Ext-L/Ext-R)
- Add cloud filament ID map endpoint (/cloud/filament-id-map)
- Fix RFID spool data erased by periodic AMS updates (skip tag matcher
for RFID-tagged trays)
- Fix AMS slot config overwrites RFID spool state
- Fix K-profile selection corrupts existing profiles on X1C/P1S
- Resolve K-profiles filament name via cloud filament ID map
- Update print scheduler and usage tracker for dual external spools
Frontend:
- Add printer model filtering to ConfigureAmsSlotModal (cloud/local/builtin
presets filtered by @BBL model suffix and compatible_printers)
- Add pre-population for configured slots (preset, color, K-profile)
- Add K-Profiles view with accurate filament name resolution
- Internationalize all ConfigureAmsSlotModal strings (en/de/fr/it/ja — 21 keys)
- Add 5 new ConfigureAmsSlotModal tests (model filtering, pre-selection,
color pre-population, i18n)
- Update PrintersPage for dual external spool rendering
Docs:
- Update CHANGELOG, README, website features, and wiki AMS docs
- Remove 28 unused imports across 22 test files
- Prefix 4 unused local variables with _ in app code
(archives, bambu_mqtt, main) and remove 1 dead store
- Consolidate import/import-from in test_plate_detection.py
- Fix unreachable statement in test_archive_service.py
- Simplify redundant comparison in timelapse_processor.py
Resolves ~50 CodeQL py/unused-import, py/unused-local-variable,
py/import-and-import-from, py/unreachable-statement, and
py/redundant-comparison findings.