mirror of
https://github.com/RunLit/Bambu-Run.git
synced 2026-10-21 15:37:38 +01:00
feat(mcp): add get_filament tool
This commit is contained in:
@@ -80,3 +80,36 @@ def _spool_summary(f, include_history):
|
|||||||
for u in f.print_usages.select_related("print_job").order_by("-print_job__start_time")[:3]
|
for u in f.print_usages.select_related("print_job").order_by("-print_job__start_time")[:3]
|
||||||
]
|
]
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
|
|
||||||
|
def get_filament(filament_id: int) -> dict:
|
||||||
|
"""One spool in full, plus its complete print-usage history.
|
||||||
|
|
||||||
|
Usage rows with corrupt consumption (negative, or derived from the -1
|
||||||
|
"unread" sentinel) are returned with consumed_grams null and
|
||||||
|
data_quality "unreliable" rather than dropped -- the print still
|
||||||
|
happened, and hiding it would misstate the spool's history. Raises
|
||||||
|
Filament.DoesNotExist if filament_id is unknown.
|
||||||
|
"""
|
||||||
|
f = Filament.objects.get(id=filament_id)
|
||||||
|
summary = _spool_summary(f, include_history=False)
|
||||||
|
|
||||||
|
usages = []
|
||||||
|
for u in f.print_usages.select_related("print_job").order_by("-print_job__start_time"):
|
||||||
|
consumed_percent, consumed_grams, quality = normalize_consumed(
|
||||||
|
u.starting_percent, u.ending_percent, f.initial_weight_grams
|
||||||
|
)
|
||||||
|
usages.append({
|
||||||
|
"job_id": u.print_job_id,
|
||||||
|
"job_name": u.print_job.project_name,
|
||||||
|
"started_at": u.print_job.start_time.isoformat(),
|
||||||
|
"consumed_percent": consumed_percent,
|
||||||
|
"consumed_grams": consumed_grams,
|
||||||
|
"data_quality": quality,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
**summary,
|
||||||
|
"purchase_date": f.purchase_date.isoformat() if f.purchase_date else None,
|
||||||
|
"usage_history": usages,
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import pytest
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from bambu_run.models import Filament, Printer, PrintJob, FilamentUsage
|
from bambu_run.models import Filament, Printer, PrintJob, FilamentUsage
|
||||||
from bambu_run.mcp.filaments import list_filaments
|
from bambu_run.mcp.filaments import list_filaments, get_filament
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -97,3 +97,39 @@ def test_list_filaments_never_exposes_rfid_identifiers():
|
|||||||
entry_str = repr(result["filaments"][0])
|
entry_str = repr(result["filaments"][0])
|
||||||
assert "SECRET-UUID" not in entry_str
|
assert "SECRET-UUID" not in entry_str
|
||||||
assert "SECRET-TAG" not in entry_str
|
assert "SECRET-TAG" not in entry_str
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_filament_returns_full_usage_history_with_data_quality():
|
||||||
|
p = Printer.objects.create(name="RNL-H2C", model="H2C", is_active=True)
|
||||||
|
f = Filament.objects.create(type="ABS", brand="Bambu Lab", color="Black", initial_weight_grams=1000)
|
||||||
|
job1 = PrintJob.objects.create(device=p, project_name="Bracket", start_time=timezone.now(), final_status="FINISH")
|
||||||
|
job2 = PrintJob.objects.create(device=p, project_name="Vase", start_time=timezone.now(), final_status="FINISH")
|
||||||
|
FilamentUsage.objects.create(print_job=job1, filament=f, tray_id=0, starting_percent=80, ending_percent=70)
|
||||||
|
FilamentUsage.objects.create(print_job=job2, filament=f, tray_id=0, starting_percent=-1, ending_percent=100)
|
||||||
|
|
||||||
|
result = get_filament(f.id)
|
||||||
|
|
||||||
|
assert len(result["usage_history"]) == 2
|
||||||
|
reliable = next(u for u in result["usage_history"] if u["job_name"] == "Bracket")
|
||||||
|
unreliable = next(u for u in result["usage_history"] if u["job_name"] == "Vase")
|
||||||
|
assert reliable["data_quality"] == "ok"
|
||||||
|
assert reliable["consumed_grams"] == 100
|
||||||
|
assert unreliable["data_quality"] == "unreliable"
|
||||||
|
assert unreliable["consumed_grams"] is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_filament_never_exposes_purchase_price_or_cost():
|
||||||
|
f = Filament.objects.create(type="PLA", brand="Bambu Lab", color="White", purchase_price=25.50)
|
||||||
|
|
||||||
|
result = get_filament(f.id)
|
||||||
|
|
||||||
|
assert "purchase_price" not in result
|
||||||
|
assert "cost" not in result
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_filament_unknown_id_raises():
|
||||||
|
with pytest.raises(Filament.DoesNotExist):
|
||||||
|
get_filament(999999)
|
||||||
|
|||||||
Reference in New Issue
Block a user