diff --git a/README.md b/README.md index 1a96bc5..90f29bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RewriteM600 -Implement M600 for pinters that can't support M600 by default (TFT with out Marlin Mode support, like Artilelry X1 and Genius). You can use M600, is going to stop wait until you change and press resume. If you have a TFT 28 (Like the Artillery) i would recomend you to check [Rawr TFT Firmware](https://github.com/wgcv/RAWR-TFT-Firmware-Artillery3D) to implement M600 direct in the TFT and do not need Octoprint. +Implement M600 for pinters that can't support M600 by default (TFT with out Marlin Mode support, like the Artillery Sidewinder X1 and Genius). You can use M600, it will stop and wait until you change and press resume. If you have a TFT 28 (like the Artillery) I would recomend you check out [Rawr TFT Firmware](https://github.com/wgcv/RAWR-TFT-Firmware-Artillery3D) to implement M600 direct in the TFT then do not need Octoprint. ## Setup @@ -14,12 +14,16 @@ Copy or manually using this URL: https://github.com/wgcv/RewriteM600/archive/master.zip +## Configuration - +As this plugin only tries to recognize the correct pausing position as a response to the `M114`-marlin-command, it is possible to change the default behaviour. +The plugin provides the dict `cached_position` (with members `x`, `y`, `z` and `e`) to the GCODE-Script `beforePrintResumed`. You can access them via `{{plugins.RewriteM600.cached_position.(x|y|z|e)}}`. ## Screenshots +  ## Support -You can help this project reporting issues, making PR or Sponsor it [PayPal](https://paypal.me/wgcvl). + +You can help this project by reporting issues, making PR or Sponsor it [PayPal](https://paypal.me/wgcv). diff --git a/octoprint_RewriteM600/__init__.py b/octoprint_RewriteM600/__init__.py index 6933619..aec04f8 100644 --- a/octoprint_RewriteM600/__init__.py +++ b/octoprint_RewriteM600/__init__.py @@ -1,5 +1,6 @@ # coding=utf-8 from __future__ import absolute_import +import re ### (Don't forget to remove me) # This is a basic skeleton for your plugin's __init__.py. You probably want to adjust the class name of your plugin @@ -12,40 +13,110 @@ import octoprint.plugin class Rewritem600Plugin(octoprint.plugin.AssetPlugin, octoprint.plugin.TemplatePlugin, octoprint.plugin.SettingsPlugin): + cached_position = {"x": "NOT SET", "y": "NOT SET", "z": "NOT SET", "e": "NOT SET"} + listening = False + waiting = False + waitingForPause = False; + waitingForResume = False; + resumeScript = None; + + def on_settings_initialized(self): + scripts = self._settings.listScripts("gcode") + if not "rewrite_m600_pause" in scripts: + self._settings.saveScript("gcode", "rewrite_m600_pause", u'' + self._settings.get(["pauseCommand"])) + if not "rewrite_m600_resume" in scripts: + self._settings.saveScript("gcode", "rewrite_m600_resume", u'' + self._settings.get(["resumeCommand"])) + + def on_settings_save(self, data): + if 'pauseCommand' in data: + script = data["pauseCommand"] + self._settings.saveScript("gcode", "rewrite_m600_pause", u'' + script.replace("\r\n", "\n").replace("\r", "\n")) + # data.pop('pauseCommand') + if 'resumeCommand' in data: + script = data["resumeCommand"] + self._settings.saveScript("gcode", "rewrite_m600_resume", u'' + script.replace("\r\n", "\n").replace("\r", "\n")) + octoprint.plugin.SettingsPlugin.on_settings_save(self, data) + def rewrite_m600(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs): if gcode and gcode == "M600": - self._plugin_manager.send_plugin_message(self._identifier, dict(type="popup", msg="Please change the filament and resume the print")) - comm_instance.setPause(True) - cmd = [("M117 Filament Change",),"G91","M83", "G1 Z+"+self._settings.get(["zDistance"])+" E-0.8 F4500", "M82", "G90", "G1 X0 Y0"] + self._logger.info("rewrite_m600") + self._plugin_manager.send_plugin_message(self._identifier, + dict(type = "popup", + msg = "Please change the filament and resume the print")) + self.listening = True + cmd = ["G4 S" + str(self._settings.get(["timeG4"])), "M114", "G4 S" + str(self._settings.get(["timeG4"])), "@setpause"] + self._logger.info(cmd) + self._logger.info(self.cached_position) + self.waiting = True + self.waitingForPause = True; return cmd + + def toggle_pause(self, comm_instance, phase, command, parameters, tags=None, *args, **kwargs): + if command == "setpause" and self.waitingForPause: + self._logger.info("setpause") + if self._settings.get(["defaultPause"]): + comm_instance.setPause(True) + else: + comm_instance.setPause(True, local_handling = False) # sorgt dafür, dass das Pause-Script nicht ausgeführt wird! + self._printer.script("rewrite_m600_pause", must_be_set=False) + self.waitingForPause = False + if command == "afterResumed" and self.waitingForResume: + self._logger.info("afterResumed") + self._settings.saveScript("gcode", "beforePrintResumed", u'' + self.resumeScript) + self.waitingForResume = False + + def detect_position(self, comm_instance, line, *args, **kwargs): + # ok X:20.0 Y:20.0 Z:0.6 E:20.01306 Count: A:2000 B:2000 C:60 + # match = re.match("X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:-?([0-9.]+) Count X|A:([0-9]+) Y|B:([0-9]+) Z|C:([0-9]+)", line) + match = re.search(self._settings.get(["regularExpression"]), line) + if match is not None and self.listening: + self._logger.info("DetectPosition: " + line) + self.cached_position["x"] = match.group(self._settings.get(["x"])) + self.cached_position["y"] = match.group(self._settings.get(["y"])) + self.cached_position["z"] = match.group(self._settings.get(["z"])) + self.cached_position["e"] = match.group(self._settings.get(["e"])) + self._logger.info("CachedPosition: " + self.cached_position["x"]) + self._plugin_manager.send_plugin_message(self._identifier, dict(type="popup", msg = "Saved location at X:" + + self.cached_position["x"] + " Y:" + self.cached_position["y"] + + " Z:" + self.cached_position["z"])) + self.listening = False # Reset so we don't listen to the update called on print pause + self._logger.info(self.cached_position) + return line + + def after_resume(self, comm_instance, script_type, script_name, *args, **kwargs): + self._logger.info("Received queued command: " + script_name) + if self.waiting and script_type == "gcode" and script_name == "beforePrintResumed": + self._logger.info("Resuming from Filament Change") + self.waiting = False + self._plugin_manager.send_plugin_message(self._identifier, dict(type = "popup", msg = "Resuming to location at X:" + + self.cached_position["x"] + " Y:" + self.cached_position["y"] + + " Z:" + self.cached_position["z"])) + variables = dict(cached=self.cached_position) + if not self._settings.get(["defaultResume"]): + # Script ausführen + self._printer.script("rewrite_m600_resume", context=variables, must_be_set=False) + # script laden & leeren + self.resumeScript = self._settings.loadScript("gcode", "beforePrintResumed", source=True) + self._settings.saveScript("gcode", "beforePrintResumed", u'') + self.waitingForResume = True + self.cached_position = {"x": "NOT SET", "y": "NOT SET", "z": "NOT SET", "e": "NOT SET"} + return None, ["@afterResumed"], variables - def after_resume(self, comm_instance, phase, cmd, parameters, tags=None, *args, **kwargs): - if cmd and cmd == "resume": - if(comm_instance.pause_position.x): - cmd = [] - cmd =["M83","G1 E-0.8 F4500", "G1 E0.8 F4500", "G1 E0.8 F4500", "M82", "G90", "G92 E"+comm_instance.pause_position.e, "M83", "G1 X"+comm_instance.pause_position.x+" Y"+comm_instance.pause_position.y+" Z"+comm_instance.pause_position.z+" F4500"] - if(comm_instance.pause_position.f): - cmd.append("G1 F" + comm_instance.pause_position.f) - comm_instance.commands(cmd) - comm_instance.setPause(False) - return def get_settings_defaults(self): - return dict(zDistance=80) + return dict(x = 1, y = 2, z = 3, e = 4, timeG4 = 5, pauseCommand = "", resumeCommand = "", defaultPause = True, defaultResume = True, regularExpression = "X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:-?([0-9.]+) Count:? (X|A):([0-9]+) (Y|B):([0-9]+) (Z|C):([0-9]+)") def get_template_configs(self): return [ - dict(type="navbar", custom_bindings=False), dict(type="settings", custom_bindings=False) ] + ##~~ AssetPlugin mixin def get_assets(self): # Define your plugin's asset files to automatically include in the # core UI here. return dict( - js=["js/RewriteM600.js"], - css=["css/RewriteM600.css"], - less=["less/RewriteM600.less"] + js = ["js/RewriteM600.js"] ) ##~~ Softwareupdate hook @@ -91,6 +162,7 @@ def __plugin_load__(): __plugin_hooks__ = { "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information, "octoprint.comm.protocol.gcode.queuing": __plugin_implementation__.rewrite_m600, - "octoprint.comm.protocol.atcommand.queuing": __plugin_implementation__.after_resume, + "octoprint.comm.protocol.scripts": __plugin_implementation__.after_resume, + "octoprint.comm.protocol.gcode.received": __plugin_implementation__.detect_position, + "octoprint.comm.protocol.atcommand.queuing": __plugin_implementation__.toggle_pause, } - diff --git a/octoprint_RewriteM600/static/js/RewriteM600.js b/octoprint_RewriteM600/static/js/RewriteM600.js index d0f7696..f52d186 100644 --- a/octoprint_RewriteM600/static/js/RewriteM600.js +++ b/octoprint_RewriteM600/static/js/RewriteM600.js @@ -7,10 +7,20 @@ $(function() { function Rewritem600ViewModel(parameters) { var self = this; + + self.settings = parameters[0]; + self.defaultPause = ko.observable(); + self.defaultResume = ko.observable(); // assign the injected parameters, e.g.: // self.loginStateViewModel = parameters[0]; // self.settingsViewModel = parameters[1]; + + self.onBeforeBinding = function() { + console.log(self.settings); + self.defaultPause(self.settings.settings.plugins.RewriteM600.defaultPause()); + self.defaultResume(self.settings.settings.plugins.RewriteM600.defaultResume()); + } // TODO: Implement your plugin's view model here. self.onDataUpdaterPluginMessage = function(plugin, data) { @@ -23,7 +33,7 @@ $(function() { title: 'M600', text: data.msg, type: "info", - hide: false + hide: true }); } } @@ -36,8 +46,8 @@ $(function() { OCTOPRINT_VIEWMODELS.push({ construct: Rewritem600ViewModel, // ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ... - dependencies: [ /* "loginStateViewModel", "settingsViewModel" */ ], + dependencies: [ "settingsViewModel"/* "loginStateViewModel", "settingsViewModel" */ ], // Elements to bind to, e.g. #settings_plugin_RewriteM600, #tab_plugin_RewriteM600, ... - elements: [ /* ... */ ] + elements: [ ] }); }); diff --git a/octoprint_RewriteM600/templates/RewriteM600_settings.jinja2 b/octoprint_RewriteM600/templates/RewriteM600_settings.jinja2 index 0909f6e..e7d460e 100644 --- a/octoprint_RewriteM600/templates/RewriteM600_settings.jinja2 +++ b/octoprint_RewriteM600/templates/RewriteM600_settings.jinja2 @@ -1,8 +1,77 @@ +
afterPrintPaused (from GCODE Scripts) is sent to the printer. Otherwise, the gcode stated in the following textarea is used.
+ beforePrintResumed (from GCODE Scripts) is sent to the printer. Otherwise, the gcode stated in the following textarea is used.
+