From 379ba726e15a908a79f5d3a5aa543026b52dc3e5 Mon Sep 17 00:00:00 2001 From: maziggy Date: Thu, 5 Feb 2026 08:13:13 +0100 Subject: [PATCH] Fix A1/A1 Mini FTP upload EOFError (#271) The FTP code called prot_p() (protected data channel) for all printers, but for A1/A1 Mini it didn't wrap the data connection in SSL. This mismatch caused an immediate EOFError - server expected encrypted data but received plain data. Fix: - Use prot_c() (clear/unencrypted data channel) for A1/A1 Mini - Use prot_p() (protected/encrypted data channel) for X1C/P1S/etc - Removed non-functional ftplib._SSLSocket = None workaround A1/A1 Mini: control channel encrypted (implicit TLS), data channel clear X1C/P1S/etc: both channels encrypted with SSL session reuse Closes #271 --- backend/app/services/bambu_ftp.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/app/services/bambu_ftp.py b/backend/app/services/bambu_ftp.py index e6e9c7e34..4c99511cb 100644 --- a/backend/app/services/bambu_ftp.py +++ b/backend/app/services/bambu_ftp.py @@ -112,8 +112,15 @@ class BambuFTPClient: self._ftp.connect(self.ip_address, self.FTP_PORT, timeout=self.timeout) logger.debug("FTP connected, logging in as bblp") self._ftp.login("bblp", self.access_code) - logger.debug("FTP logged in, setting prot_p and passive mode") - self._ftp.prot_p() + if skip_reuse: + # A1/A1 Mini: Use clear (unencrypted) data channel + # These printers have issues with SSL on the data channel + logger.debug("FTP logged in, setting prot_c (clear) and passive mode for A1") + self._ftp.prot_c() + else: + # X1C/P1S/etc: Use protected (encrypted) data channel with session reuse + logger.debug("FTP logged in, setting prot_p (protected) and passive mode") + self._ftp.prot_p() self._ftp.set_pasv(True) # Log welcome message for debugging if hasattr(self._ftp, "welcome") and self._ftp.welcome: @@ -334,9 +341,6 @@ class BambuFTPClient: progress_callback(uploaded, file_size) with open(local_path, "rb") as f: - if self._should_skip_session_reuse(): - ftplib._SSLSocket = None - logger.debug(f"FTP STOR command starting for {remote_path}") self._ftp.storbinary(f"STOR {remote_path}", f, callback=on_block) logger.info(f"FTP upload complete: {remote_path}")