Files
Bambu-Run/tests/test_multi_ams_collection.py

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