mirror of
https://github.com/RunLit/Bambu-Run.git
synced 2026-06-22 14:09:04 +01:00
105 lines
3.8 KiB
Python
105 lines
3.8 KiB
Python
import pytest
|
|
|
|
from bambu_run.management.commands.bambu_collector import Command, DeviceSession, resolve_printer_device
|
|
from bambu_run.models import Filament, FilamentSnapshot, FilamentUsage, PrinterMetrics
|
|
|
|
|
|
class FakeClient:
|
|
"""Stub in place of BambuPrinter — returns canned snapshots, no real MQTT."""
|
|
|
|
def __init__(self, snapshots):
|
|
self._snapshots = snapshots
|
|
self._index = 0
|
|
self._client = None
|
|
|
|
def get_snapshot(self):
|
|
snap = self._snapshots[min(self._index, len(self._snapshots) - 1)]
|
|
self._index += 1
|
|
return snap
|
|
|
|
|
|
def make_session(device_id, name, snapshots):
|
|
printer = resolve_printer_device(device_id, {"name": name, "dev_product_name": "H2C"})
|
|
return DeviceSession(device_id=device_id, client=FakeClient(snapshots), printer=printer)
|
|
|
|
|
|
def two_unit_tray0_snapshot():
|
|
"""Two AMS units (AMS unit_id=0, AMS HT unit_id=128) both report tray_id=0,
|
|
with different filament types loaded — these must not collide."""
|
|
return {
|
|
"gcode_state": "IDLE",
|
|
"ams_units": [
|
|
{"unit_id": "0", "ams_type": "AMS", "humidity": 30, "temp": 25.0},
|
|
{"unit_id": "128", "ams_type": "AMS HT", "humidity": 20, "temp": 60.0},
|
|
],
|
|
"filaments": [
|
|
{
|
|
"tray_id": 0, "type": "PLA", "sub_type": "PLA Basic", "color": "FF0000FF",
|
|
"tray_uuid": "UUID-UNIT0-TRAY0",
|
|
"remain_percent": 80, "ams_unit_id": 0, "ams_type": "AMS",
|
|
},
|
|
{
|
|
"tray_id": 0, "type": "PA-CF", "sub_type": "PA6-CF", "color": "00FF00FF",
|
|
"tray_uuid": "UUID-UNIT128-TRAY0",
|
|
"remain_percent": 50, "ams_unit_id": 128, "ams_type": "AMS HT",
|
|
},
|
|
],
|
|
}
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_two_ams_units_with_same_tray_id_create_distinct_snapshots():
|
|
session = make_session("SERIAL-A", "Printer A", [two_unit_tray0_snapshot()])
|
|
|
|
cmd = Command()
|
|
cmd.verbose = False
|
|
cmd._collect_printer_data(session)
|
|
|
|
metric = PrinterMetrics.objects.get(device=session.printer)
|
|
snapshots = FilamentSnapshot.objects.filter(printer_metric=metric).order_by("ams_unit_id")
|
|
|
|
assert snapshots.count() == 2
|
|
|
|
ams_snap, ht_snap = snapshots
|
|
assert ams_snap.tray_id == 0
|
|
assert ams_snap.ams_unit_id == 0
|
|
assert ams_snap.ams_type == "AMS"
|
|
assert ams_snap.type == "PLA"
|
|
|
|
assert ht_snap.tray_id == 0
|
|
assert ht_snap.ams_unit_id == 128
|
|
assert ht_snap.ams_type == "AMS HT"
|
|
assert ht_snap.type == "PA-CF"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_filament_usage_matches_correct_unit_when_tray_ids_collide():
|
|
start_snapshot = two_unit_tray0_snapshot()
|
|
start_snapshot.update({"gcode_state": "RUNNING", "subtask_name": "job_1", "print_percent": 1, "tray_now": "0"})
|
|
|
|
end_snapshot = two_unit_tray0_snapshot()
|
|
end_snapshot["filaments"][0]["remain_percent"] = 70 # AMS unit 0 consumed
|
|
end_snapshot["filaments"][1]["remain_percent"] = 50 # AMS HT unit 128 untouched
|
|
end_snapshot.update({"gcode_state": "FINISH", "subtask_name": "job_1", "print_percent": 100})
|
|
|
|
session = make_session("SERIAL-A", "Printer A", [start_snapshot, end_snapshot])
|
|
|
|
cmd = Command()
|
|
cmd.verbose = False
|
|
cmd._collect_printer_data(session)
|
|
cmd._collect_printer_data(session)
|
|
|
|
usages = FilamentUsage.objects.filter(print_job__device=session.printer).order_by("ams_unit_id")
|
|
# Both units reported tray_id=0 with a tracked filament loaded throughout the
|
|
# job — usage is recorded per physical unit, not collapsed into one ambiguous row.
|
|
assert usages.count() == 2
|
|
|
|
ams_usage, ht_usage = usages
|
|
assert ams_usage.ams_unit_id == 0
|
|
assert ams_usage.starting_percent == 80
|
|
assert ams_usage.ending_percent == 70
|
|
|
|
assert ht_usage.ams_unit_id == 128
|
|
assert ht_usage.starting_percent == 50
|
|
assert ht_usage.ending_percent == 50
|