mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 07:33:18 +02:00
Swapping a Bambu spool for one the AMS cannot read left Assign Spool publishing no ams_filament_setting at all. The printer kept showing "?" on its screen and in the slicer, and only Configure, which publishes unconditionally, put anything there. Four places asked the tray's `state` field whether a spool was in the slot. It cannot answer that. An AMS-HT reports its LOADED tray as 9 rather than 11, because it does not feed into a shared buffer the way a 4-slot AMS does -- the merge has skipped its own state heuristic for HT units since #2594 for exactly this reason. And the field is partly our own writing: apply_tray_exist_bits stamps state=9 on every slot whose tray_exist_bits bit is 0, and when the bit comes back it refreshes only the `exists` annotation beside it. Either way the slot sits at exists=True, state=9 until something configures it. That 9 also kept the deferred-configuration replay from firing -- its own "has a spool appeared" test was the same heuristic -- which is the deadlock #1322 removed from the assign path, still in place one step further along. And it is what deleted the assignments in #3100: with the replay never firing, the row kept the empty fingerprint it was stored with, and the first tray report naming a filament was read as a swap. All four now read tray_exist_bits first, which is the mask firmware answers this question with and the one the printer card has drawn its "?" from since #2527. The bit is allowed to overrule an "empty" state and nothing else: a bit reading empty deliberately does not start suppressing pushes that go out today, because the cost of computing a bit position wrong is a slot that silently stops configuring, against a saving of one message firmware would have dropped. A blank tray report from a slot the bit calls occupied no longer unlinks anything, off a print as well as during one, in both inventory modes -- Spoolman's parse_ams_tray calls a tray with no type empty, so a tag-less spool assigned through the UI had its row deleted by the first idle push after it went in. A filament the AMS cannot identify is not a filament that was removed.
46 lines
2.2 KiB
Python
46 lines
2.2 KiB
Python
"""Unit tests for the firmware presence bit helper.
|
|
|
|
#3084: a slot can read ``exists=True, state=9`` — the bit says a spool is in
|
|
it, the state says the opposite — because ``apply_tray_exist_bits`` writes the
|
|
9 itself and never takes it back. Everything downstream has to know which of
|
|
the two to believe, and this helper is the single place that says so.
|
|
"""
|
|
|
|
from backend.app.services.ams_slot_presence import spool_present
|
|
|
|
|
|
class TestSpoolPresent:
|
|
def test_the_bit_is_reported_as_it_stands(self):
|
|
assert spool_present({"id": 0, "exists": True}) is True
|
|
assert spool_present({"id": 0, "exists": False}) is False
|
|
|
|
def test_the_bit_answers_over_a_contradicting_state(self):
|
|
# The #3084 slot: non-Bambu spool swapped in, so the bit is set, while
|
|
# the 9 Bambuddy stamped on the slot when it was briefly empty is still
|
|
# sitting there.
|
|
assert spool_present({"id": 0, "exists": True, "state": 9}) is True
|
|
# And the converse — a spool pulled from a slot the firmware last
|
|
# described as loaded.
|
|
assert spool_present({"id": 0, "exists": False, "state": 11}) is False
|
|
|
|
def test_a_tray_with_no_annotation_answers_nothing(self):
|
|
# vt_tray entries and the VP bridge's cache carry no presence bit, so
|
|
# callers have to fall back to their own reading rather than be handed
|
|
# a guess dressed up as firmware's answer.
|
|
assert spool_present({"id": 0, "state": 11, "tray_type": "PLA"}) is None
|
|
assert spool_present({}) is None
|
|
|
|
def test_a_non_bool_exists_is_not_a_presence_bit(self):
|
|
# Only apply_tray_exist_bits writes this key, and it writes a bool.
|
|
# Anything else reached the dict some other way and is not firmware's
|
|
# answer — 0 and "" would otherwise read as a confident "empty".
|
|
assert spool_present({"exists": 0}) is None
|
|
assert spool_present({"exists": ""}) is None
|
|
assert spool_present({"exists": "true"}) is None
|
|
assert spool_present({"exists": None}) is None
|
|
|
|
def test_a_missing_tray_answers_nothing(self):
|
|
assert spool_present(None) is None
|
|
assert spool_present([]) is None
|
|
assert spool_present("tray") is None
|