mirror of
https://github.com/RunLit/Bambu-Run.git
synced 2026-06-22 22:19:03 +01:00
Add multi-AMS support: per-unit snapshot/usage tracking, grouped dashboard panels with real type labels, and dual-nozzle card UX fixes. Fixes a real-world AMS info-code parsing bug found by inspecting live H2C data.
This commit is contained in:
104
tests/test_multi_ams_collection.py
Normal file
104
tests/test_multi_ams_collection.py
Normal file
@@ -0,0 +1,104 @@
|
||||
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
|
||||
Reference in New Issue
Block a user