From baea9235c0d46b8cec2d879e8ffc2ed01b78f4ea Mon Sep 17 00:00:00 2001 From: zkk Date: Sat, 10 May 2025 08:08:39 +0000 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6=E6=96=B0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=E5=BC=80=E9=97=A8=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=AD=89...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/model_menu.conf | 19 ++- ks_includes/KlippyFactory.py | 1 + ks_includes/ModelConfig.py | 56 ++++++- ks_includes/locales/KlipperScreen.pot | 43 ++++-- .../zh_CN/LC_MESSAGES/KlipperScreen.mo | Bin 23500 -> 24120 bytes .../zh_CN/LC_MESSAGES/KlipperScreen.po | 55 +++++-- .../zh_TW/LC_MESSAGES/KlipperScreen.mo | Bin 23219 -> 23839 bytes .../zh_TW/LC_MESSAGES/KlipperScreen.po | 55 +++++-- ks_includes/prompts_text.py | 6 + ks_includes/sdbus_reg.py | 26 +++- panels/advanced.py | 60 +++++++- panels/factory_settings.py | 73 +++++---- panels/license.py | 44 ++++-- panels/splash_screen.py | 20 +-- printer_config/D1000/1.1/door_detect.cfg | 1 + printer_config/D1000/base.cfg | 125 +++++++++++----- printer_config/D600Pro2/1.1/door_detect.cfg | 1 + printer_config/D600Pro2/base.cfg | 138 +++++++++++++----- printer_config/F430NX/base.cfg | 58 +++++--- printer_config/module/door_detect.cfg | 32 ++++ screen.py | 2 +- 21 files changed, 612 insertions(+), 203 deletions(-) create mode 120000 printer_config/D1000/1.1/door_detect.cfg create mode 120000 printer_config/D600Pro2/1.1/door_detect.cfg create mode 100644 printer_config/module/door_detect.cfg diff --git a/config/model_menu.conf b/config/model_menu.conf index 3ba83ee6..e8ea8ed0 100644 --- a/config/model_menu.conf +++ b/config/model_menu.conf @@ -1,6 +1,13 @@ -F430NX -D600Pro2 -D600Pro2_V0 -D1000 -D1000_V0 -P800 +[F430NX] +versions = 1.0 + +[D600Pro2HS] +versions = 1.0, 1.1 +#V1.1 Add door detection + +[D1000HS] +versions = 1.0, 1.1 +#V1.1 Add door detection + +[P800] +versions = 1.0 diff --git a/ks_includes/KlippyFactory.py b/ks_includes/KlippyFactory.py index 0995240b..3fe534c0 100644 --- a/ks_includes/KlippyFactory.py +++ b/ks_includes/KlippyFactory.py @@ -49,6 +49,7 @@ class KlippyFactory: "adaptive_meshing": False, "power_loss_recovery": True, "auto_change_nozzle": False, + "door_detect": "Disabled", } for key, val in option_list.items(): script = KlippyGcodes.set_save_variables(key, val) diff --git a/ks_includes/ModelConfig.py b/ks_includes/ModelConfig.py index 819dca4f..2ed83841 100644 --- a/ks_includes/ModelConfig.py +++ b/ks_includes/ModelConfig.py @@ -1,6 +1,6 @@ -import subprocess -import os import logging +import os +import subprocess class ModelConfig: @@ -38,9 +38,37 @@ class ModelConfig: else: return None - def wirte_printer_config(self, device_name): + def write_device_name_config(self, device_name): if device_name: - source_path = f"{os.path.expanduser('~')}/KlipperScreen/printer_config/{device_name}/" + try: + with open(self.klipperscreen_config_path, "r+") as file: + lines = file.readlines() + file.seek(0) + found_printer_section = False + for i, line in enumerate(lines): + if line.strip().startswith("[printer"): + lines[i] = f"[printer {device_name}]\n" + found_printer_section = True + break + if not found_printer_section: + lines.insert(0, f"[printer {device_name}]\n") + file.truncate(0) + file.writelines(lines) + logging.info(f"Setting device name to {device_name}") + except FileNotFoundError: + logging.error( + f"Configuration file {self.klipperscreen_config_path} not found." + ) + + def wirte_printer_config(self, device_name, version): + config_dict = { + "F430NX": "F430NX", + "D600Pro2HS": "D600Pro2", + "D1000HS": "D1000", + "P800": "P800", + } + if device_name: + source_path = f"{os.path.expanduser('~')}/KlipperScreen/printer_config/{config_dict.get(device_name)}/" target_path = f"{os.path.expanduser('~')}/printer_data/config/" if not os.path.exists(target_path): os.makedirs(target_path) @@ -58,6 +86,21 @@ class ModelConfig: except Exception as e: logging.error(f"Error creating symlink for{device_name}:{e}") + source_module_path = os.path.join(source_path, os.path.basename(version)) + target_module_path = os.path.join(target_path, os.path.basename("module")) + try: + if os.path.islink(target_module_path) or os.path.exists(target_module_path): + os.remove(target_module_path) + if version != "1.0": + os.symlink(source_module_path, target_module_path) + logging.info(f"Created config version for {device_name}-{version}.") + except FileExistsError: + logging.error(f"Failed to create version symlink for {device_name}.") + except PermissionError: + logging.error(f"No permission to create version symlink for {device_name}.") + except Exception as e: + logging.error(f"Error creating version symlink for{device_name}:{e}") + source_printer_path = os.path.join(source_path, os.path.basename("printer.cfg")) target_printer_path = os.path.join(target_path, os.path.basename("printer.cfg")) command = ['cp','-f', source_printer_path, target_printer_path] @@ -81,10 +124,11 @@ class ModelConfig: except Exception as e: logging.error(f"An unexpected error occurred: {e}") - def generate_config(self, model): + def generate_config(self, model, version): model_name = model device_name = self.generate_machine_name(model_name) - self.wirte_printer_config(model) + self.write_device_name_config(device_name) + self.wirte_printer_config(model, version) self.wirte_hostname(device_name) os.system("systemctl restart klipper.service") os.system("systemctl restart moonraker.service") diff --git a/ks_includes/locales/KlipperScreen.pot b/ks_includes/locales/KlipperScreen.pot index 4a1a2111..90649464 100644 --- a/ks_includes/locales/KlipperScreen.pot +++ b/ks_includes/locales/KlipperScreen.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-26 11:12+0800\n" +"POT-Creation-Date: 2025-03-29 17:34+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -76,6 +76,9 @@ msgstr "" msgid "Adaptive Bed Leveling" msgstr "" +msgid "Add" +msgstr "" + msgid "Add profile" msgstr "" @@ -292,6 +295,9 @@ msgstr "" msgid "Disable for 12hs with am / pm" msgstr "" +msgid "Disabled" +msgstr "" + msgid "Disconnect" msgstr "" @@ -306,6 +312,9 @@ msgstr "" msgid "Do you want to recover %s?" msgstr "" +msgid "Door Open Protection Mode" +msgstr "" + msgid "Elapsed trial time:" msgstr "" @@ -321,9 +330,6 @@ msgstr "" msgid "Enable screen power management" msgstr "" -msgid "Enabled successfully" -msgstr "" - msgid "Error" msgstr "" @@ -643,6 +649,9 @@ msgstr "" msgid "Minimum:" msgstr "" +msgid "Minus" +msgstr "" + msgid "Modified" msgstr "" @@ -763,6 +772,9 @@ msgstr "" msgid "Pause" msgstr "" +msgid "Pause Print" +msgstr "" + msgid "Paused" msgstr "" @@ -775,6 +787,9 @@ msgstr "" msgid "Pins" msgstr "" +msgid "Please close the door and click Resume to proceed." +msgstr "" + msgid "Please ensure that the Probe Calibrate has been performed" msgstr "" @@ -823,6 +838,12 @@ msgstr "" msgid "Printer Select" msgstr "" +msgid "Printer door is opened. Please close the door and then start printing." +msgstr "" + +msgid "Printer door is opening!" +msgstr "" + msgid "Printing" msgstr "" @@ -877,12 +898,6 @@ msgstr "" msgid "Reprint" msgstr "" -msgid "Reset" -msgstr "" - -msgid "Reset successfully" -msgstr "" - msgid "Restart" msgstr "" @@ -1052,6 +1067,9 @@ msgstr "" msgid "Temperature" msgstr "" +msgid "Test Mode" +msgstr "" + msgid "The last print job was not completed continue printing?" msgstr "" @@ -1067,6 +1085,11 @@ msgstr "" msgid "This device is not activated and is available for trial use only" msgstr "" +msgid "" +"This feature allows you to customize the printer's response when door " +"opening is detected" +msgstr "" + msgid "This operation is about to print the model" msgstr "" diff --git a/ks_includes/locales/zh_CN/LC_MESSAGES/KlipperScreen.mo b/ks_includes/locales/zh_CN/LC_MESSAGES/KlipperScreen.mo index b36aa86b3a48bc2e2839f6483c51f12e9372b957..6cc1981fdba6382731e67d0de9aa0d88d7b7a9af 100644 GIT binary patch delta 9304 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\n" "Language-Team: Chinese (Simplified) J)d5D@9VzrbFXtw0=3}7fX#;k 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 LJOz_Rj|ln~DA%wh delta 8689 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\n" "Language-Team: Chinese (Traditional) bool: + async def test_registration(self, val: str) -> bool: + raise NotImplementedError + + @dbus_method_async(result_signature="b") + async def add_registration_time(self) -> bool: + raise NotImplementedError + + @dbus_method_async(result_signature="b") + async def minus_registration_time(self) -> bool: raise NotImplementedError @dbus_property_async(property_signature="b") @@ -146,12 +154,24 @@ class LicenseManager: return self._async_call(_verify, default=False) - def reset_registration(self, code: str) -> bool: + def test_registration(self, code: str) -> bool: async def _reset(): - return await self.registration_interface.proxy.reset_registration(code) + return await self.registration_interface.proxy.test_registration(code) return self._async_call(_reset, default=False) + def add_registration_time(self) -> bool: + async def _add(): + return await self.registration_interface.proxy.add_registration_time() + + return self._async_call(_add, default=False) + + def minus_registration_time(self) -> bool: + async def _minus(): + return await self.registration_interface.proxy.minus_registration_time() + + return self._async_call(_minus, default=False) + def enabled_registration(self) -> bool: async def _get(): return await self.registration_interface.proxy.enabled_registration diff --git a/panels/advanced.py b/panels/advanced.py index 974fbc37..50ae4579 100644 --- a/panels/advanced.py +++ b/panels/advanced.py @@ -3,17 +3,19 @@ import logging import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk +from gi.repository import GLib, Gtk from ks_includes.KlippyFactory import KlippyFactory from ks_includes.KlippyGcodes import KlippyGcodes from ks_includes.screen_panel import ScreenPanel +from datetime import datetime class Panel(ScreenPanel): def __init__(self, screen, title): title = title or _("Advanced") super().__init__(screen, title) + self.last_drop_time = datetime.now() self.advanced = {} self.menu_list = {} self.advanced_options = [ @@ -59,6 +61,27 @@ class Panel(ScreenPanel): } }, ] + if self._printer.get_macro("_door_detection"): + self.advanced_options.append( + { + "door_open_detection": { + "section": "main", + "name": _("Door Open Protection Mode"), + "type": "dropdown", + "tooltip": _( + "This feature allows you to customize the printer's response when door opening is detected" + ), + "value": "Disabled", + "callback": self.door_open_detection, + "options": [ + {"name": _("Disabled") + " " + _("(default)"), "value": "Disabled"}, + {"name": _("Pause Print"), "value": "Pause Print"}, + {"name": _("Emergency Stop"), "value": "Emergency Stop"}, + ], + } + } + ) + options = self.advanced_options self.labels["advanced_menu"] = self._gtk.ScrolledWindow() self.labels["advanced"] = Gtk.Grid() @@ -69,6 +92,9 @@ class Panel(ScreenPanel): self.menu_list.update(res) self.content.add(self.labels["advanced_menu"]) + if "door_open_detection" in self.menu_list: + self.menu_list["door_open_detection"].connect("notify::popup-shown", self.on_popup_shown) + def reset_factory_settings(self, *args): text = _("Confirm factory reset?\n") + "\n\n" + _("The system will reboot!") label = Gtk.Label(wrap=True, vexpand=True) @@ -111,6 +137,26 @@ class Panel(ScreenPanel): if response_id == Gtk.ResponseType.OK: KlippyFactory.user_factory_reset(self._screen._ws.klippy, self._config, clear_files_checkbox.get_active()) + def on_popup_shown(self, combo_box, param): + if combo_box.get_property("popup-shown"): + logging.debug("Dropdown popup show") + self.last_drop_time = datetime.now() + else: + elapsed = (datetime.now() - self.last_drop_time).total_seconds() + if elapsed < 0.1: + logging.debug(f"Dropdown closed too fast ({elapsed}s)") + GLib.timeout_add(50, lambda: self.dropdown_keep_open(combo_box)) + return + logging.debug("Dropdown popup close") + + def dropdown_keep_open(self, combo_box): + if isinstance(combo_box, Gtk.ComboBox): + combo_box.popup() + return False + + def door_open_detection(self, str): + self.set_configuration_string("door_detect", str) + def set_adaptive_leveling(self, *args): self.set_configuration_feature("adaptive_meshing", *args) @@ -120,6 +166,11 @@ class Panel(ScreenPanel): def set_auto_change_nozzle(self, *args): self.set_configuration_feature("auto_change_nozzle", *args) + def set_configuration_string(self, feature_name, str): + script = KlippyGcodes.set_save_variables(feature_name, str) + self._screen._send_action(None, "printer.gcode.script", {"script": script}) + logging.info(f"Set {feature_name}: {str}") + def set_configuration_feature(self, feature_name, *args): enable_feature = any(args) script_value = True if enable_feature else False @@ -143,3 +194,10 @@ class Panel(ScreenPanel): self.menu_list["auto_change_nozzle"].set_active(variables["auto_change_nozzle"]) else: self.menu_list["auto_change_nozzle"].set_active(False) + + if self._printer.get_macro("_door_detection"): + if "door_detect" in variables: + model = self.menu_list["door_open_detection"].get_model() + for i, row in enumerate(model): + if row[0] == _(variables["door_detect"]): + self.menu_list["door_open_detection"].set_active(i) diff --git a/panels/factory_settings.py b/panels/factory_settings.py index 786ef4ef..55f1a89a 100644 --- a/panels/factory_settings.py +++ b/panels/factory_settings.py @@ -19,6 +19,10 @@ class Panel(ScreenPanel): def __init__(self, screen, title): title = title or "factory settings" super().__init__(screen, title) + klipperscreendir = pathlib.Path(__file__).parent.resolve().parent + self.model_list_path = os.path.join(klipperscreendir, "config", "model_menu.conf") + self.model_list_config = configparser.ConfigParser() + self.model_list_config.read(self.model_list_path, encoding="utf-8") self.last_drop_time = datetime.now() self.factory_settings_list = [ { @@ -62,6 +66,7 @@ class Panel(ScreenPanel): ] self.settings = {} self.select_model = False + self.select_model_version = False self.labels["setting_menu"] = self._gtk.ScrolledWindow() self.labels["settings"] = Gtk.Grid() self.labels["setting_menu"].add(self.labels["settings"]) @@ -77,6 +82,9 @@ class Panel(ScreenPanel): self.content.show_all() def back(self): + if self.select_model_version: + self.hide_select_model_version() + return True if self.select_model: self.hide_select_model() return True @@ -99,38 +107,53 @@ class Panel(ScreenPanel): combo_box.popup() return False - def show_select_model(self, widget, option): - self.create_select_model() + def create_list_menu(self, menu_list, callback=None): + if "model_menu" in self.labels: + del self.labels["model_menu"] + self.labels["model_menu"] = self._gtk.ScrolledWindow() + self.labels["model"] = Gtk.Grid() + self.labels["model_menu"].add(self.labels["model"]) + self.models = {} + for value in menu_list: + self.models[value] = { + "name": value, + "type": "button", + "callback": callback, + } + self.add_option("model", self.models, value, self.models[value]) + + def show_select_model(self, widget=None, option=None): + self.create_list_menu(self.model_list_config.sections(), self._on_model_selected) for child in self.content.get_children(): self.content.remove(child) self.content.add(self.labels["model_menu"]) self.content.show_all() self.select_model = True - def create_select_model(self): - if "model_menu" in self.labels: - return + def show_select_model_version(self, model): + versions_str = self.model_list_config[model].get("versions", "") + versions = [v.strip() for v in versions_str.split(",") if v.strip()] + self.create_list_menu(versions, self._on_version_selected) + self.select_model_version = True + self.model = model + + def _on_model_selected(self, widget, event): + for child in self.content.get_children(): + self.content.remove(child) + self.show_select_model_version(event) + self.content.add(self.labels["model_menu"]) + self.content.show_all() + + def _on_version_selected(self, widget, version): if not hasattr(self, "model_config") or self.model_config is None: self.model_config = ModelConfig() - self.labels["model_menu"] = self._gtk.ScrolledWindow() - self.labels["model"] = Gtk.Grid() - self.labels["model_menu"].add(self.labels["model"]) - klipperscreendir = pathlib.Path(__file__).parent.resolve().parent - self.model_list_path = os.path.join(klipperscreendir, "config", "model_menu.conf") - self.model_list = pathlib.Path(self.model_list_path).read_text() - with open(self.model_list_path) as file: - self.models = {} - for line in file: - model_name = line.strip() - self.models[model_name] = { - "name": model_name, - "type": "button", - "callback": self.change_model, - } - self.add_option("model", self.models, model_name, self.models[model_name]) + self.model_config.generate_config(self.model, version) - def change_model(self, widget, event): - self.model_config.generate_config(event) + def hide_select_model_version(self): + for child in self.content.get_children(): + self.content.remove(child) + self.show_select_model() + self.select_model_version = False def hide_select_model(self): for child in self.content.get_children(): @@ -148,7 +171,7 @@ class Panel(ScreenPanel): {"name": _("Accept"), "response": Gtk.ResponseType.OK, "style": "dialog-error"}, {"name": _("Cancel"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-info"}, ] - + text = _("Are you sure?\n") + "\n\n" + _("The system will reboot!") label = Gtk.Label(wrap=True, vexpand=True) label.set_markup(text) @@ -158,7 +181,6 @@ class Panel(ScreenPanel): checkbox.set_halign(Gtk.Align.CENTER) checkbox.set_valign(Gtk.Align.CENTER) - grid = Gtk.Grid(row_homogeneous=True, column_homogeneous=True) grid.set_row_spacing(20) grid.set_column_spacing(0) @@ -173,7 +195,6 @@ class Panel(ScreenPanel): self.confirm_factory_reset_production, checkbox, ) - def confirm_factory_reset_production(self, dialog, response_id, checkbox): self._gtk.remove_dialog(dialog) diff --git a/panels/license.py b/panels/license.py index e83b818b..04a313f7 100644 --- a/panels/license.py +++ b/panels/license.py @@ -17,6 +17,9 @@ class Panel(ScreenPanel): + _("Please enter a key to activate") ) self.key_len = 15 + self.key_val_test = 1 + self.key_val_add = 2 + self.key_val_minus = 3 self.full = False self.interface = screen.license self.serial_num = self.interface.get_unique_id() or _("Unknown") @@ -71,6 +74,13 @@ class Panel(ScreenPanel): for child in self.content.get_children(): self.content.remove(child) + def display_test_dialog(self, key_text=""): + buttons = [ + {"name": _("Add"), "response": self.key_val_add, "style": "dialog-secondary"}, + {"name": _("Minus"), "response": self.key_val_minus, "style": "dialog-info"}, + {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, + ] + self.create_license_key_dialog(buttons=buttons, key=key_text) def display_dialog(self, full=False, key=""): BUTTON_CONFIGS = { "trial_with_callback": [ @@ -78,12 +88,12 @@ class Panel(ScreenPanel): {"name": _("Skip"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-error"}, ], "full_features": [ - {"name": _("Reset"), "response": Gtk.ResponseType.APPLY, "style": "dialog-secondary"}, + {"name": _("Test Mode"), "response": self.key_val_test, "style": "dialog-secondary"}, {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ], "Trial": [ - {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, + {"name": _("Activate"), "response": Gtk.ResponseType.YES, "style": "dialog-info"}, {"name": _("Trial"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ], "default": [ @@ -133,6 +143,7 @@ class Panel(ScreenPanel): status_text = _("Unknown") elif self.is_active: status_text = _("Permanent Activation") + self.title_label.set_markup(f"{status_text}\n") self.license_box["state_text"], self.license_box["state_text_value"] = add_labeled_value( 0, _("State:"), status_text ) @@ -178,18 +189,14 @@ class Panel(ScreenPanel): def confirm_license_response(self, dialog, response_id): if response_id == Gtk.ResponseType.YES: - if self.interface.enabled_registration(): - self.state_update(_("Enabled successfully")) - elif response_id == Gtk.ResponseType.APPLY: if len(self.license_box["key_input"].get_text()) == 0: self.state_update(_("Key is empty")) return - else: - if self.interface.reset_registration(self.license_box["key_input"].get_text()): - self.update_time() - self.state_update(_("Reset successfully")) - else: - self.state_update(_("Key is invalid")) + self.verify_key(self.license_box["key_input"].get_text()) + self.update_time() + if self.interface.is_active(): + self._gtk.remove_dialog(dialog) + self._screen._menu_go_back() elif response_id == Gtk.ResponseType.CLOSE: self._gtk.remove_dialog(dialog) self._screen._menu_go_back() @@ -205,6 +212,21 @@ class Panel(ScreenPanel): return self.verify_key(self.license_box["key_input"].get_text()) self.update_time() + elif response_id == self.key_val_test: + if len(self.license_box["key_input"].get_text()) == 0: + self.state_update(_("Key is empty")) + return + if self.interface.test_registration(self.license_box["key_input"].get_text()): + self._gtk.remove_dialog(dialog) + self.display_test_dialog() + else: + self.state_update(_("Key is invalid")) + elif response_id == self.key_val_add: + self.interface.add_registration_time() + self.update_time() + elif response_id == self.key_val_minus: + self.interface.minus_registration_time() + self.update_time() def on_show_keyboard(self, entry=None, event=None): self._gtk.remove_dialog(self.dialog) diff --git a/panels/splash_screen.py b/panels/splash_screen.py index 4c8f4a36..3371b2f4 100644 --- a/panels/splash_screen.py +++ b/panels/splash_screen.py @@ -24,22 +24,10 @@ class Panel(ScreenPanel): self.labels["menu"] = self._gtk.Button("more-settings", _("Menu"), "color4") self.labels["menu"].connect("clicked", self._screen._go_to_submenu, "") - self.labels["restart"] = self._gtk.Button( - "refresh", _("Klipper Restart"), "color1" - ) - self.labels["restart"].connect("clicked", self.restart_klipper) self.labels["firmware_restart"] = self._gtk.Button( "refresh", _("Firmware Restart"), "color2" ) self.labels["firmware_restart"].connect("clicked", self.firmware_restart) - self.labels["restart_system"] = self._gtk.Button( - "refresh", _("System Restart"), "color1" - ) - self.labels["restart_system"].connect("clicked", self.reboot_poweroff, "reboot") - self.labels["shutdown"] = self._gtk.Button( - "shutdown", _("System Shutdown"), "color2" - ) - self.labels["shutdown"].connect("clicked", self.reboot_poweroff, "shutdown") self.labels["retry"] = self._gtk.Button("load", _("Retry"), "color3") self.labels["retry"].connect("clicked", self.retry) @@ -79,16 +67,12 @@ class Panel(ScreenPanel): self.add_power_button(power_devices) if self._screen.initialized: - self.labels["actions"].add(self.labels["restart"]) self.labels["actions"].add(self.labels["firmware_restart"]) - else: - self.labels["actions"].add(self.labels["restart_system"]) - self.labels["actions"].add(self.labels["shutdown"]) self.labels["actions"].add(self.labels["menu"]) if ( self._screen._ws - and not self._screen._ws.connecting - or self._screen.reinit_count > self._screen.max_retries + and self._screen._ws.connecting + or self._screen.reinit_count > self._screen.max_retries or not self._screen.initialized ): self.labels["actions"].add(self.labels["retry"]) self.labels["actions"].show_all() diff --git a/printer_config/D1000/1.1/door_detect.cfg b/printer_config/D1000/1.1/door_detect.cfg new file mode 120000 index 00000000..7f384b92 --- /dev/null +++ b/printer_config/D1000/1.1/door_detect.cfg @@ -0,0 +1 @@ +../../module/door_detect.cfg \ No newline at end of file diff --git a/printer_config/D1000/base.cfg b/printer_config/D1000/base.cfg index ee778b15..4276e197 100644 --- a/printer_config/D1000/base.cfg +++ b/printer_config/D1000/base.cfg @@ -9,6 +9,10 @@ filename: ~/printer_data/config/config_variables.cfg [exclude_object] +[board_pins] +aliases: + DOOR_PIN=PC5 + [gcode_arcs] resolution: 1.0 @@ -103,14 +107,16 @@ position_min: -4 homing_speed: 10 second_homing_speed: 1 homing_retract_dist: 2.0 +step_pulse_duration: 0.000005 [heater_bed] heater_pin: PD12 sensor_type: Generic 3950 sensor_pin: PC0 max_power: 1.0 -min_temp: 0 -max_temp: 130 +min_temp: -20 +max_temp: 100 +overshoot: 10 # control: pid # pid_kp: 17.22 # pid_ki: 0.9 @@ -127,8 +133,9 @@ heater_pin:PD15 max_power:1.0 sensor_type: Generic 3950 sensor_pin:PC3 -min_temp: 0 -max_temp: 70 +min_temp: -20 +max_temp: 60 +overshoot: 10 pwm_cycle_time: 0.3 # control: pid # pid_kp: 30.68 @@ -246,8 +253,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: tool:PC6 max_power: 1.0 -min_temp: 0 -max_temp: 435 +min_temp: -20 +max_temp: 420 +overshoot: 20 min_extrude_temp: 180 pressure_advance: 0.03 pressure_advance_smooth_time:0.040 @@ -295,8 +303,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: tool:PC7 max_power: 1.0 -min_temp: 0 -max_temp: 435 +min_temp: -20 +max_temp: 420 +overshoot: 20 min_extrude_temp: 180 pressure_advance: 0.032 pressure_advance_smooth_time:0.040 @@ -363,7 +372,10 @@ gcode: [gcode_macro T0] gcode: - {% set filament_insert = printer["filament_switch_sensor extruder"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor|default("") == "" + else True if not printer[client.filament_sensor].enabled + else printer[client.filament_sensor].filament_detected|default(False) %} {% set printing = printer.print_stats.state == "printing" %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -390,7 +402,10 @@ gcode: {% set y_offset = sv.nozzle_y_offset_val|default(0)|float %} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set x_offset = x_offset - 59 %} - {% set filament_insert = printer["filament_switch_sensor extruder1"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor1|default("") == "" + else True if not printer[client.filament_sensor1].enabled + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -654,13 +669,14 @@ gcode: [gcode_macro _USER_PAUSE] gcode: - {% set extruderTools = [('extruder', 'last_extruder_temp'), - ('extruder1', 'last_extruder1_temp')] %} + {% set heaters = [('extruder', 'last_extruder_temp'), + ('extruder1', 'last_extruder1_temp'), + ('heater_bed', 'last_bed_temp')] %} {% set act = printer.gcode_move.gcode_position %} SAVE_VARIABLE VARIABLE=power_resume_z VALUE={act.z} - {% for extruder_name, name in extruderTools %} - {% set temp = printer[extruder_name].target if extruder_name in printer else 0 %} - {% set restore = False if printer[extruder_name] == '' + {% for heater, name in heaters %} + {% set temp = printer[heater].target if heater in printer else 0 %} + {% set restore = False if printer[heater] == '' else True if params.RESTORE|default(1)|int == 1 else False %} SET_GCODE_VARIABLE MACRO=RESUME VARIABLE={name} VALUE="{{'restore': restore, 'temp': temp}}" {% endfor %} @@ -711,6 +727,10 @@ gcode: {% set extruder_info = [ {'index': 0, 'name': 'last_extruder_temp'}, {'index': 1, 'name': 'last_extruder1_temp'}] %} + {% set value = printer["gcode_macro RESUME"]["last_bed_temp"].temp %} + {% if value != 0 %} + M190 S{value} + {% endif %} {% set temperature = "last_extruder_temp" if printer.toolhead.extruder == "extruder" else "last_extruder1_temp" %} {% set value = printer["gcode_macro RESUME"][temperature].temp %} {% if printer[printer.toolhead.extruder].temperature < value-3 %} @@ -770,11 +790,28 @@ gcode: {% endif %} {% endif %} +[gcode_macro _REAPPLY_OFFSET] +gcode: + {% set re_extruder = printer['gcode_macro RESUME'].resume_extruder|default("extruder") %} + {% set svv = printer.save_variables.variables %} + {% set x_offset = svv.nozzle_x_offset_val|default(0)|float %} + {% set y_offset = svv.nozzle_y_offset_val|default(0)|float %} + {% set z_offset = svv.nozzle_z_offset_val|default(0)|float %} + {% set x_offset = x_offset - 59 %} + {% set is_extruder = printer.toolhead.extruder == "extruder" %} + + {% if printer.toolhead.extruder!= re_extruder %} + SET_GCODE_OFFSET Z={0 if is_extruder else z_offset} MOVE=1 + SET_GCODE_OFFSET Y={0 if is_extruder else y_offset} + SET_GCODE_OFFSET X={0 if is_extruder else x_offset} + {% endif %} + [gcode_macro RESUME] description: Resume the actual running print rename_existing: RESUME_BASE variable_last_extruder_temp: {'restore': False, 'temp': 0} variable_last_extruder1_temp: {'restore': False, 'temp': 0} +variable_last_bed_temp: {'restore': False, 'temp': 0} variable_restore_idle_timeout: 0 variable_idle_state: False variable_filament_state: "" @@ -786,28 +823,41 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set do_resume = False %} {% set runout = True %} - ##### end of definitions ##### - _FILAMENT_UPDATE - _RESUME_EXTRUDER AUTOSHIFT={autoshift} - _EXTRUDER_TEMPERATURE_HANDLE + {% macro resume_action() %} + _FILAMENT_UPDATE + _RESUME_EXTRUDER AUTOSHIFT={autoshift} + _EXTRUDER_TEMPERATURE_HANDLE - {% set can_extrude = True if printer.toolhead.extruder == '' # no extruder defined in config - else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder - #### Printer comming from timeout idle state #### - {% if printer.idle_timeout.state|upper == "IDLE" or idle_state or autoshift %} - SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False + {% set can_extrude = True if printer.toolhead.extruder == '' # no extruder defined in config + else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder + #### Printer comming from timeout idle state #### + {% if printer.idle_timeout.state|upper == "IDLE" or idle_state or autoshift %} + SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False + {% endif %} {% if last_extruder_temp.restore or last_extruder1_temp.restore %} - # we need to use the unicode (\u00B0) for the ° as py2 env's would throw an error otherwise - {client.user_temp_macro|default("")} + { client.user_temp_macro|default("") } {% set do_resume = True %} {% elif can_extrude %} {% set do_resume = True %} {% endif %} - #### Printer comming out of regular PAUSE state #### - {% elif can_extrude %} - {% set do_resume = True %} + _ACT_RESUME DO_RESUME={ do_resume } + {% endmacro %} + {% if printer['gcode_button _door_detection'] %} + {% set sv = printer.save_variables.variables %} + {% set door_function = sv.door_detect|default("Disabled") %} + {% set door_state = printer['gcode_button _door_detection'].state|default('released')|lower %} + + {% if door_function == 'Pause Print' and door_state == 'released' %} + RESPOND TYPE=command MSG="action:prompt_begin" + RESPOND TYPE=command MSG="action:prompt_text Please close the door and click Resume to proceed." + RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end" + RESPOND TYPE=command MSG="action:prompt_show" + {% else %} + { resume_action() } + {% endif %} + {% else %} + { resume_action() } {% endif %} - _ACT_RESUME DO_RESUME={do_resume} [gcode_macro _ACT_RESUME] gcode: @@ -826,6 +876,7 @@ gcode: {client.user_resume_macro|default("")} _CLIENT_EXTRUDE RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)} + _REAPPLY_OFFSET SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=change_runout VALUE="None" {% else %} {% set msg = "Left" if printer.toolhead.extruder == "extruder" else "Right" %} @@ -928,9 +979,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -946,9 +997,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -958,7 +1009,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -1140,4 +1191,6 @@ gcode: [gcode_macro _NOZZLE_XY_OFFSET_CALIBRATE] gcode: RUN_SHELL_COMMAND CMD=fetch_assets PARAMS="\"Gcode\" \"D1000HS\" \"NozzleAglin.zip\"" - SDCARD_PRINT_FILE FILENAME=".PresetModel/NozzleAglin.gcode" \ No newline at end of file + SDCARD_PRINT_FILE FILENAME=".PresetModel/NozzleAglin.gcode" + +[include module/*.cfg] diff --git a/printer_config/D600Pro2/1.1/door_detect.cfg b/printer_config/D600Pro2/1.1/door_detect.cfg new file mode 120000 index 00000000..7f384b92 --- /dev/null +++ b/printer_config/D600Pro2/1.1/door_detect.cfg @@ -0,0 +1 @@ +../../module/door_detect.cfg \ No newline at end of file diff --git a/printer_config/D600Pro2/base.cfg b/printer_config/D600Pro2/base.cfg index b28c7c23..1c7fa12b 100644 --- a/printer_config/D600Pro2/base.cfg +++ b/printer_config/D600Pro2/base.cfg @@ -9,6 +9,10 @@ filename: ~/printer_data/config/config_variables.cfg [exclude_object] +[board_pins] +aliases: + DOOR_PIN=PC5 + [gcode_arcs] resolution: 1.0 @@ -103,14 +107,16 @@ position_min: -4 homing_speed: 10 second_homing_speed: 1 homing_retract_dist: 2.0 +step_pulse_duration: 0.000005 [heater_bed] heater_pin: PD12 sensor_type: Generic 3950 sensor_pin: PC0 max_power: 1.0 -min_temp: 0 -max_temp: 130 +min_temp: -20 +max_temp: 100 +overshoot: 10 # control: pid # pid_kp: 59.368 # pid_ki: 1.656 @@ -127,8 +133,9 @@ heater_pin:PD15 max_power:1.0 sensor_type: Generic 3950 sensor_pin:PC3 -min_temp: 0 -max_temp: 80 +min_temp: -20 +max_temp: 70 +overshoot: 10 pwm_cycle_time: 0.3 # control: pid # pid_kp: 30.68 @@ -246,8 +253,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: tool:PC6 max_power: 1.0 -min_temp: 0 -max_temp: 435 +min_temp: -20 +max_temp: 420 +overshoot: 20 min_extrude_temp: 180 pressure_advance: 0.03 pressure_advance_smooth_time:0.040 @@ -295,8 +303,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: tool:PC7 max_power: 1.0 -min_temp: 0 -max_temp: 435 +min_temp: -20 +max_temp: 420 +overshoot: 20 min_extrude_temp: 180 pressure_advance: 0.032 pressure_advance_smooth_time:0.040 @@ -363,7 +372,10 @@ gcode: [gcode_macro T0] gcode: - {% set filament_insert = printer["filament_switch_sensor extruder"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor|default("") == "" + else True if not printer[client.filament_sensor].enabled + else printer[client.filament_sensor].filament_detected|default(False) %} {% set printing = printer.print_stats.state == "printing" %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -390,7 +402,10 @@ gcode: {% set y_offset = sv.nozzle_y_offset_val|default(0)|float %} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set x_offset = x_offset - 59 %} - {% set filament_insert = printer["filament_switch_sensor extruder1"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor1|default("") == "" + else True if not printer[client.filament_sensor1].enabled + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -417,7 +432,7 @@ gcode: [gcode_macro PROBE_SERVO_CLOSE] gcode: - SET_SERVO SERVO=probe_servo angle=130 + SET_SERVO SERVO=probe_servo angle=170 G4 P2000 [gcode_macro _START_PRINT_BASE] @@ -538,12 +553,18 @@ gcode: {% set do_z = 'Z' in params|string %} {% if do_x %} + SET_STEPPER_ENABLE STEPPER=stepper_x ENABLE=1 + G4 P300 {% set homing_cmd = 'X ' %} {% endif %} {% if do_y %} + SET_STEPPER_ENABLE STEPPER=stepper_y ENABLE=1 + G4 P300 {% set homing_cmd = homing_cmd + 'Y ' %} {% endif %} {% if do_z %} + SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 + G4 P300 {% if 'x' not in printer.toolhead.homed_axes|lower or 'y' not in printer.toolhead.homed_axes|lower %} {% set homing_cmd = 'X Y Z' %} {% else %} @@ -551,6 +572,10 @@ gcode: {% endif %} {% endif %} {% if not homing_cmd %} + SET_STEPPER_ENABLE STEPPER=stepper_x ENABLE=1 + SET_STEPPER_ENABLE STEPPER=stepper_y ENABLE=1 + SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 + G4 P300 C28 _ACTIVATE_DEFAULT_EXTRUDER {% else %} @@ -645,13 +670,14 @@ gcode: [gcode_macro _USER_PAUSE] gcode: - {% set extruderTools = [('extruder', 'last_extruder_temp'), - ('extruder1', 'last_extruder1_temp')] %} + {% set heaters = [('extruder', 'last_extruder_temp'), + ('extruder1', 'last_extruder1_temp'), + ('heater_bed', 'last_bed_temp')] %} {% set act = printer.gcode_move.gcode_position %} SAVE_VARIABLE VARIABLE=power_resume_z VALUE={act.z} - {% for extruder_name, name in extruderTools %} - {% set temp = printer[extruder_name].target if extruder_name in printer else 0 %} - {% set restore = False if printer[extruder_name] == '' + {% for heater, name in heaters %} + {% set temp = printer[heater].target if heater in printer else 0 %} + {% set restore = False if printer[heater] == '' else True if params.RESTORE|default(1)|int == 1 else False %} SET_GCODE_VARIABLE MACRO=RESUME VARIABLE={name} VALUE="{{'restore': restore, 'temp': temp}}" {% endfor %} @@ -702,6 +728,10 @@ gcode: {% set extruder_info = [ {'index': 0, 'name': 'last_extruder_temp'}, {'index': 1, 'name': 'last_extruder1_temp'}] %} + {% set value = printer["gcode_macro RESUME"]["last_bed_temp"].temp %} + {% if value != 0 %} + M190 S{value} + {% endif %} {% set temperature = "last_extruder_temp" if printer.toolhead.extruder == "extruder" else "last_extruder1_temp" %} {% set value = printer["gcode_macro RESUME"][temperature].temp %} {% if printer[printer.toolhead.extruder].temperature < value-3 %} @@ -761,11 +791,28 @@ gcode: {% endif %} {% endif %} +[gcode_macro _REAPPLY_OFFSET] +gcode: + {% set re_extruder = printer['gcode_macro RESUME'].resume_extruder|default("extruder") %} + {% set svv = printer.save_variables.variables %} + {% set x_offset = svv.nozzle_x_offset_val|default(0)|float %} + {% set y_offset = svv.nozzle_y_offset_val|default(0)|float %} + {% set z_offset = svv.nozzle_z_offset_val|default(0)|float %} + {% set x_offset = x_offset - 59 %} + {% set is_extruder = printer.toolhead.extruder == "extruder" %} + + {% if printer.toolhead.extruder!= re_extruder %} + SET_GCODE_OFFSET Z={0 if is_extruder else z_offset} MOVE=1 + SET_GCODE_OFFSET Y={0 if is_extruder else y_offset} + SET_GCODE_OFFSET X={0 if is_extruder else x_offset} + {% endif %} + [gcode_macro RESUME] description: Resume the actual running print rename_existing: RESUME_BASE variable_last_extruder_temp: {'restore': False, 'temp': 0} variable_last_extruder1_temp: {'restore': False, 'temp': 0} +variable_last_bed_temp: {'restore': False, 'temp': 0} variable_restore_idle_timeout: 0 variable_idle_state: False variable_filament_state: "" @@ -777,29 +824,41 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set do_resume = False %} {% set runout = True %} - ##### end of definitions ##### - _FILAMENT_UPDATE - _RESUME_EXTRUDER AUTOSHIFT={autoshift} - _EXTRUDER_TEMPERATURE_HANDLE + {% macro resume_action() %} + _FILAMENT_UPDATE + _RESUME_EXTRUDER AUTOSHIFT={autoshift} + _EXTRUDER_TEMPERATURE_HANDLE - {% set can_extrude = True if printer.toolhead.extruder == '' # no extruder defined in config - else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder - - #### Printer comming from timeout idle state #### - {% if printer.idle_timeout.state|upper == "IDLE" or idle_state or autoshift %} - SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False + {% set can_extrude = True if printer.toolhead.extruder == '' # no extruder defined in config + else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder + #### Printer comming from timeout idle state #### + {% if printer.idle_timeout.state|upper == "IDLE" or idle_state or autoshift %} + SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False + {% endif %} {% if last_extruder_temp.restore or last_extruder1_temp.restore %} - # we need to use the unicode (\u00B0) for the ° as py2 env's would throw an error otherwise - {client.user_temp_macro|default("")} + { client.user_temp_macro|default("") } {% set do_resume = True %} {% elif can_extrude %} {% set do_resume = True %} {% endif %} - #### Printer comming out of regular PAUSE state #### - {% elif can_extrude %} - {% set do_resume = True %} + _ACT_RESUME DO_RESUME={ do_resume } + {% endmacro %} + {% if printer['gcode_button _door_detection'] %} + {% set sv = printer.save_variables.variables %} + {% set door_function = sv.door_detect|default("Disabled") %} + {% set door_state = printer['gcode_button _door_detection'].state|default('released')|lower %} + + {% if door_function == 'Pause Print' and door_state == 'released' %} + RESPOND TYPE=command MSG="action:prompt_begin" + RESPOND TYPE=command MSG="action:prompt_text Please close the door and click Resume to proceed." + RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end" + RESPOND TYPE=command MSG="action:prompt_show" + {% else %} + { resume_action() } + {% endif %} + {% else %} + { resume_action() } {% endif %} - _ACT_RESUME DO_RESUME={do_resume} [gcode_macro _ACT_RESUME] gcode: @@ -818,6 +877,7 @@ gcode: {client.user_resume_macro|default("")} _CLIENT_EXTRUDE RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)} + _REAPPLY_OFFSET SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=change_runout VALUE="None" {% else %} {% set msg = "Left" if printer.toolhead.extruder == "extruder" else "Right" %} @@ -920,9 +980,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -938,9 +998,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -950,7 +1010,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -1132,4 +1192,6 @@ gcode: [gcode_macro _NOZZLE_XY_OFFSET_CALIBRATE] gcode: RUN_SHELL_COMMAND CMD=fetch_assets PARAMS="\"Gcode\" \"D600Pro2HS\" \"NozzleAglin.zip\"" - SDCARD_PRINT_FILE FILENAME=".PresetModel/NozzleAglin.gcode" \ No newline at end of file + SDCARD_PRINT_FILE FILENAME=".PresetModel/NozzleAglin.gcode" + +[include module/*.cfg] diff --git a/printer_config/F430NX/base.cfg b/printer_config/F430NX/base.cfg index a16495cc..0b30881f 100644 --- a/printer_config/F430NX/base.cfg +++ b/printer_config/F430NX/base.cfg @@ -48,7 +48,7 @@ square_corner_velocity: 5.0 speed: 100 horizontal_move_z: 7 mesh_min: 34.6,17.4 -mesh_max: 420, 300 +mesh_max: 420, 290 probe_count: 5,4 mesh_pps: 2,2 fade_end: 5 @@ -65,7 +65,7 @@ full_steps_per_rotation: 200 endstop_pin: ^PC10 position_min: -20 position_endstop: -20 -position_max: 475 +position_max: 400 homing_speed: 100 homing_retract_dist: 10 step_pulse_duration:0.0000025 @@ -152,8 +152,9 @@ heater_pin: PD12 sensor_type: Generic 3950 sensor_pin: PC0 max_power: 1.0 -min_temp: 0 -max_temp: 150 +min_temp: -20 +max_temp: 140 +overshoot: 10 # control: pid # pid_kp: 40.673 # pid_ki: 0.837 @@ -170,8 +171,9 @@ heater_pin: PD15 max_power: 1.0 sensor_type: Generic 3950 sensor_pin: PC3 -min_temp: 0 -max_temp: 80 +min_temp: -20 +max_temp: 70 +overshoot: 10 # control: pid # pid_kp: 30.68 # pid_ki: 0.21 @@ -203,7 +205,7 @@ kick_start_time: 1.0 pin: PC6 max_power: 0.8 heater: -stepper: stepper_x, stepper_z, dual_carriage +stepper: stepper_x, stepper_z, dual_carriage idle_speed: 0.5 [delayed_gcode INIT_LIGHT] @@ -298,8 +300,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: L_tool:PA8 max_power: 1.0 -min_temp: 0 +min_temp: -20 max_temp: 450 +overshoot: 20 min_extrude_temp: 150 pressure_advance: 0.032 pressure_advance_smooth_time:0.040 @@ -391,8 +394,9 @@ max_extrude_only_accel: 1000.0 max_extrude_cross_section:5 heater_pin: R_tool:PA8 max_power: 1.0 -min_temp: 0 +min_temp: -20 max_temp: 450 +overshoot: 20 min_extrude_temp: 150 pressure_advance: 0.032 pressure_advance_smooth_time:0.040 @@ -442,7 +446,10 @@ gcode: [gcode_macro T0] gcode: - {% set filament_insert = printer["filament_switch_sensor extruder"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor|default("") == "" + else True if not printer[client.filament_sensor].enabled + else printer[client.filament_sensor].filament_detected|default(False) %} {% set printing = printer.print_stats.state == "printing" %} {% if filament_insert or printing == False %} {% if "x" not in printer.toolhead.homed_axes %} @@ -490,7 +497,10 @@ gcode: {% set y_offset = svv.nozzle_y_offset_val|default(0)|float %} {% set z_offset = svv.nozzle_z_offset_val|default(0)|float %} - {% set filament_insert = printer["filament_switch_sensor extruder1"].filament_detected|default(False) %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} + {% set filament_insert = True if client.filament_sensor1|default("") == "" + else True if not printer[client.filament_sensor1].enabled + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} {% if "x" not in printer.toolhead.homed_axes %} @@ -838,13 +848,14 @@ gcode: [gcode_macro _USER_PAUSE] gcode: - {% set extruderTools = [('extruder', 'last_extruder_temp'), - ('extruder1', 'last_extruder1_temp')] %} + {% set heaters = [('extruder', 'last_extruder_temp'), + ('extruder1', 'last_extruder1_temp'), + ('heater_bed', 'last_bed_temp')] %} {% set act = printer.gcode_move.gcode_position %} SAVE_VARIABLE VARIABLE=power_resume_z VALUE={act.z} - {% for extruder_name, name in extruderTools %} - {% set temp = printer[extruder_name].target if extruder_name in printer else 0 %} - {% set restore = False if printer[extruder_name] == '' + {% for heater, name in heaters %} + {% set temp = printer[heater].target if heater in printer else 0 %} + {% set restore = False if printer[heater] == '' else True if params.RESTORE|default(1)|int == 1 else False %} SET_GCODE_VARIABLE MACRO=RESUME VARIABLE={name} VALUE="{{'restore': restore, 'temp': temp}}" {% endfor %} @@ -864,6 +875,10 @@ gcode: {% set extruder_info = [ {'index': 0, 'name': 'last_extruder_temp'}, {'index': 1, 'name': 'last_extruder1_temp'}] %} + {% set value = printer["gcode_macro RESUME"]["last_bed_temp"].temp %} + {% if value != 0 %} + M190 S{value} + {% endif %} {% set temperature = "last_extruder_temp" if printer.toolhead.extruder == "extruder" else "last_extruder1_temp" %} {% set value = printer["gcode_macro RESUME"][temperature].temp %} {% for info in extruder_info %} @@ -980,6 +995,7 @@ description: Resume the actual running print rename_existing: RESUME_BASE variable_last_extruder_temp: {'restore': False, 'temp': 0} variable_last_extruder1_temp: {'restore': False, 'temp': 0} +variable_last_bed_temp: {'restore': False, 'temp': 0} variable_restore_idle_timeout: 0 variable_idle_state: False variable_resume_dual: False @@ -1146,9 +1162,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -1164,9 +1180,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -1176,7 +1192,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/printer_config/module/door_detect.cfg b/printer_config/module/door_detect.cfg new file mode 100644 index 00000000..bbafd803 --- /dev/null +++ b/printer_config/module/door_detect.cfg @@ -0,0 +1,32 @@ +[gcode_button _door_detection] +pin: DOOR_PIN +press_gcode: +release_gcode: + {% set sv = printer.save_variables.variables %} + {% set door_function = sv.door_detect|default("Disabled") %} + {% if door_function != "Disabled" %} + M118 Printer door is opening! + {% endif %} + _DOOR_DETECTION_HANDLE STATUS='open' + +[gcode_macro _DOOR_DETECTION_HANDLE] +gcode: + {% set sv = printer.save_variables.variables %} + {% set door_function = sv.door_detect|default("Disabled") %} + {% set status = params.STATUS|default("close") %} + {% set printing_state = printer.print_stats.state %} + {% if status=='open' and printing_state == 'printing' %} + {% if door_function == 'Emergency Stop' %} + M112 + {% elif door_function == 'Pause Print' %} + PAUSE + {% endif %} + {% endif %} + +[gcode_macro _DOOR_START_PRINT_BASE] +description: Call handle door is open when starting to print +gcode: + RESPOND TYPE=command MSG="action:prompt_begin" + RESPOND TYPE=command MSG="action:prompt_text Printer door is opened. Please close the door and then start printing." + RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end" + RESPOND TYPE=command MSG="action:prompt_show" diff --git a/screen.py b/screen.py index d3196e79..be0bfe56 100755 --- a/screen.py +++ b/screen.py @@ -66,7 +66,7 @@ class KlipperScreen(Gtk.Window): _ws = None screensaver_timeout = None reinit_count = 0 - max_retries = 4 + max_retries = 14 initialized = initializing = False popup_timeout = None wayland = False