mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
Some small improvements for auto poweroff feature
This commit is contained in:
@@ -539,10 +539,17 @@ async def scan_timelapse(
|
||||
base_name = Path(archive.filename).stem
|
||||
|
||||
# Scan timelapse directory on printer
|
||||
try:
|
||||
files = await list_files_async(printer.ip_address, printer.access_code, "/timelapse/video")
|
||||
except Exception:
|
||||
raise HTTPException(500, "Failed to connect to printer")
|
||||
# Try both /timelapse and /timelapse/video (different printer models use different paths)
|
||||
files = []
|
||||
for timelapse_path in ["/timelapse", "/timelapse/video"]:
|
||||
try:
|
||||
files = await list_files_async(printer.ip_address, printer.access_code, timelapse_path)
|
||||
if files:
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
if not files:
|
||||
raise HTTPException(500, "Failed to connect to printer or no timelapse directory found")
|
||||
|
||||
# Look for matching timelapse
|
||||
matching_file = None
|
||||
@@ -574,7 +581,12 @@ async def scan_timelapse(
|
||||
# Timelapse is usually created at print end, so compare to completed_at or created_at
|
||||
compare_time = archive.completed_at or archive.created_at
|
||||
if compare_time:
|
||||
diff = abs(file_time - compare_time)
|
||||
# Bambu printers use China Standard Time (UTC+8) for filenames
|
||||
# Try matching with CST offset adjustment
|
||||
diff_direct = abs(file_time - compare_time)
|
||||
# Also try with 8-hour offset (CST to UTC-ish local times)
|
||||
diff_cst_adjusted = abs(file_time - timedelta(hours=8) - compare_time)
|
||||
diff = min(diff_direct, diff_cst_adjusted)
|
||||
if diff < best_diff:
|
||||
best_diff = diff
|
||||
best_match = f
|
||||
@@ -587,8 +599,8 @@ async def scan_timelapse(
|
||||
if not matching_file:
|
||||
return {"status": "not_found", "message": "No matching timelapse found on printer"}
|
||||
|
||||
# Download the timelapse
|
||||
remote_path = f"/timelapse/video/{matching_file['name']}"
|
||||
# Download the timelapse - use the full path from the file listing
|
||||
remote_path = matching_file.get('path') or f"/timelapse/{matching_file['name']}"
|
||||
timelapse_data = await download_file_bytes_async(
|
||||
printer.ip_address, printer.access_code, remote_path
|
||||
)
|
||||
|
||||
@@ -153,6 +153,11 @@ class BambuMQTTClient:
|
||||
|
||||
# Temperature data
|
||||
temps = {}
|
||||
# Log all temperature-related fields for debugging (only when we have temp data)
|
||||
temp_fields = {k: v for k, v in data.items() if 'temp' in k.lower() or 'nozzle' in k.lower()}
|
||||
if temp_fields and not hasattr(self, '_temp_fields_logged'):
|
||||
logger.info(f"[{self.serial_number}] Temperature fields in MQTT data: {temp_fields}")
|
||||
self._temp_fields_logged = True
|
||||
if "bed_temper" in data:
|
||||
temps["bed"] = float(data["bed_temper"])
|
||||
if "bed_target_temper" in data:
|
||||
@@ -162,10 +167,20 @@ class BambuMQTTClient:
|
||||
if "nozzle_target_temper" in data:
|
||||
temps["nozzle_target"] = float(data["nozzle_target_temper"])
|
||||
# Second nozzle for dual-extruder printers (H2 series)
|
||||
# Try multiple possible field names used by different firmware versions
|
||||
if "nozzle_temper_2" in data:
|
||||
temps["nozzle_2"] = float(data["nozzle_temper_2"])
|
||||
elif "right_nozzle_temper" in data:
|
||||
temps["nozzle_2"] = float(data["right_nozzle_temper"])
|
||||
if "nozzle_target_temper_2" in data:
|
||||
temps["nozzle_2_target"] = float(data["nozzle_target_temper_2"])
|
||||
elif "right_nozzle_target_temper" in data:
|
||||
temps["nozzle_2_target"] = float(data["right_nozzle_target_temper"])
|
||||
# Also check for left nozzle as primary (some H2 models)
|
||||
if "left_nozzle_temper" in data and "nozzle" not in temps:
|
||||
temps["nozzle"] = float(data["left_nozzle_temper"])
|
||||
if "left_nozzle_target_temper" in data and "nozzle_target" not in temps:
|
||||
temps["nozzle_target"] = float(data["left_nozzle_target_temper"])
|
||||
if "chamber_temper" in data:
|
||||
temps["chamber"] = float(data["chamber_temper"])
|
||||
if temps:
|
||||
@@ -232,7 +247,7 @@ class BambuMQTTClient:
|
||||
"raw_data": data,
|
||||
})
|
||||
|
||||
# Detect print completion
|
||||
# Detect print completion (FINISH = success, FAILED = error)
|
||||
if (
|
||||
self._previous_gcode_state == "RUNNING"
|
||||
and self.state.state in ("FINISH", "FAILED")
|
||||
|
||||
@@ -70,7 +70,11 @@ class SmartPlugManager:
|
||||
async def on_print_complete(
|
||||
self, printer_id: int, status: str, db: AsyncSession
|
||||
):
|
||||
"""Called when a print completes - schedule turn off if configured."""
|
||||
"""Called when a print completes - schedule turn off if configured.
|
||||
|
||||
Only triggers auto-off on successful completion (status='completed').
|
||||
Failed prints keep the printer powered on for user investigation.
|
||||
"""
|
||||
plug = await self._get_plug_for_printer(printer_id, db)
|
||||
|
||||
if not plug:
|
||||
@@ -84,8 +88,17 @@ class SmartPlugManager:
|
||||
logger.debug(f"Smart plug '{plug.name}' auto_off is disabled")
|
||||
return
|
||||
|
||||
# Only auto-off on successful completion, not on failures
|
||||
# This allows the user to investigate errors before power-off
|
||||
if status != "completed":
|
||||
logger.info(
|
||||
f"Print on printer {printer_id} ended with status '{status}', "
|
||||
f"skipping auto-off for plug '{plug.name}' to allow investigation"
|
||||
)
|
||||
return
|
||||
|
||||
logger.info(
|
||||
f"Print completed on printer {printer_id} (status: {status}), "
|
||||
f"Print completed successfully on printer {printer_id}, "
|
||||
f"scheduling turn-off for plug '{plug.name}'"
|
||||
)
|
||||
|
||||
@@ -192,14 +205,14 @@ class SmartPlugManager:
|
||||
max_nozzle_temp = nozzle_temp
|
||||
if nozzle_2_temp is not None:
|
||||
max_nozzle_temp = max(nozzle_temp, nozzle_2_temp)
|
||||
logger.debug(
|
||||
f"Checking temp for plug {plug_id}: nozzle1={nozzle_temp}°C, "
|
||||
logger.info(
|
||||
f"Temp check plug {plug_id}: nozzle1={nozzle_temp}°C, "
|
||||
f"nozzle2={nozzle_2_temp}°C, max={max_nozzle_temp}°C, "
|
||||
f"threshold={temp_threshold}°C"
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
f"Checking temp for plug {plug_id}: nozzle={nozzle_temp}°C, "
|
||||
logger.info(
|
||||
f"Temp check plug {plug_id}: nozzle={nozzle_temp}°C, "
|
||||
f"threshold={temp_threshold}°C"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user