Skip to content
4 changes: 4 additions & 0 deletions BlocksScreen.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ timeout: 5000

[usb_manager]
gcodes_dir: ~/printer_data/gcodes/

[filament_presence]
object: cutter_sensor
name: extruder_cutter
195 changes: 104 additions & 91 deletions BlocksScreen/lib/panels/filamentTab.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import enum
from functools import partial


import logging
from lib.printer import Printer
from lib.filament import Filament
from lib.ui.filamentStackedWidget_ui import Ui_filamentStackedWidget

from lib.panels.widgets.popupDialogWidget import Popup
from PyQt6 import QtCore, QtGui, QtWidgets

logger = logging.getLogger(__name__)


class FilamentTypes(enum.Enum):
PLA = Filament(name="PLA", temperature=220)
PETG = Filament(name="PETG", temperature=240)
ABS = Filament(name="ABS", temperature=250)
HIPS = Filament(name="HIPS", temperature=250)
NYLON = Filament(name="NYLON", temperature=270)
TPU = Filament(name="TPU", temperature=230)
UNKNOWN = Filament(name="UNKNOWN", temperature=250)


class FilamentTab(QtWidgets.QStackedWidget):
request_filament_change_page = QtCore.pyqtSignal(name="filament_change_page")
request_filament_load = QtCore.pyqtSignal(name="filament_load_t1")
request_back = QtCore.pyqtSignal(name="request_back")
request_change_page = QtCore.pyqtSignal(int, int, name="request_change_page")
request_change_tab = QtCore.pyqtSignal(int, name="request_change_tab")
request_toolhead_count = QtCore.pyqtSignal(int, name="toolhead_number_received")
run_gcode = QtCore.pyqtSignal(str, name="run_gcode")
call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel")

class FilamentTypes(enum.Enum):
PLA = Filament(name="PLA", temperature=220)

class FilamentStates(enum.Enum):
LOADED = enum.auto()
UNLOADED = enum.auto()
Expand All @@ -43,37 +52,45 @@ def __init__(self, parent: QtWidgets.QWidget, printer: Printer, ws, /) -> None:
self.popup = Popup(self)
self.has_load_unload_objects = None
self._filament_state = self.FilamentStates.UNKNOWN
self._sensor_states = {}
self.filament_type: Filament | None = None
self.filament_type = FilamentTypes.UNKNOWN

