test_h3c_mounted_hotend_temp_3442.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """The H3C's nozzle temperature is the mounted hotend's (#3442).
  2. The H3C swaps hotends on its one extruder. After a swap, ``nozzle_temper``
  3. keeps reporting the hotend just put back in the rack, while the mounted one's
  4. temperature is in ``device.extruder.info[0].temp`` (target << 16 | current),
  5. which Bambu Studio reads over ``nozzle_temper`` (DevExtruderSystem ParseV2_0).
  6. """
  7. import pytest
  8. from backend.app.services.bambu_mqtt import BambuMQTTClient
  9. from backend.tests.unit.test_h3c_ams3h import _frame
  10. pytestmark = pytest.mark.unit
  11. def _encoded(target: int, current: int) -> int:
  12. return target * 65536 + current
  13. def _h3c_frame(extruder_temp: int, nozzle_temper: float = 31.0, nozzle_target: float = 0.0) -> dict:
  14. frame = _frame()
  15. frame["device"]["extruder"]["info"][0]["temp"] = extruder_temp
  16. frame.update(nozzle_temper=nozzle_temper, nozzle_target_temper=nozzle_target)
  17. return frame
  18. def _client(model: str) -> BambuMQTTClient:
  19. return BambuMQTTClient(ip_address="10.0.0.1", serial_number="SN", access_code="c", model=model)
  20. class TestH3C:
  21. def test_the_mounted_hotend_is_shown_not_the_racked_one(self):
  22. client = _client("H3C")
  23. client._process_message({"print": _h3c_frame(_encoded(220, 215))})
  24. temps = client.state.temperatures
  25. assert (temps["nozzle"], temps["nozzle_target"], temps["nozzle_heating"]) == (215.0, 220.0, True)
  26. def test_a_delta_with_only_nozzle_temper_keeps_it(self):
  27. client = _client("H3C")
  28. client._process_message({"print": _h3c_frame(_encoded(220, 220))})
  29. client._process_message({"print": {"nozzle_temper": 40.0, "nozzle_target_temper": 0.0}})
  30. temps = client.state.temperatures
  31. assert (temps["nozzle"], temps["nozzle_target"]) == (220.0, 220.0)
  32. def test_a_cold_hotend_reads_direct(self):
  33. client = _client("H3C")
  34. client._process_message({"print": _h3c_frame(28)})
  35. temps = client.state.temperatures
  36. assert (temps["nozzle"], temps["nozzle_target"], temps["nozzle_heating"]) == (28.0, 0.0, False)
  37. def test_a_rack_printer_of_an_unknown_model_too(self):
  38. # Told apart by its AMS 3H and per-hotend inputs, like the tray ids.
  39. client = _client("")
  40. client._process_message({"print": _h3c_frame(_encoded(220, 215))})
  41. assert client.state.temperatures["nozzle"] == 215.0
  42. def test_an_h3c_without_ams_data_yet_ignores_nozzle_temper(self):
  43. client = _client("N10")
  44. client._process_message({"print": {"nozzle_temper": 40.0, "nozzle_target_temper": 0.0}})
  45. assert "nozzle" not in client.state.temperatures
  46. class TestOtherPrinters:
  47. def test_single_nozzle_keeps_nozzle_temper(self):
  48. # A one-extruder report on a printer without a rack changes nothing.
  49. client = _client("P2S")
  50. client._process_message(
  51. {
  52. "print": {
  53. "nozzle_temper": 200.0,
  54. "nozzle_target_temper": 210.0,
  55. "device": {"extruder": {"state": 1, "info": [{"id": 0, "temp": _encoded(250, 245)}]}},
  56. }
  57. }
  58. )
  59. temps = client.state.temperatures
  60. assert (temps["nozzle"], temps["nozzle_target"]) == (200.0, 210.0)
  61. def test_h2d_unchanged(self):
  62. client = _client("H2D")
  63. client._process_message(
  64. {
  65. "print": {
  66. "nozzle_temper": 33.0,
  67. "device": {
  68. "extruder": {
  69. "state": 2,
  70. "info": [{"id": 0, "temp": _encoded(220, 210)}, {"id": 1, "temp": _encoded(250, 240)}],
  71. }
  72. },
  73. }
  74. }
  75. )
  76. temps = client.state.temperatures
  77. assert (temps["nozzle"], temps["nozzle_target"]) == (240.0, 250.0)
  78. assert (temps["nozzle_2"], temps["nozzle_2_target"]) == (210.0, 220.0)