mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-22 03:49:18 +02:00
Fix plate calibration backup/restore with printer ID remapping
- Add "Plate Detection" option to backup modal - Store printer_id_to_serial mapping in backup for calibration files - Remap printer IDs during restore based on serial numbers so files like printer_3_ref_0.jpg get correctly renamed if printer 3 becomes printer 2 on the new system - Add parents=True to mkdir calls in config.py to fix startup crash - Labels/metadata are now correctly restored via the metadata.json files
This commit is contained in:
@@ -435,11 +435,24 @@ async def export_backup(
|
||||
if include_printers and include_plate_calibration:
|
||||
plate_cal_dir = app_settings.plate_calibration_dir
|
||||
if plate_cal_dir.exists():
|
||||
backup["plate_calibration"] = []
|
||||
backup["plate_calibration"] = {
|
||||
"files": [],
|
||||
"printer_id_to_serial": {}, # Map old printer IDs to serial numbers for restore
|
||||
}
|
||||
for cal_file in plate_cal_dir.iterdir():
|
||||
if cal_file.is_file():
|
||||
backup["plate_calibration"].append(cal_file.name)
|
||||
if backup["plate_calibration"]:
|
||||
backup["plate_calibration"]["files"].append(cal_file.name)
|
||||
# Extract printer ID from filename (e.g., "printer_1_ref_0.jpg" -> 1)
|
||||
if cal_file.name.startswith("printer_"):
|
||||
parts = cal_file.name.split("_")
|
||||
if len(parts) >= 2 and parts[1].isdigit():
|
||||
old_printer_id = int(parts[1])
|
||||
if old_printer_id not in backup["plate_calibration"]["printer_id_to_serial"]:
|
||||
# Look up serial number for this printer ID
|
||||
backup["plate_calibration"]["printer_id_to_serial"][old_printer_id] = (
|
||||
printer_id_to_serial.get(old_printer_id)
|
||||
)
|
||||
if backup["plate_calibration"]["files"]:
|
||||
backup["included"].append("plate_calibration")
|
||||
|
||||
# Filaments
|
||||
@@ -883,6 +896,8 @@ async def import_backup(
|
||||
content = await file.read()
|
||||
base_dir = app_settings.base_dir
|
||||
files_restored = 0
|
||||
# Store plate calibration files for later (need printer ID remapping after printers restored)
|
||||
plate_cal_files: dict[str, bytes] = {}
|
||||
|
||||
# Check if it's a ZIP file
|
||||
if file.filename and file.filename.endswith(".zip"):
|
||||
@@ -903,12 +918,12 @@ async def import_backup(
|
||||
# Ensure path is safe (no path traversal)
|
||||
if ".." in zip_path or zip_path.startswith("/"):
|
||||
continue
|
||||
# Plate calibration files go to plate_calibration_dir (may differ from base_dir)
|
||||
# Plate calibration files - store for later processing after printers are restored
|
||||
if zip_path.startswith("plate_calibration/"):
|
||||
filename = zip_path.replace("plate_calibration/", "", 1)
|
||||
target_path = app_settings.plate_calibration_dir / filename
|
||||
else:
|
||||
target_path = base_dir / zip_path
|
||||
plate_cal_files[filename] = zf.read(zip_path)
|
||||
continue
|
||||
target_path = base_dir / zip_path
|
||||
target_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with zf.open(zip_path) as src, open(target_path, "wb") as dst:
|
||||
dst.write(src.read())
|
||||
@@ -1054,6 +1069,48 @@ async def import_backup(
|
||||
# Flush printers so other sections can look them up
|
||||
await db.flush()
|
||||
|
||||
# Restore plate calibration files (remap printer IDs based on serial numbers)
|
||||
if plate_cal_files:
|
||||
# Build serial_number -> new_printer_id mapping
|
||||
serial_to_new_id: dict[str, int] = {}
|
||||
pr_result = await db.execute(select(Printer))
|
||||
for pr in pr_result.scalars().all():
|
||||
serial_to_new_id[pr.serial_number] = pr.id
|
||||
|
||||
# Get old_id -> serial mapping from backup (supports both old list format and new dict format)
|
||||
plate_cal_data = backup.get("plate_calibration", {})
|
||||
if isinstance(plate_cal_data, dict):
|
||||
old_id_to_serial: dict[int, str | None] = {
|
||||
int(k): v for k, v in plate_cal_data.get("printer_id_to_serial", {}).items()
|
||||
}
|
||||
else:
|
||||
old_id_to_serial = {}
|
||||
|
||||
# Build old_id -> new_id mapping
|
||||
old_id_to_new_id: dict[int, int] = {}
|
||||
for old_id, serial in old_id_to_serial.items():
|
||||
if serial and serial in serial_to_new_id:
|
||||
old_id_to_new_id[old_id] = serial_to_new_id[serial]
|
||||
|
||||
app_settings.plate_calibration_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for filename, file_data in plate_cal_files.items():
|
||||
# Parse old printer ID from filename (e.g., "printer_3_ref_0.jpg" -> 3)
|
||||
new_filename = filename
|
||||
if filename.startswith("printer_"):
|
||||
parts = filename.split("_")
|
||||
if len(parts) >= 2 and parts[1].isdigit():
|
||||
old_printer_id = int(parts[1])
|
||||
if old_printer_id in old_id_to_new_id:
|
||||
new_printer_id = old_id_to_new_id[old_printer_id]
|
||||
# Replace old ID with new ID in filename
|
||||
new_filename = filename.replace(f"printer_{old_printer_id}_", f"printer_{new_printer_id}_", 1)
|
||||
|
||||
target_path = app_settings.plate_calibration_dir / new_filename
|
||||
with open(target_path, "wb") as f:
|
||||
f.write(file_data)
|
||||
files_restored += 1
|
||||
|
||||
# Restore notification providers (skip or overwrite duplicates by name)
|
||||
# Build printer serial to ID lookup (printers were restored first)
|
||||
if "notification_providers" in backup:
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -23,7 +23,7 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-jEq4K9YC.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-C8T392Mv.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BQIOMqJ9.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user