Prechádzať zdrojové kódy

fix(printer): "off" flow_cali / nozzle_offset_cali now actually suppress the stage

  The Re-print and Schedule modal toggles for Flow Calibration and Nozzle
  Offset Calibration accepted "off" correctly and flowed it through to the
  project_file MQTT publish — Bambuddy sent extrude_cali_flag: 2 and
  nozzle_offset_cali: 2 per the "1 = run, 2 = skip" reading inherited from
  the #1478 / #1682 work. Live test on H2D 01.x: with both toggles off,
  the stg queue still scheduled stage 8 ("Calibrating dynamic flow") and
  stage 39 ("Nozzle offset calibration"), and the printer ran both at
  print start.

  Root cause: 2 means "skip the explicit pass but still apply / verify
  stored PA via the calibration stage" — close to a no-op K-factor wise
  but the per-print physical sequence still runs. 0 is the encoding that
  actually drops the stage from stg. A BambuStudio Send-dialog capture
  on the same firmware showed 0 for both fields when the user unchecked
  the calibrations — contradicting the #1478 commit's read of "BambuStudio
  never sends 0."

  Fix:
  - extrude_cali_flag = 1 if flow_cali else 0  (was: else 2)
  - nozzle_offset_cali = 1 if (nozzle_offset_cali and is_dual_nozzle) else 0
    (was: else 2)

  Dual-nozzle gate stays; single-nozzle prints continue to force-skip the
  nozzle-offset cali their head doesn't support (#1682). The 1 (run)
  branch is unchanged.

  Verified live on the same H2D after the patch: stg dropped to
  [29, 13, 4, 14, 3] (cooling, homing, filament change, nozzle cleaning,
  vibration comp). Stages 8 and 39 gone.

  Vibration compensation is NOT fixed by this commit: vibration_cali is a
  bool in our and BambuStudio's wire format, and the H2D firmware queues
  stage 3 regardless of the false value. Firmware-side, not solvable at
  the dispatch layer with the current field. Filed as a follow-up.
maziggy 2 mesiacov pred
rodič
commit
0de71ca412

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
CHANGELOG.md


+ 17 - 10
backend/app/services/bambu_mqtt.py

@@ -3459,17 +3459,24 @@ class BambuMQTTClient:
                     "use_ams": use_ams,
                     "use_ams": use_ams,
                     "cfg": "0",
                     "cfg": "0",
                     # extrude_cali_flag gates flow-dynamics calibration:
                     # extrude_cali_flag gates flow-dynamics calibration:
-                    # 1 = run it, 2 = skip and reuse the stored PA value.
-                    # BambuStudio always pairs this with flow_cali and never
-                    # sends 0; a hardcoded 0 made the printer skip calibration
-                    # regardless of the flow_cali toggle (#1478).
-                    "extrude_cali_flag": 1 if flow_cali else 2,
+                    # 1 = run it, 0 = printer skips entirely (#1478 evidence).
+                    # 2 = "skip and reuse stored PA" was previously believed to
+                    # suppress the stage too, but #1721 testing on H2D 01.x
+                    # showed stage 8 ("Calibrating dynamic flow") still gets
+                    # queued when we send 2. A real BambuStudio Send-dialog
+                    # capture today also showed 0 when the user disables flow
+                    # calibration. Going with 0 to actually suppress the
+                    # pre-print calibration stage.
+                    "extrude_cali_flag": 1 if flow_cali else 0,
                     "extrude_cali_manual_mode": 0,
                     "extrude_cali_manual_mode": 0,
-                    # 1 = run, 2 = skip. BambuStudio exposes the toggle only for
-                    # dual-nozzle machines (H2D/H2D Pro/H2C/X2D); on single-nozzle
-                    # printers we always send 2 so firmware never wastes cycles
-                    # on a calibration their head doesn't support (#1682).
-                    "nozzle_offset_cali": 1 if (nozzle_offset_cali and is_dual_nozzle) else 2,
+                    # 1 = run, 0 = skip (matches BambuStudio's wire today). The
+                    # earlier 2 = "skip" reading from #1682 didn't actually
+                    # suppress stage 39 ("Nozzle offset calibration") on H2D
+                    # 01.x — captured live in #1721. BambuStudio exposes the
+                    # toggle only for dual-nozzle (H2D/H2D Pro/H2C/X2D); single-
+                    # nozzle prints still resolve to 0 here so firmware never
+                    # runs a calibration the head doesn't support.
+                    "nozzle_offset_cali": 1 if (nozzle_offset_cali and is_dual_nozzle) else 0,
                     "subtask_name": filename.replace(".3mf", "").replace(".gcode", ""),
                     "subtask_name": filename.replace(".3mf", "").replace(".gcode", ""),
                     "profile_id": "0",
                     "profile_id": "0",
                     "project_id": submission_id,
                     "project_id": submission_id,

+ 21 - 15
backend/tests/unit/services/test_bambu_mqtt.py

@@ -3826,8 +3826,12 @@ class TestStartPrintAmsMapping:
         cmd = self._get_published_command(mqtt_client)
         cmd = self._get_published_command(mqtt_client)
         assert cmd["timelapse"] is True
         assert cmd["timelapse"] is True
         assert cmd["flow_cali"] is False
         assert cmd["flow_cali"] is False
