Merge commit '26452c9873d242518ae23f4db995367fbd21361d' into release

This commit is contained in:
张开科 2025-03-31 11:13:17 +08:00
commit 2676709ed5
11 changed files with 277 additions and 73 deletions

@ -1,6 +1,20 @@
CreatBot_F430NX
CreatBot_D600Pro2
CreatBot_D600Pro2_V0
CreatBot_D1000
CreatBot_D1000_V0
CreatBot_P800
[CreatBot_F430NX]
versions = 1.0
[CreatBot_D600Pro2HS]
versions = 1.0, 1.1
#V1.1 Add door detection
[CreatBot_D600Pro2HS_KIT]
versions = 1.0
[CreatBot_D1000HS]
versions = 1.0, 1.1
#V1.1 Add door detection
[CreatBot_D1000HS_KIT]
versions = 1.0
[CreatBot_P800]
versions = 1.0

@ -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)

@ -100,9 +100,17 @@ class ModelConfig:
f"Configuration file {self.klipperscreen_config_path} not found."
)
def wirte_printer_config(self, device_name):
def wirte_printer_config(self, device_name, version):
config_dict = {
"CreatBot_F430NX": "CreatBot_F430NX",
"CreatBot_D600Pro2HS": "CreatBot_D600Pro2",
"CreatBot_D600Pro2HS_KIT": "CreatBot_D600Pro2_V0",
"CreatBot_D1000HS": "CreatBot_D1000",
"CreatBot_D1000HS_KIT": "CreatBot_D1000_V0",
"CreatBot_P800": "CreatBot_P800",
}
if device_name:
source_path = f"{os.path.expanduser('~')}/klipper/config/{device_name}/"
source_path = f"{os.path.expanduser('~')}/klipper/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)
@ -120,6 +128,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]
@ -143,13 +166,13 @@ 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
model_name = model_name.split("_")[1]
device_name = self.generate_machine_name(model_name)
self.write_mdns_config(device_name)
self.write_device_name_config(device_name)
self.wirte_printer_config(model)
self.wirte_printer_config(model, version)
self.wirte_hostname(device_name)
os.system("systemctl restart klipper.service")
os.system("systemctl restart moonraker.service")

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 ""

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: KlipperScreen\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: 2024-06-03 19:09+0000\n"
"Last-Translator: wsj20050623 <2129426599@qq.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
@ -77,6 +77,9 @@ msgstr "激活"
msgid "Adaptive Bed Leveling"
msgstr "自适应床调平"
msgid "Add"
msgstr "加"
msgid "Add profile"
msgstr "添加配置文件"
@ -293,6 +296,9 @@ msgstr "关闭电机"
msgid "Disable for 12hs with am / pm"
msgstr "在十二小时显示模式中不现实AM/PM"
msgid "Disabled"
msgstr "禁用"
msgid "Disconnect"
msgstr "断开"
@ -307,6 +313,9 @@ msgstr "您要忘记或断开%s的连接吗?"
msgid "Do you want to recover %s?"
msgstr "你想恢复 %s 吗?"
msgid "Door Open Protection Mode"
msgstr "开门保护模式"
msgid "Elapsed trial time:"
msgstr "已用时间:"
@ -322,9 +331,6 @@ msgstr "启用注册码"
msgid "Enable screen power management"
msgstr "开启屏幕功率管理功能"
msgid "Enabled successfully"
msgstr "启用成功"
msgid "Error"
msgstr "错误"
@ -644,6 +650,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 "此操作即将开始打印模型"
@ -1228,6 +1251,15 @@ msgid "second"
msgid_plural "seconds"
msgstr[0] "秒"
#~ msgid "Enabled successfully"
#~ msgstr "启用成功"
#~ msgid "Reset"
#~ msgstr "重置"
#~ msgid "Reset successfully"
#~ msgstr "重置成功"
#~ msgid "Connected"
#~ msgstr "已连接"
@ -1344,9 +1376,6 @@ msgstr[0] "秒"
#~ msgid "Homing"
#~ msgstr "归零"
#~ msgid "Disable XY"
#~ msgstr "关闭 XY 轴电机"
#~ msgid "Slicer Time correction (%)"
#~ msgstr "切片软件时间校正(%)"

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: KlipperScreen\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: 2024-06-01 12:09+0000\n"
"Last-Translator: 峻瑜哥 <a728728728@gmail.com>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
@ -77,6 +77,9 @@ msgstr "激活"
msgid "Adaptive Bed Leveling"
msgstr "自適應床調平"
msgid "Add"
msgstr "加"
msgid "Add profile"
msgstr "新增設定檔案"
@ -293,6 +296,9 @@ msgstr "關閉電機"
msgid "Disable for 12hs with am / pm"
msgstr "在十二小時顯示模式中不顯示AM/PM"
msgid "Disabled"
msgstr "禁用"
msgid "Disconnect"
msgstr "断开"
@ -307,6 +313,9 @@ msgstr "您要忘記或斷開%s的連接嗎?"
msgid "Do you want to recover %s?"
msgstr "你想恢復 %s 嗎?"
msgid "Door Open Protection Mode"
msgstr "開門保護模式"
msgid "Elapsed trial time:"
msgstr "已用時間"
@ -322,9 +331,6 @@ msgstr "啟用註冊碼"
msgid "Enable screen power management"
msgstr "開啟螢幕功率管理功能"
msgid "Enabled successfully"
msgstr "啟用成功"
msgid "Error"
msgstr "錯誤"
@ -644,6 +650,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 "此操作即將開始打印模型"
@ -1228,6 +1251,15 @@ msgid "second"
msgid_plural "seconds"
msgstr[0] "秒"
#~ msgid "Enabled successfully"
#~ msgstr "啟用成功"
#~ msgid "Reset"
#~ msgstr "重置"
#~ msgid "Reset successfully"
#~ msgstr "重置成功"
#~ msgid "Connected"
#~ msgstr "已連線"
@ -1314,9 +1346,6 @@ msgstr[0] "秒"
#~ msgid "Homing"
#~ msgstr "归零"
#~ msgid "Disable XY"
#~ msgstr "关闭 XY 轴电机"
#~ msgid "Slicer Time correction (%)"
#~ msgstr "切片软件时间校正(%)"

@ -13,4 +13,10 @@ prompts_text = [
_("Left extruder detects no filament, please load filament and continue."),
_("Right extruder detects no filament, please load filament and continue."),
_("Ok"),
_("Disabled"),
_("Pause Print"),
_("Printer door is opening!"),
_("Printer door is opened. Please close the door and then start printing."),
_("Please close the door and click Resume to proceed.")
]

@ -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)

@ -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)