From 216f05d553b738b8c94fed0ab9f6d0df839d7ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 24 Jan 2017 18:15:49 +0100 Subject: [PATCH] Hibernate communication with printer during active G4 on Repetier Should hopefully solve #1506 --- .../plugins/virtual_printer/virtual.py | 19 +++++++++++++++++ src/octoprint/server/api/settings.py | 4 +++- src/octoprint/settings.py | 7 ++++--- .../static/js/app/viewmodels/settings.js | 1 + .../dialogs/settings/features.jinja2 | 7 +++++++ src/octoprint/util/comm.py | 21 ++++++++++++++++--- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/octoprint/plugins/virtual_printer/virtual.py b/src/octoprint/plugins/virtual_printer/virtual.py index ac8d7ed5..7bad238e 100644 --- a/src/octoprint/plugins/virtual_printer/virtual.py +++ b/src/octoprint/plugins/virtual_printer/virtual.py @@ -92,6 +92,7 @@ class VirtualPrinter(object): self._supportF = settings().getBoolean(["devel", "virtualPrinter", "supportF"]) self._sendWait = settings().getBoolean(["devel", "virtualPrinter", "sendWait"]) + self._sendBusy = settings().getBoolean(["devel", "virtualPrinter", "sendBusy"]) self._waitInterval = settings().getFloat(["devel", "virtualPrinter", "waitInterval"]) self._echoOnM117 = settings().getBoolean(["devel", "virtualPrinter", "echoOnM117"]) @@ -451,6 +452,24 @@ class VirtualPrinter(object): _gcode_G2 = _gcode_G0 _gcode_G3 = _gcode_G0 + def _gcode_G4(self, data): + matchS = re.search('S([0-9]+)', data) + matchP = re.search('P([0-9]+)', data) + + _timeout = 0 + if matchP: + _timeout = float(matchP.group(1)) / 1000.0 + elif matchS: + _timeout = float(matchS.group(1)) + + if self._sendBusy: + until = time.time() + _timeout + while time.time() < until: + time.sleep(1.0) + self._send("busy:processing") + else: + time.sleep(_timeout) + ##~~ further helpers def _calculate_checksum(self, line): diff --git a/src/octoprint/server/api/settings.py b/src/octoprint/server/api/settings.py index 90fc3c6b..0276eb01 100644 --- a/src/octoprint/server/api/settings.py +++ b/src/octoprint/server/api/settings.py @@ -126,7 +126,8 @@ def getSettings(): "ignoreIdenticalResends": s.getBoolean(["feature", "ignoreIdenticalResends"]), "modelSizeDetection": s.getBoolean(["feature", "modelSizeDetection"]), "firmwareDetection": s.getBoolean(["feature", "firmwareDetection"]), - "printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"]) + "printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"]), + "blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"]) }, "serial": { "port": connectionOptions["portPreference"], @@ -311,6 +312,7 @@ def _saveSettings(data): if "modelSizeDetection" in data["feature"]: s.setBoolean(["feature", "modelSizeDetection"], data["feature"]["modelSizeDetection"]) if "firmwareDetection" in data["feature"]: s.setBoolean(["feature", "firmwareDetection"], data["feature"]["firmwareDetection"]) if "printCancelConfirmation" in data["feature"]: s.setBoolean(["feature", "printCancelConfirmation"], data["feature"]["printCancelConfirmation"]) + if "blockWhileDwelling" in data["feature"]: s.setBoolean(["feature", "blockWhileDwelling"], data["feature"]["blockWhileDwelling"]) if "serial" in data.keys(): if "autoconnect" in data["serial"].keys(): s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"]) diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index 7d677ac0..c8d4fd54 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -168,7 +168,6 @@ default_settings = { "options": {}, "postRoll": 0, "fps": 25, - "capturePostRoll": True }, "cleanTmpAfterDays": 7 }, @@ -203,7 +202,8 @@ default_settings = { "supportFAsCommand": False, "modelSizeDetection": True, "firmwareDetection": True, - "printCancelConfirmation": True + "printCancelConfirmation": True, + "blockWhileDwelling": False }, "folder": { "uploads": None, @@ -357,7 +357,8 @@ default_settings = { "brokenM29": True, "supportF": False, "firmwareName": "Virtual Marlin 1.0", - "sharedNozzle": False + "sharedNozzle": False, + "sendBusy": False, } } } diff --git a/src/octoprint/static/js/app/viewmodels/settings.js b/src/octoprint/static/js/app/viewmodels/settings.js index 7b9394e5..5f1241f4 100644 --- a/src/octoprint/static/js/app/viewmodels/settings.js +++ b/src/octoprint/static/js/app/viewmodels/settings.js @@ -139,6 +139,7 @@ $(function() { self.feature_modelSizeDetection = ko.observable(undefined); self.feature_firmwareDetection = ko.observable(undefined); self.feature_printCancelConfirmation = ko.observable(undefined); + self.feature_blockWhileDwelling = ko.observable(undefined); self.serial_port = ko.observable(); self.serial_baudrate = ko.observable(); diff --git a/src/octoprint/templates/dialogs/settings/features.jinja2 b/src/octoprint/templates/dialogs/settings/features.jinja2 index 1e7c8592..c90bebab 100644 --- a/src/octoprint/templates/dialogs/settings/features.jinja2 +++ b/src/octoprint/templates/dialogs/settings/features.jinja2 @@ -88,6 +88,13 @@ +
+
+ +
+
diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index dd0ab9c6..a43ee9f3 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -284,6 +284,7 @@ class MachineCom(object): self._long_running_command = False self._heating = False + self._dwelling_until = False self._connection_closing = False self._timeout = None @@ -315,6 +316,7 @@ class MachineCom(object): self._unknownCommandsNeedAck = settings().getBoolean(["feature", "unknownCommandsNeedAck"]) self._sdAlwaysAvailable = settings().getBoolean(["feature", "sdAlwaysAvailable"]) self._sdRelativePath = settings().getBoolean(["feature", "sdRelativePath"]) + self._blockWhileDwelling = settings().getBoolean(["feature", "blockWhileDwelling"]) self._currentLine = 1 self._line_mutex = threading.RLock() self._resendDelta = None @@ -1058,6 +1060,7 @@ class MachineCom(object): self.sayHello() while self._monitoring_active: + now = time.time() try: line = self._readline() if line is None: @@ -1066,6 +1069,9 @@ class MachineCom(object): self._consecutive_timeouts = 0 self._timeout = get_new_timeout("communication", self._timeout_intervals) + if self._dwelling_until and now > self._dwelling_until: + self._dwelling_until = False + ##~~ debugging output handling if line.startswith("//"): debugging_output = line[2:].strip() @@ -1147,7 +1153,7 @@ class MachineCom(object): handled = True # process timeouts - elif line == "" and time.time() > self._timeout: + elif line == "" and (not self._blockWhileDwelling or not self._dwelling_until or now > self._dwelling_until) and now > self._timeout: # timeout only considered handled if the printer is printing self._handle_timeout() handled = self.isPrinting() @@ -1237,6 +1243,7 @@ class MachineCom(object): self._alwaysSendChecksum = True self._resendSwallowRepetitions = True + self._blockWhileDwelling = True supportRepetierTargetTemp = True disable_external_heatup_detection = True @@ -1550,7 +1557,7 @@ class MachineCom(object): command or heating, no poll will be done. """ - if self.isOperational() and not self._connection_closing and not self.isStreaming() and not self._long_running_command and not self._heating and not self._manualStreaming: + if self.isOperational() and not self._connection_closing and not self.isStreaming() and not self._long_running_command and not self._heating and not self._dwelling_until and not self._manualStreaming: self.sendCommand("M105", cmd_type="temperature_poll") def _poll_sd_status(self): @@ -1561,7 +1568,7 @@ class MachineCom(object): command or heating, no poll will be done. """ - if self.isOperational() and not self._connection_closing and self.isSdPrinting() and not self._long_running_command and not self._heating: + if self.isOperational() and not self._connection_closing and self.isSdPrinting() and not self._long_running_command and not self._dwelling_until and not self._heating: self.sendCommand("M27", cmd_type="sd_status_poll") def _onConnected(self): @@ -2018,6 +2025,12 @@ class MachineCom(object): if not self._send_queue_active: break + # sleep if we are dwelling + now = time.time() + if self._blockWhileDwelling and self._dwelling_until and now < self._dwelling_until: + time.sleep(self._dwelling_until - now) + self._dwelling_until = False + # fetch command, command type and optional linenumber and sent callback from queue command, linenumber, command_type, on_sent = entry @@ -2422,7 +2435,9 @@ class MachineCom(object): _timeout = float(p_match.group("value")) / 1000.0 elif s_match: _timeout = float(s_match.group("value")) + self._timeout = get_new_timeout("communication", self._timeout_intervals) + _timeout + self._dwelling_until = time.time() + _timeout ##~~ command phase handlers