mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-20 09:03:43 +02:00
feat: dual external spool support, AMS slot model filtering & pre-population
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
This commit is contained in:
@@ -889,6 +889,67 @@ async def get_builtin_filaments(
|
||||
return [{"filament_id": fid, "name": name} for fid, name in _BUILTIN_FILAMENT_NAMES.items()]
|
||||
|
||||
|
||||
# Cache for filament_id → name mapping (resolved from cloud preset details)
|
||||
_filament_id_name_cache: dict[str, str] = {}
|
||||
_filament_id_name_cache_time: float = 0
|
||||
|
||||
|
||||
@router.get("/filament-id-map")
|
||||
async def get_filament_id_map(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User | None = RequirePermissionIfAuthEnabled(Permission.FILAMENTS_READ),
|
||||
):
|
||||
"""
|
||||
Get filament_id → name mapping for user cloud presets.
|
||||
|
||||
K-profiles store a filament_id (e.g., "P4d64437") which is different from
|
||||
the cloud preset setting_id (e.g., "PFUS9ac902733670a9"). This endpoint
|
||||
fetches details for all custom presets and returns the mapping.
|
||||
Cached for 5 minutes.
|
||||
"""
|
||||
import time
|
||||
|
||||
global _filament_id_name_cache, _filament_id_name_cache_time
|
||||
|
||||
if _filament_id_name_cache and time.time() - _filament_id_name_cache_time < FILAMENT_CACHE_TTL:
|
||||
return _filament_id_name_cache
|
||||
|
||||
token, _ = await get_stored_token(db)
|
||||
if not token:
|
||||
return _filament_id_name_cache or {}
|
||||
|
||||
cloud = get_cloud_service()
|
||||
cloud.set_token(token)
|
||||
if not cloud.is_authenticated:
|
||||
return _filament_id_name_cache or {}
|
||||
|
||||
try:
|
||||
data = await cloud.get_slicer_settings()
|
||||
custom_presets = data.get("filament", {}).get("private", [])
|
||||
|
||||
result: dict[str, str] = {}
|
||||
for preset in custom_presets:
|
||||
setting_id = preset.get("setting_id", "")
|
||||
if not setting_id:
|
||||
continue
|
||||
try:
|
||||
detail = await cloud.get_setting_detail(setting_id)
|
||||
fid = detail.get("filament_id", "")
|
||||
name = detail.get("name", "")
|
||||
if fid and name:
|
||||
# Strip printer/nozzle suffix: "Devil Design PLA Basic @Bambu Lab H2D 0.4 nozzle" → "Devil Design PLA Basic"
|
||||
clean_name = name.split(" @")[0].strip() if " @" in name else name
|
||||
result[fid] = clean_name
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
_filament_id_name_cache = result
|
||||
_filament_id_name_cache_time = time.time()
|
||||
return result
|
||||
except Exception:
|
||||
return _filament_id_name_cache or {}
|
||||
|
||||
|
||||
@router.get("/fields/{preset_type}")
|
||||
async def get_preset_fields(
|
||||
preset_type: Literal["filament", "print", "process", "printer"],
|
||||
|
||||
Reference in New Issue
Block a user