Просмотр исходного кода

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 месяцев назад
Родитель
Сommit
0de71ca412
3 измененных файлов с 38 добавлено и 25 удалено
  1. 0 0
      CHANGELOG.md
  2. 17 10
      backend/app/services/bambu_mqtt.py
  3. 21 15
      backend/tests/unit/services/test_bambu_mqtt.py

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
CHANGELOG.md


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

@@ -3459,17 +3459,24 @@ class BambuMQTTClient:
                     "use_ams": use_ams,
                     "cfg": "0",
                     # 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,
-                    # 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", ""),
                     "profile_id": "0",
                     "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)
         assert cmd["timelapse"] is True
         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):
         """H2S is single-nozzle (#1386): external spool (254) → ams_id=255.
@@ -3888,18 +3892,18 @@ class TestStartPrintAmsMapping:
         assert cmd["extrude_cali_flag"] == 1
 
     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.start_print("test.3mf")
 
         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):
         """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
         printer was misidentified as dual carries the flag, the MQTT layer
         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.start_print("test.3mf", nozzle_offset_cali=True)
 
         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):
         """Dual-nozzle printer (H2D): `nozzle_offset_cali=True` → wire value `1`.
 
         H2D is in `DUAL_NOZZLE_MODELS`. The toggle controls whether the
         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.start_print("test.3mf", nozzle_offset_cali=True)
@@ -3931,16 +3936,17 @@ class TestStartPrintAmsMapping:
         assert cmd["nozzle_offset_cali"] == 1
 
     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.start_print("test.3mf", nozzle_offset_cali=False)
 
         cmd = self._get_published_command(mqtt_client)
-        assert cmd["nozzle_offset_cali"] == 2
+        assert cmd["nozzle_offset_cali"] == 0
 
 
 class TestStartPrintUniqueIdentityFields:

Некоторые файлы не были показаны из-за большого количества измененных файлов