mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-21 10:15:04 +02:00
Fix Bambu Cloud preset lookup by transforming filament_id to setting_id
Printers report filament_id (e.g., GFA00) but the Bambu Cloud API expects setting_id format which has an "S" inserted after "GF" (e.g., GFSA00). - Add _filament_id_to_setting_id() helper function - Transform IDs before API calls: GFx## -> GFSx## - User presets (P-prefix) and already-correct IDs unchanged - Improved warning message to show both original and transformed IDs
This commit is contained in:
@@ -267,6 +267,34 @@ _filament_cache_time: float = 0
|
||||
FILAMENT_CACHE_TTL = 300 # 5 minutes
|
||||
|
||||
|
||||
def _filament_id_to_setting_id(filament_id: str) -> str:
|
||||
"""
|
||||
Convert filament_id to setting_id format for Bambu Cloud API.
|
||||
|
||||
Printers report filament_id (e.g., GFA00, GFG02) but the API expects
|
||||
setting_id format which has an "S" inserted after "GF" (e.g., GFSA00, GFSG02).
|
||||
|
||||
User presets (starting with "P") and already-correct IDs are returned unchanged.
|
||||
"""
|
||||
if not filament_id:
|
||||
return filament_id
|
||||
|
||||
# User presets start with "P" - leave unchanged
|
||||
if filament_id.startswith("P"):
|
||||
return filament_id
|
||||
|
||||
# Official Bambu presets: GFx## -> GFSx##
|
||||
# Check if it matches the filament_id pattern (GF followed by letter and digits)
|
||||
if filament_id.startswith("GF") and len(filament_id) >= 4:
|
||||
# Check if it's already a setting_id (has S after GF)
|
||||
if filament_id[2] == "S":
|
||||
return filament_id
|
||||
# Insert "S" after "GF": GFA00 -> GFSA00
|
||||
return f"GFS{filament_id[2:]}"
|
||||
|
||||
return filament_id
|
||||
|
||||
|
||||
@router.post("/filament-info")
|
||||
async def get_filament_info(setting_ids: list[str] = Body(...), db: AsyncSession = Depends(get_db)):
|
||||
"""
|
||||
@@ -308,7 +336,10 @@ async def get_filament_info(setting_ids: list[str] = Body(...), db: AsyncSession
|
||||
continue
|
||||
|
||||
try:
|
||||
data = await cloud.get_setting_detail(setting_id)
|
||||
# Transform filament_id to setting_id format (GFA00 -> GFSA00)
|
||||
api_setting_id = _filament_id_to_setting_id(setting_id)
|
||||
|
||||
data = await cloud.get_setting_detail(api_setting_id)
|
||||
setting = data.get("setting", {})
|
||||
|
||||
# Extract name (e.g., "Bambu PLA Basic Jade White")
|
||||
@@ -323,11 +354,14 @@ async def get_filament_info(setting_ids: list[str] = Body(...), db: AsyncSession
|
||||
k_value = None
|
||||
|
||||
info = {"name": name, "k": k_value}
|
||||
# Cache using original ID so frontend gets expected response
|
||||
_filament_cache[setting_id] = info
|
||||
result[setting_id] = info
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to get cloud preset {setting_id}: {e}")
|
||||
logger.warning(
|
||||
f"Failed to get cloud preset {setting_id} (API ID: {_filament_id_to_setting_id(setting_id)}): {e}"
|
||||
)
|
||||
# Cache the failure to avoid repeated requests
|
||||
_filament_cache[setting_id] = {"name": "", "k": None}
|
||||
result[setting_id] = {"name": "", "k": None}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Debug script to investigate Bambu Cloud preset API responses."""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add backend to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
import httpx
|
||||
from sqlalchemy import create_engine, text
|
||||
|
||||
from backend.app.core.config import settings
|
||||
|
||||
# Test preset IDs (from the warning logs)
|
||||
TEST_IDS = ["GFG02", "GFL05", "GFA00", "GFA02", "GFA06"]
|
||||
|
||||
|
||||
def get_token_from_db() -> str | None:
|
||||
"""Get the stored token from the database."""
|
||||
db_path = settings.base_dir / "bambuddy.db"
|
||||
engine = create_engine(f"sqlite:///{db_path}")
|
||||
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text("SELECT value FROM settings WHERE key = 'bambu_cloud_token'"))
|
||||
row = result.fetchone()
|
||||
|
||||
if row and row[0]:
|
||||
return row[0]
|
||||
return None
|
||||
|
||||
|
||||
async def test_preset(setting_id: str, token: str, base_url: str = "https://api.bambulab.com"):
|
||||
"""Test fetching a single preset and show full response."""
|
||||
url = f"{base_url}/v1/iot-service/api/slicer/setting/{setting_id}"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f"Testing preset: {setting_id}")
|
||||
print(f"URL: {url}")
|
||||
print(f"{'=' * 60}")
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
|
||||
print(f"Status: {response.status_code}")
|
||||
print("\nResponse body:")
|
||||
try:
|
||||
data = response.json()
|
||||
print(json.dumps(data, indent=2))
|
||||
except Exception:
|
||||
print(response.text)
|
||||
|
||||
return response.status_code
|
||||
|
||||
|
||||
async def main():
|
||||
# Get token from DB
|
||||
token = get_token_from_db()
|
||||
|
||||
if not token:
|
||||
print("Could not find token in database.")
|
||||
print("Make sure you're logged into Bambu Cloud in Bambuddy.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Found token in database (length: {len(token)})")
|
||||
|
||||
# Allow testing specific preset IDs from command line
|
||||
test_ids = sys.argv[1:] if len(sys.argv) > 1 else TEST_IDS
|
||||
|
||||
# Test each preset
|
||||
for preset_id in test_ids:
|
||||
await test_preset(preset_id, token)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user