diff --git a/backend/app/services/bambu_ftp.py b/backend/app/services/bambu_ftp.py index 8085db1c3..dafc59234 100644 --- a/backend/app/services/bambu_ftp.py +++ b/backend/app/services/bambu_ftp.py @@ -78,7 +78,8 @@ class BambuFTPClient: FTP_PORT = 990 DEFAULT_TIMEOUT = 30 # Default timeout in seconds (increased for A1 printers) # Models that need SSL session reuse disabled (A1 series has FTP issues with session reuse) - SKIP_SESSION_REUSE_MODELS = ("A1", "A1 Mini", "P1S", "P1P", "P2S") + # P2S should use normal session reuse like X1C/P1S, not skip it + SKIP_SESSION_REUSE_MODELS = ("A1", "A1 Mini", "P1S", "P1P") def __init__( self, diff --git a/backend/app/services/bambu_mqtt.py b/backend/app/services/bambu_mqtt.py index ec27a3dc4..4346510fe 100644 --- a/backend/app/services/bambu_mqtt.py +++ b/backend/app/services/bambu_mqtt.py @@ -249,6 +249,7 @@ class BambuMQTTClient: ip_address: str, serial_number: str, access_code: str, + model: str | None = None, on_state_change: Callable[[PrinterState], None] | None = None, on_print_start: Callable[[dict], None] | None = None, on_print_complete: Callable[[dict], None] | None = None, @@ -258,6 +259,7 @@ class BambuMQTTClient: self.ip_address = ip_address self.serial_number = serial_number self.access_code = access_code + self.model = model self.on_state_change = on_state_change self.on_print_start = on_print_start self.on_print_complete = on_print_complete @@ -2075,6 +2077,12 @@ class BambuMQTTClient: } } + # P2S-specific parameter adjustments + # P2S printer doesn't support vibration calibration like X1/P1 series + if self.model and self.model.upper().strip() in ("P2S", "N7"): + command["print"]["vibration_cali"] = False + logger.info(f"[{self.serial_number}] P2S detected: disabling vibration_cali") + # Add AMS mapping if provided if ams_mapping is not None: command["print"]["ams_mapping"] = ams_mapping @@ -2083,7 +2091,16 @@ class BambuMQTTClient: logger.info(f"[{self.serial_number}] Sending print command: {json.dumps(command)}") self._client.publish(self.topic_publish, json.dumps(command), qos=1) return True - return False + else: + # Log why we couldn't send the command + if not self._client: + logger.error(f"[{self.serial_number}] Cannot start print: MQTT client not initialized") + elif not self.state.connected: + logger.error( + f"[{self.serial_number}] Cannot start print: Printer not connected (client exists but disconnected). " + f"Connection state: {self.state.connected}, Last message: {self._last_message_time}" + ) + return False def stop_print(self) -> bool: """Stop the current print job.""" diff --git a/backend/app/services/print_scheduler.py b/backend/app/services/print_scheduler.py index 0e8a04d47..e60e7efa7 100644 --- a/backend/app/services/print_scheduler.py +++ b/backend/app/services/print_scheduler.py @@ -1004,17 +1004,22 @@ class PrintScheduler: pass # Don't fail if MQTT fails else: item.status = "failed" - item.error_message = "Failed to send print command" + item.error_message = "Failed to send print command to printer" item.completed_at = datetime.utcnow() await db.commit() - logger.error(f"Queue item {item.id}: Failed to start print") + logger.error( + f"Queue item {item.id}: Failed to start print on {printer.name} ({printer.model}) - " + f"printer_manager.start_print() returned False. " + f"This may indicate: printer not connected, MQTT error, unsupported model configuration, or firmware issue. " + f"Check printer status and backend logs for details." + ) # Send failure notification await notification_service.on_queue_job_failed( job_name=filename.replace(".gcode.3mf", "").replace(".3mf", ""), printer_id=printer.id, printer_name=printer.name, - reason="Failed to send print command", + reason="Failed to send print command to printer - check printer connection and status", db=db, ) diff --git a/backend/app/services/printer_manager.py b/backend/app/services/printer_manager.py index c02ea743b..c0e6e8a81 100644 --- a/backend/app/services/printer_manager.py +++ b/backend/app/services/printer_manager.py @@ -192,6 +192,7 @@ class PrinterManager: ip_address=printer.ip_address, serial_number=printer.serial_number, access_code=printer.access_code, + model=printer.model, on_state_change=on_state_change, on_print_start=on_print_start, on_print_complete=on_print_complete,