mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 21:47:39 +02:00
fix(inventory): break the Reset-Slot deadlock on A1 Mini BMCU / P1S Standard AMS (#1322)
The original #1322 fix widened empty-slot detection to (state == 11 OR tray_type != ""), which closed the configured-slot reconfig case but didn't help the "Reset Slot on printer screen with spool still inserted" flow. On these firmwares the AMS reports state=3, tray_type="" after a Reset Slot regardless of whether a spool is physically present, so the empty-detection still decided "empty", skipped MQTT, marked pending — and on_ams_change replay never re-fired because the AMS never reported any state change either. RosdasHH traced the path: tray_state=3 falls into the else: branch, slot_is_empty = not (fingerprint_type and fingerprint_type.strip()), fingerprint_type is "", so slot_is_empty=True, MQTT is skipped, and the slot stays unconfigured forever. He verified empirically that removing the gate makes the firmware accept the push when a spool is physically present. Drop the tray_type fallback entirely. Only state in {9, 10} (firmware's explicit "no spool" / "spool present but no feed") short-circuits the MQTT publish. Every other state — including 3 (default-idle, ambiguous) and missing-state (older firmwares) — attempts the publish. Bambu's "firmware silently drops on empty slots" behavior makes the worst case a no-op for a truly-empty slot, and on_ams_change replay still serves as the safety net for state=9/10 slots whose spools get inserted later. pending_config is now (slot_is_definitely_empty OR not configured) so a printer-offline / no-client publish failure correctly flags the assignment for replay instead of falsely showing "configured".
This commit is contained in:
@@ -1270,36 +1270,40 @@ async def assign_spool(
|
||||
|
||||
# 4. Auto-configure AMS slot via MQTT.
|
||||
#
|
||||
# Skip the publish entirely when the target slot is empty: Bambu firmware
|
||||
# silently drops ams_filament_setting / extrusion_cali_sel for unloaded
|
||||
# slots (there is no filament context for the cali_idx to attach to). The
|
||||
# SpoolAssignment row is preserved with an empty fingerprint_type, which
|
||||
# acts as the "pending config" marker — when the spool is physically
|
||||
# inserted later, on_ams_change re-fires the full configuration. This is
|
||||
# the SpoolBuddy primary workflow: weigh-then-assign before insertion.
|
||||
# Only suppress the publish when the firmware's *explicit* empty signal
|
||||
# (state ∈ {9, 10}) is set — "no spool" / "spool present but no feed".
|
||||
# Every other state, including state=3 (the default idle on A1 Mini BMCU /
|
||||
# P1S Standard AMS for both loaded and unconfigured slots) and missing
|
||||
# state (older firmwares), is treated as the user's assertion that a
|
||||
# spool is in the slot and we attempt the MQTT push.
|
||||
#
|
||||
# Empty-detection: priority order is the firmware's explicit signals
|
||||
# first, then a tray_type fallback for firmwares that don't use the full
|
||||
# state enum meaningfully.
|
||||
# - state == 9 → empty (firmware says "no spool")
|
||||
# - state == 10 → empty (firmware says "spool present but no feed")
|
||||
# - state == 11 → loaded (firmware says "filament in extruder")
|
||||
# - any other state value, including 3 (A1 Mini BMCU / P1S Standard AMS
|
||||
# always report 3) or None (older firmwares omit the field), falls
|
||||
# back to tray_type: configured ⇒ loaded, empty ⇒ empty (#1322).
|
||||
# The tray_type fallback for state==3 fixes the reported bug. The 9/10
|
||||
# branch keeps existing behavior intact even if the MQTT relay's
|
||||
# auto-clearing of tray_type ever fails to fire — the firmware's
|
||||
# explicit "empty" signal stays authoritative over stale metadata.
|
||||
if tray_state == 9 or tray_state == 10:
|
||||
slot_is_empty = True
|
||||
elif tray_state == 11:
|
||||
slot_is_empty = False
|
||||
else:
|
||||
slot_is_empty = not (fingerprint_type and fingerprint_type.strip())
|
||||
# The pre-existing "skip when slot looks empty" guard read state=3 +
|
||||
# tray_type="" as "empty" and skipped MQTT. On these firmwares that
|
||||
# combination is the post-"Reset Slot" state with the spool still
|
||||
# physically inserted — there is NO AMS signal that distinguishes it
|
||||
# from a truly-empty slot, so the guard created a deadlock: MQTT never
|
||||
# fired, the AMS never reported any change (because nothing changed
|
||||
# physically), and on_ams_change replay therefore never re-fired the
|
||||
# config either. Reporter (#1322 follow-up by @RosdasHH) verified
|
||||
# empirically that removing the guard makes the slot configure
|
||||
# correctly because Bambu firmware DOES accept the push for a
|
||||
# physically-loaded slot, even when tray_type is "" and state is 3.
|
||||
#
|
||||
# Trade-off for the truly-empty slot case: firmware drops the push
|
||||
# silently (per Bambu's documented behavior), the SpoolAssignment row
|
||||
# still has empty fingerprint_type because nothing in the assign path
|
||||
# updates that column, and on_ams_change at main.py:1031-1054 still
|
||||
# fires the deferred config when a spool eventually appears. So the
|
||||
# SpoolBuddy weigh-then-assign-before-insert workflow continues to
|
||||
# work — just without the optimization of skipping a no-op MQTT call.
|
||||
#
|
||||
# state ∈ {9, 10} stays as an explicit short-circuit so we don't churn
|
||||
# a doomed MQTT push when the firmware has positively confirmed "no
|
||||
# spool" — and to keep the on_ams_change replay path as the single
|
||||
# source of truth for those slots.
|
||||
slot_is_definitely_empty = tray_state == 9 or tray_state == 10
|
||||
configured = False
|
||||
pending_config = slot_is_empty
|
||||
if not slot_is_empty:
|
||||
if not slot_is_definitely_empty:
|
||||
try:
|
||||
configured = await apply_spool_to_slot_via_mqtt(
|
||||
db=db,
|
||||
@@ -1313,6 +1317,11 @@ async def assign_spool(
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("MQTT auto-configure failed for spool %d: %s", spool.id, e)
|
||||
# pending_config is the "config not landed yet" UI marker. True when the
|
||||
# firmware said empty, OR when MQTT couldn't actually publish (printer
|
||||
# offline, no client, transient failure). on_ams_change replay re-fires
|
||||
# the config in either case once the AMS reports a non-empty fingerprint.
|
||||
pending_config = slot_is_definitely_empty or not configured
|
||||
|
||||
# Return assignment with spool data
|
||||
result = await db.execute(
|
||||
|
||||
Reference in New Issue
Block a user