mirror of
https://github.com/RunLit/Bambu-Run.git
synced 2026-06-22 22:19:03 +01:00
101 lines
4.1 KiB
Python
101 lines
4.1 KiB
Python
from bambu_run.mqtt_client import PrinterState
|
|
|
|
|
|
def real_nozzle_payload():
|
|
"""Real captured device.nozzle payload from a live H2C with a Vortek rack
|
|
(1x AMS, 1x AMS 2 Pro, 1x AMS HT physically connected — unrelated here).
|
|
SN/used-time cross-checked against the user's Bambu Studio Hotends Info table."""
|
|
return {
|
|
"exist": 3997699,
|
|
"src_id": 17,
|
|
"tar_id": 17,
|
|
"state": 0,
|
|
"info": [
|
|
{"id": 21, "sn": "20D06A5B2918952", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFA01", "color_m": "FFFFFFFF", "p_t": 11472, "wear": 128.0, "stat": 0, "tm": 350},
|
|
{"id": 1, "sn": "N/A", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "", "color_m": "00000000", "p_t": 0, "wear": 0.0, "stat": 0, "tm": 0},
|
|
{"id": 16, "sn": "20D06A5B2919219", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFA01", "color_m": "A3D8E1FF", "p_t": 105386, "wear": 128.0, "stat": 0, "tm": 350},
|
|
{"id": 20, "sn": "20D06A590610257", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFG01", "color_m": "00000000", "p_t": 81506, "wear": 128.0, "stat": 0, "tm": 350},
|
|
{"id": 18, "sn": "20D06A591506263", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFA01", "color_m": "DE4343FF", "p_t": 30962, "wear": 128.0, "stat": 0, "tm": 350},
|
|
{"id": 0, "sn": "20D06A5C0426280", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFA00", "color_m": "FEC600FF", "p_t": 93490, "wear": 128.0, "stat": 0, "tm": 350},
|
|
{"id": 19, "sn": "20D06A5C0207881", "type": "HS01", "diameter": 0.4,
|
|
"fila_id": "GFA01", "color_m": "DE4343FF", "p_t": 1430, "wear": 128.0, "stat": 0, "tm": 350},
|
|
],
|
|
}
|
|
|
|
|
|
def make_data(nozzle_payload):
|
|
return {"print": {"gcode_state": "IDLE", "device": {"nozzle": nozzle_payload}}}
|
|
|
|
|
|
def test_snapshot_includes_one_hotend_per_nozzle_info_entry():
|
|
state = PrinterState.from_mqtt_data(make_data(real_nozzle_payload()))
|
|
snapshot = state.get_snapshot()
|
|
|
|
assert len(snapshot["hotends"]) == 7
|
|
|
|
|
|
def test_hotend_fields_extracted_correctly():
|
|
state = PrinterState.from_mqtt_data(make_data(real_nozzle_payload()))
|
|
snapshot = state.get_snapshot()
|
|
|
|
by_sn = {h["serial_number"]: h for h in snapshot["hotends"]}
|
|
h = by_sn["20D06A5B2919219"]
|
|
|
|
assert h["raw_id"] == 16
|
|
assert h["nozzle_type"] == "HS01"
|
|
assert h["diameter"] == 0.4
|
|
assert h["fila_id"] == "GFA01"
|
|
assert h["color"] == "A3D8E1" # alpha stripped
|
|
assert h["used_time_seconds"] == 105386
|
|
assert h["wear_percent"] == 100.0 # 128/128*100
|
|
assert h["is_empty"] is False
|
|
|
|
|
|
def test_id_zero_is_toolhead_and_resolves_slot_number():
|
|
state = PrinterState.from_mqtt_data(make_data(real_nozzle_payload()))
|
|
snapshot = state.get_snapshot()
|
|
|
|
by_sn = {h["serial_number"]: h for h in snapshot["hotends"]}
|
|
toolhead = by_sn["20D06A5C0426280"]
|
|
|
|
assert toolhead["raw_id"] == 0
|
|
assert toolhead["is_toolhead"] is True
|
|
assert toolhead["slot_number"] is None # true bay address hidden while id==0 sentinel
|
|
|
|
|
|
def test_rack_bay_ids_resolve_to_slot_numbers_one_through_six():
|
|
state = PrinterState.from_mqtt_data(make_data(real_nozzle_payload()))
|
|
snapshot = state.get_snapshot()
|
|
|
|
by_sn = {h["serial_number"]: h for h in snapshot["hotends"]}
|
|
|
|
assert by_sn["20D06A5B2919219"]["slot_number"] == 1 # raw_id 16
|
|
assert by_sn["20D06A591506263"]["slot_number"] == 3 # raw_id 18
|
|
assert by_sn["20D06A5C0207881"]["slot_number"] == 4 # raw_id 19
|
|
assert by_sn["20D06A590610257"]["slot_number"] == 5 # raw_id 20
|
|
assert by_sn["20D06A5B2918952"]["slot_number"] == 6 # raw_id 21
|
|
|
|
|
|
def test_empty_bay_with_na_serial_is_flagged_empty():
|
|
state = PrinterState.from_mqtt_data(make_data(real_nozzle_payload()))
|
|
snapshot = state.get_snapshot()
|
|
|
|
by_sn = {h["serial_number"]: h for h in snapshot["hotends"]}
|
|
empty = by_sn["N/A"]
|
|
|
|
assert empty["is_empty"] is True
|
|
assert empty["is_toolhead"] is False
|
|
|
|
|
|
def test_snapshot_hotends_empty_list_when_no_nozzle_payload():
|
|
state = PrinterState.from_mqtt_data({"print": {"gcode_state": "IDLE"}})
|
|
snapshot = state.get_snapshot()
|
|
|
|
assert snapshot["hotends"] == []
|