-        # flow_cali off → extrude_cali_flag=2 (skip, reuse stored PA value).
-        assert cmd["extrude_cali_flag"] == 2
+        # flow_cali off → extrude_cali_flag=0 (firmware actually skips the
+        # pre-print calibration stage). #1721 test on H2D 01.x showed `2`
+        # didn't suppress stage 8 ("Calibrating dynamic flow") despite the
+        # earlier "skip and reuse stored PA" reading; `0` does — verified
+        # live against the stg queue.
+        assert cmd["extrude_cali_flag"] == 0
 
 
     def test_h2s_single_external_spool_uses_main_id(self, mqtt_client):
     def test_h2s_single_external_spool_uses_main_id(self, mqtt_client):
         """H2S is single-nozzle (#1386): external spool (254) → ams_id=255.
         """H2S is single-nozzle (#1386): external spool (254) → ams_id=255.
@@ -3888,18 +3892,18 @@ class TestStartPrintAmsMapping:
         assert cmd["extrude_cali_flag"] == 1
         assert cmd["extrude_cali_flag"] == 1
 
 
     def test_nozzle_offset_cali_default_is_skip(self, mqtt_client):
     def test_nozzle_offset_cali_default_is_skip(self, mqtt_client):
-        """Default `nozzle_offset_cali=False` → wire value `2` (skip).
+        """Default `nozzle_offset_cali=False` → wire value `0` (skip).
 
 
-        Matches the legacy behavior on every model: BambuStudio sends `2`
-        unless the user enabled the toggle for a dual-nozzle machine. The
-        legacy hardcoded value before #1682 was `2` for everyone — this
-        test pins that default so we don't regress.
+        #1721 H2D 01.x test: `2` ("skip") didn't actually suppress stage 39
+        ("Nozzle offset calibration") — the stage stayed in the `stg` queue
+        and ran at print start. `0` does suppress it (verified live). Matches
+        what a BambuStudio Send-dialog echo on the same firmware shows.
         """
         """
         mqtt_client.model = "P1S"
         mqtt_client.model = "P1S"
         mqtt_client.start_print("test.3mf")
         mqtt_client.start_print("test.3mf")
 
 
         cmd = self._get_published_command(mqtt_client)
         cmd = self._get_published_command(mqtt_client)
-        assert cmd["nozzle_offset_cali"] == 2
+        assert cmd["nozzle_offset_cali"] == 0
 
 
     def test_nozzle_offset_cali_ignored_on_single_nozzle(self, mqtt_client):
     def test_nozzle_offset_cali_ignored_on_single_nozzle(self, mqtt_client):
         """Single-nozzle printer: `nozzle_offset_cali=True` is silently dropped.
         """Single-nozzle printer: `nozzle_offset_cali=True` is silently dropped.
@@ -3909,20 +3913,21 @@ class TestStartPrintAmsMapping:
         behind `nozzle_count==2`. Even if a stale queue item from when the
         behind `nozzle_count==2`. Even if a stale queue item from when the
         printer was misidentified as dual carries the flag, the MQTT layer
         printer was misidentified as dual carries the flag, the MQTT layer
         must downgrade it so firmware never tries to calibrate a head it
         must downgrade it so firmware never tries to calibrate a head it
-        doesn't have (#1682).
+        doesn't have (#1682). `0` is the actually-honoured skip value
+        post-#1721; old `2` left the stage in the queue.
         """
         """
         mqtt_client.model = "P1S"
         mqtt_client.model = "P1S"
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=True)
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=True)
 
 
         cmd = self._get_published_command(mqtt_client)
         cmd = self._get_published_command(mqtt_client)
-        assert cmd["nozzle_offset_cali"] == 2
+        assert cmd["nozzle_offset_cali"] == 0
 
 
     def test_nozzle_offset_cali_honored_on_dual_nozzle(self, mqtt_client):
     def test_nozzle_offset_cali_honored_on_dual_nozzle(self, mqtt_client):
         """Dual-nozzle printer (H2D): `nozzle_offset_cali=True` → wire value `1`.
         """Dual-nozzle printer (H2D): `nozzle_offset_cali=True` → wire value `1`.
 
 
         H2D is in `DUAL_NOZZLE_MODELS`. The toggle controls whether the
         H2D is in `DUAL_NOZZLE_MODELS`. The toggle controls whether the
         printer runs the nozzle-offset calibration pass before the print
         printer runs the nozzle-offset calibration pass before the print
-        starts. `1`=run, `2`=skip — matches BambuStudio's encoding (#1682).
+        starts. `1`=run (#1682).
         """
         """
         mqtt_client.model = "H2D"
         mqtt_client.model = "H2D"
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=True)
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=True)
@@ -3931,16 +3936,17 @@ class TestStartPrintAmsMapping:
         assert cmd["nozzle_offset_cali"] == 1
         assert cmd["nozzle_offset_cali"] == 1
 
 
     def test_nozzle_offset_cali_false_on_dual_nozzle(self, mqtt_client):
     def test_nozzle_offset_cali_false_on_dual_nozzle(self, mqtt_client):
-        """Dual-nozzle printer (H2D Pro): `nozzle_offset_cali=False` → `2` (skip).
+        """Dual-nozzle printer (H2D Pro): `nozzle_offset_cali=False` → `0` (skip).
 
 
-        Same wire encoding as legacy. Critical for users like #1682 who run
-        diamond nozzles and need to keep the calibration off.
+        Critical for users like #1682 who run diamond nozzles and need to
+        keep the calibration off. The wire value flipped from `2` to `0` in
+        #1721 after the H2D test showed `2` didn't actually suppress.
         """
         """
         mqtt_client.model = "H2D Pro"
         mqtt_client.model = "H2D Pro"
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=False)
         mqtt_client.start_print("test.3mf", nozzle_offset_cali=False)
 
 
         cmd = self._get_published_command(mqtt_client)
         cmd = self._get_published_command(mqtt_client)
-        assert cmd["nozzle_offset_cali"] == 2
+        assert cmd["nozzle_offset_cali"] == 0
 
 
 
 
 class TestStartPrintUniqueIdentityFields:
 class TestStartPrintUniqueIdentityFields:

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov