Bläddra i källkod

fix(ftp): cap H2C FTPS to TLS 1.2 so the sliced 3MF downloads reliably (#2582)

H2C (firmware 01.02.00.00) had no per-model FTP profile and ran on the
Python-default TLS 1.3, hitting the same vsFTPd session-reuse fault the P2S
(#1401) and X2D (#1638) were already capped for. The intermittent FTPS
failure dropped prints to the no-3MF fallback archive, so slice data was
missing — hence no filament in the Print Log and no inventory deduction.
Add an H2C cap_tls_v1_2 profile plus its O1C/O1C2 SSDP aliases. H2D is left
on the default profile (negotiates TLS 1.3 without the fault).
maziggy 1 månad sedan
förälder
incheckning
9174badb10

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
CHANGELOG.md


+ 15 - 0
backend/app/services/ftp_profiles.py

@@ -91,6 +91,19 @@ _PROFILES: dict[str, FTPProfile] = {
     "X2D": FTPProfile(
     "X2D": FTPProfile(
         cap_tls_v1_2=True,
         cap_tls_v1_2=True,
     ),
     ),
+    # H2C firmware 01.02.00.00 (#2582, reporter @gyrene2083) — same H2
+    # generation and same firmware line as P2S, and with no profile it
+    # ran on the Python-default TLS 1.3. Reported symptom is exactly the
+    # one the X2D comment describes: the sliced 3MF intermittently fails
+    # to come off the printer over FTPS, so the print drops to the no-3MF
+    # fallback archive with no slice data — which is why the Print Log
+    # shows no filament and nothing is deducted. Cap to TLS 1.2 by analogy
+    # with P2S (intermittent "sometimes works" points at the session-reuse
+    # variant, not X2D's deterministic handshake failure); if a debug
+    # capture shows a different FTPS variant the entry stays the tuning slot.
+    "H2C": FTPProfile(
+        cap_tls_v1_2=True,
+    ),
 }
 }
 
 
 # SSDP internal codes that should resolve to a display-name profile.
 # SSDP internal codes that should resolve to a display-name profile.
@@ -98,6 +111,8 @@ _PROFILES: dict[str, FTPProfile] = {
 _MODEL_ALIASES: dict[str, str] = {
 _MODEL_ALIASES: dict[str, str] = {
     "N7": "P2S",  # P2S internal SSDP code
     "N7": "P2S",  # P2S internal SSDP code
     "N6": "X2D",  # X2D internal SSDP code
     "N6": "X2D",  # X2D internal SSDP code
+    "O1C": "H2C",  # H2C internal SSDP code
+    "O1C2": "H2C",  # H2C dual-nozzle variant SSDP code
 }
 }
 
 
 
 

+ 16 - 0
backend/tests/unit/services/test_ftp_profiles.py

@@ -58,6 +58,22 @@ def test_x2d_internal_ssdp_code_resolves_to_x2d():
     assert profile.cap_tls_v1_2 is True
     assert profile.cap_tls_v1_2 is True
 
 
 
 
+def test_h2c_caps_tls_v1_2():
+    """H2C firmware 01.02.00.00 — same H2 generation / firmware line as
+    P2S — intermittently fails the FTPS 3MF download and falls through to
+    the no-3MF fallback archive, so nothing gets deducted (#2582, reporter
+    @gyrene2083). The profile caps to TLS 1.2 by analogy with P2S."""
+    profile = get_ftp_profile("H2C")
+    assert profile.cap_tls_v1_2 is True
+
+
+def test_h2c_internal_ssdp_codes_resolve_to_h2c():
+    """SSDP internal codes O1C and O1C2 (dual-nozzle variant) → H2C
+    profile, so the cap applies however the model string arrives."""
+    assert get_ftp_profile("O1C").cap_tls_v1_2 is True
+    assert get_ftp_profile("O1C2").cap_tls_v1_2 is True
+
+
 def test_lookup_is_case_insensitive():
 def test_lookup_is_case_insensitive():
     """Printer.model may carry mixed case; the lookup normalises."""
     """Printer.model may carry mixed case; the lookup normalises."""
     assert get_ftp_profile("p2s").cap_tls_v1_2 is True
     assert get_ftp_profile("p2s").cap_tls_v1_2 is True

Vissa filer visades inte eftersom för många filer har ändrats