diff --git a/BlocksScreen/devices/amu/models.py b/BlocksScreen/devices/amu/models.py index 804d6925..7ef9a875 100644 --- a/BlocksScreen/devices/amu/models.py +++ b/BlocksScreen/devices/amu/models.py @@ -4,10 +4,10 @@ class GateStatus(IntEnum): - UNKNOWN = 0 + EMPTY = 0 AVAILABLE = 1 AVAILABLE_FROM_BUFFER = 2 - EMPTY = -1 + UNKNOWN = -1 class FilamentPos(IntEnum): diff --git a/BlocksScreen/lib/panels/filamentTab.py b/BlocksScreen/lib/panels/filamentTab.py index ae9453fa..8a718897 100644 --- a/BlocksScreen/lib/panels/filamentTab.py +++ b/BlocksScreen/lib/panels/filamentTab.py @@ -56,6 +56,7 @@ def __init__( self._spool_id_map: dict[str, dict] = {} self._current_field: QtWidgets.QLineEdit | None = None self._color_target_field = None + self._material_filter: str | None = None self.moonraker_run = True self.amu_manager.mmu_state_changed.connect(self.on_mmu_state_changed) @@ -512,7 +513,6 @@ def _add_row(title_text: str) -> QtWidgets.QLabel: def handle_skip_button(self): gate = self.pre_gate_idx.get("gate", 0) - self.popup.hide() self._reset_popup() self.run_gcode.emit( f"MMU_GATE_MAP GATE={gate} MATERIAL=N/A NAME=N/A COLOR=FFFFFF SPOOLID=-1 TEMP=250 QUIET=1" @@ -525,6 +525,12 @@ def handle_skip_button(self): finally: self._popup_callback = None + self.popup.hide() + self._material_filter = None + self._add_spool_page.setFilter(None) + self._add_filament_page.setData("---", 0) + self.handle_popup() + def handle_popup(self, force=False): """Handles showing the popup for pre-gate filament detection. If multiple gates trigger, they will be queued and shown one at a time. @@ -602,6 +608,7 @@ def on_popup_accept(self): self._reset_popup() self.popup.hide() + self._material_filter = None self._add_spool_page.setFilter(None) self._add_filament_page.setData("---", 0) self.handle_popup() @@ -700,6 +707,7 @@ def _on_spool_selected(self) -> None: self.accept_btn.setEnabled(False) self.popup.hide() + self._material_filter = None self._add_spool_page.setFilter(None) self._add_filament_page.setData("---", 0) self.run_gcode.emit( @@ -713,6 +721,8 @@ def _on_spool_selected(self) -> None: finally: self._popup_callback = None + self.handle_popup() + def reset_spool_info(self): self.filament_name_label.setText("N/A") self.material_label.setText("N/A") @@ -818,21 +828,30 @@ def _on_color_selected(self, hex_str: str) -> None: self._color_target_field.editingFinished.emit() self._color_target_field = None + def _clear_gate_map(self, gate_info) -> None: + """Blank a gate's map entry when its filament runs out.""" + if gate_info.spool_id == -1 and gate_info.material in (None, "", "N/A"): + return # already blank + + self.run_gcode.emit( + f"MMU_GATE_MAP GATE={gate_info.index} MATERIAL= TEMP=-1 COLOR= SPOOLID=-1 NAME= QUIET=1" + ) + def on_mmu_state_changed(self, mmu_state): """Handles changes in the MMU state from the AMU manager to update the UI and show the load panel when loading/unloading.""" for gate_info in mmu_state.gates: previous_state = self._previous_gate_states.get(gate_info.index) - self._previous_gate_states[gate_info.index] = gate_info.status in [ + current_state = gate_info.status in [ GateStatus.AVAILABLE, GateStatus.AVAILABLE_FROM_BUFFER, ] - if ( - previous_state is False - and self._previous_gate_states[gate_info.index] is True - ): + self._previous_gate_states[gate_info.index] = current_state + + if previous_state is False and current_state is True: self.popup_gates.append({"gate": gate_info.index}) - if len(mmu_state.gates) > 1: - self.handle_popup() + self.handle_popup() + elif previous_state is True and gate_info.status == GateStatus.EMPTY: + self._clear_gate_map(gate_info) if not self.amu_configured: if len(mmu_state.gates) > 1: diff --git a/tests/amu/test_models_unit.py b/tests/amu/test_models_unit.py index ee969cc0..66ce4bbd 100644 --- a/tests/amu/test_models_unit.py +++ b/tests/amu/test_models_unit.py @@ -11,10 +11,11 @@ class TestGateStatus: def test_values(self) -> None: - assert GateStatus.UNKNOWN == 0 + assert GateStatus.EMPTY == 0 assert GateStatus.AVAILABLE == 1 assert GateStatus.AVAILABLE_FROM_BUFFER == 2 - assert GateStatus.EMPTY == -1 + assert GateStatus.UNKNOWN == -1 + def test_is_int_enum(self) -> None: assert isinstance(GateStatus.AVAILABLE, int) @@ -115,7 +116,7 @@ def _full_status(self, num_gates=2) -> dict: "reason_for_pause": "", "has_bypass": False, "spoolman_support": "push", - "gate_status": [1, -1], + "gate_status": [1, 0], "gate_material": ["PLA", ""], "gate_color": ["ff0000", ""], "gate_color_rgb": [(1.0, 0.0, 0.0), (0.0, 0.0, 0.0)],