cfg = parent.config
if cfg.has_section("filament_presence"):
i = cfg.get_section("filament_presence", None)
self.filament_sensor = i.get("name", str, None)
else:
self.filament_sensor = None
self.panel.filament_page_load_btn.clicked.connect(
partial(self.change_page, self.indexOf(self.panel.load_page))
)
self.panel.custom_filament_header_back_btn.clicked.connect(self.back_button)
self.panel.load_custom_btn.hide()
self.panel.load_header_back_button.clicked.connect(self.back_button)
self.panel.load_pla_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=220)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.PLA)
)
self.panel.load_petg_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=240)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.PETG)
)
self.panel.load_abs_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=250)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.ABS)
)
self.panel.load_hips_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=250)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.HIPS)
)
self.panel.load_nylon_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=270)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.NYLON)
)
self.panel.load_tpu_btn.clicked.connect(
partial(self.load_filament, toolhead=0, temp=230)
partial(self.load_filament, toolhead=0, filament=FilamentTypes.TPU)
)
self.panel.filament_page_unload_btn.clicked.connect(
lambda: self.unload_filament(toolhead=0, temp=250)
)
self.panel.main_back_button.clicked.connect(
lambda: self.request_change_tab.emit(0)
)
self.run_gcode.connect(self.ws.api.run_gcode)
self.printer.extruder_update.connect(self.on_extruder_update)
self.printer.unload_filament_update.connect(self.on_unload_filament)
self.printer.load_filament_update.connect(self.on_load_filament)
self.printer.filament_switch_sensor_update.connect(
Expand All @@ -84,8 +101,18 @@ def __init__(self, parent: QtWidgets.QWidget, printer: Printer, ws, /) -> None:
self.printer.print_stats_update[str, dict].connect(self.on_print_stats_update)
self.printer.print_stats_update[str, float].connect(self.on_print_stats_update)

self.loadignore = True
self.unloadignore = True
self.printer.save_variables_update.connect(self.on_save_variables_update)
self.state = "standby"

def on_save_variables_update(self, save_variables: dict):
"""Handle query response"""
for i in FilamentTypes:
if i.value.name in save_variables["variables"]["filament_type"]:
self.filament_type = i
break
else:
self.filament_type = FilamentTypes.UNKNOWN
self.panel.label_2.setText(self.filament_type.value.name)

@QtCore.pyqtSlot(str, dict, name="on_print_stats_update")
@QtCore.pyqtSlot(str, float, name="on_print_stats_update")
Expand All @@ -94,9 +121,23 @@ def on_print_stats_update(self, field: str, value: dict | float | str) -> None:
"""Handle print stats object update"""
if isinstance(value, str):
if "state" in field:
self.state = value
if value in ("printing", "pausing", "paused", "resuming"):
self.panel.main_back_button.show()
self.panel.spacerItem1.changeSize(
60,
0,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Minimum,
)
if value in ("standby"):
self.loadignore = True
self.unloadignore = True
self.panel.main_back_button.hide()
self.panel.spacerItem1.changeSize(
0,
0,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Minimum,
)

@QtCore.pyqtSlot(str, str, bool, name="on_filament_sensor_update")
def on_filament_sensor_update(self, sensor_name: str, parameter: str, value: bool):
Expand All @@ -106,78 +147,46 @@ def on_filament_sensor_update(self, sensor_name: str, parameter: str, value: boo
self._filament_state = self.FilamentStates.UNKNOWN
self.handle_filament_state()
return
self._sensor_states[sensor_name] = value
if not self._sensor_states:
new_state = self.FilamentStates.UNKNOWN
elif all(self._sensor_states.values()):
new_state = self.FilamentStates.LOADED
else:
new_state = self.FilamentStates.UNLOADED
if self._filament_state != new_state:
self._filament_state = new_state
self.handle_filament_state()
if sensor_name == self.filament_sensor:
if value:
self._filament_state = self.FilamentStates.LOADED
else:
self._filament_state = self.FilamentStates.UNLOADED
return
self.handle_filament_state()

@QtCore.pyqtSlot(str, str, float, name="on_extruder_update")
def on_extruder_update(
self, extruder_name: str, field: str, new_value: float
) -> None:
"""Handle extruder update"""
if not self.isVisible:
return
if not self.loadignore or not self.unloadignore:
if self.target_temp != 0:
if self.current_temp == self.target_temp:
if self.isVisible:
self.call_load_panel.emit(
True, "Extruder heated up \n Please wait"
)
return
if field == "temperature":
self.current_temp = round(new_value, 0)
if self.isVisible:
self.call_load_panel.emit(
True,
f"Heating up ({new_value}/{self.target_temp}) \n Please wait",
)
if field == "target":
self.target_temp = round(new_value, 0)
if self.isVisible:
self.call_load_panel.emit(True, "Heating up \n Please wait")

@QtCore.pyqtSlot(bool, name="on_load_filament")
def on_load_filament(self, status: bool):
@QtCore.pyqtSlot(dict, name="on_load_filament")
def on_load_filament(self, status: dict):
"""Handle load filament object updated"""
if not self.isVisible:
return
if self.loadignore:
return
if status:
self.call_load_panel.emit(True, "Loading Filament")
else:
self.loadignore = True
self.target_temp = 0
self.call_load_panel.emit(False, "")
self._filament_state = self.FilamentStates.LOADED
if "state" in status.keys():
if not status["state"]:
self.target_temp = 0
self.call_load_panel.emit(False, "")
if self.state == "paused":
self.request_change_tab.emit(0)
return
self.call_load_panel.emit(
True, f"Loading Filament\n{status['step'].capitalize()}"
)
self.handle_filament_state()

@QtCore.pyqtSlot(bool, name="on_unload_filament")
def on_unload_filament(self, status: bool):
@QtCore.pyqtSlot(dict, name="on_unload_filament")
def on_unload_filament(self, status: dict):
"""Handle unload filament object updated"""
if not self.isVisible:
return
if self.unloadignore:
return
if status:
self.call_load_panel.emit(True, "Unloading Filament")
else:
self.unloadignore = True
self.call_load_panel.emit(False, "")
self.target_temp = 0
self._filament_state = self.FilamentStates.UNLOADED
if "state" in status.keys():
if not status["state"]:
self.target_temp = 0
self.call_load_panel.emit(False, "")
return
self.call_load_panel.emit(
True, f"Unloading Filament\n{status['step'].capitalize()}"
)
self.handle_filament_state()

@QtCore.pyqtSlot(int, int, name="load_filament")
def load_filament(self, toolhead: int = 0, temp: int = 220) -> None:
def load_filament(
self, toolhead: int = 0, filament: FilamentTypes = FilamentTypes.UNKNOWN
) -> None:
"""Handle load filament buttons clicked"""
if not self.isVisible:
return
Expand All @@ -194,9 +203,11 @@ def load_filament(self, toolhead: int = 0, temp: int = 220) -> None:
message="Filament is already loaded.",
)
return
self.loadignore = False
self.call_load_panel.emit(True, "Loading Filament")
self.run_gcode.emit(f"LOAD_FILAMENT TOOLHEAD=load_toolhead TEMPERATURE={temp}")
self.run_gcode.emit(
f"""SAVE_VARIABLE VARIABLE=filament_type VALUE='"{filament.value.name}"'"""
)
self.run_gcode.emit(f"LOAD_FILAMENT TEMPERATURE={filament.value.temperature}")

@QtCore.pyqtSlot(str, int, name="unload_filament")
def unload_filament(self, toolhead: int = 0, temp: int = 220) -> None:
Expand All @@ -218,21 +229,23 @@ def unload_filament(self, toolhead: int = 0, temp: int = 220) -> None:
return

self.find_routine_objects()
self.unloadignore = False
self.call_load_panel.emit(True, "Unloading Filament")
self.run_gcode.emit(
f"""SAVE_VARIABLE VARIABLE=filament_type VALUE='"{FilamentTypes.UNKNOWN.value.name}"'"""
)
self.run_gcode.emit(f"UNLOAD_FILAMENT TEMPERATURE={temp}")

def handle_filament_state(self):
"""Handle ui changes on filament states"""
if self._filament_state == self.FilamentStates.LOADED:
self.panel.filament_page_load_btn.setDisabled(True)
self.panel.filament_page_load_btn.setDisabled(False)
self.panel.filament_page_unload_btn.setEnabled(True)
self.panel.filament_page_load_btn.setEnabled(False)
elif self._filament_state == self.FilamentStates.UNLOADED:
self.panel.filament_page_unload_btn.setDisabled(True)
self.panel.filament_page_unload_btn.setDisabled(False)
self.panel.filament_page_unload_btn.setEnabled(False)
self.panel.filament_page_load_btn.setEnabled(True)
else:
self.panel.filament_page_load_btn.setDisabled(False)
self.panel.filament_page_unload_btn.setDisabled(False)
self.panel.filament_page_load_btn.setEnabled(True)
self.panel.filament_page_unload_btn.setEnabled(True)

@property
def filament_state(self):
Expand Down
Loading
Loading