From 9ee9f7bffbaccf8209056394cb771466304f159b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 24 Apr 2015 09:36:43 +0200 Subject: [PATCH] Workaround for idle temperature polling not working with Repetier Firmware Repetier always first sends the ok and then any command output. In case of M105, that makes the response look like from an externally triggered heatup (no ok on the same line), causing polling to stop until that falsely detected heatup is complete. Added a configuration option to disable heatup detection. The disadvantage of this is that when printing via Repetier Firmware from SD, the heatup times won't be substractable from the total print time, leading to a less accurate print time left estimation. Closes #835 --- docs/configuration/config_yaml.rst | 5 ++++ .../plugins/virtual_printer/virtual.py | 29 +++++++++++++------ src/octoprint/server/api/settings.py | 2 ++ src/octoprint/settings.py | 4 ++- .../static/js/app/viewmodels/settings.js | 3 ++ .../dialogs/settings/features.jinja2 | 11 +++++-- src/octoprint/util/comm.py | 4 ++- 7 files changed, 45 insertions(+), 13 deletions(-) diff --git a/docs/configuration/config_yaml.rst b/docs/configuration/config_yaml.rst index 2823c05a..11981684 100644 --- a/docs/configuration/config_yaml.rst +++ b/docs/configuration/config_yaml.rst @@ -393,6 +393,11 @@ Use the following settings to enable or disable OctoPrint features: # instead of attaching that information to the regular M105 responses repetierTargetTemp: false + # Whether to enable external heatup detection (to detect heatup triggered e.g. through the printer's LCD panel or + # while printing from SD) or not. Causes issues with Repetier's "first ok then response" approach to + # communication, so disable for printers running Repetier firmware. + externalHeatupDetection: true + # Whether to enable the keyboard control feature in the control tab keyboardControl: true diff --git a/src/octoprint/plugins/virtual_printer/virtual.py b/src/octoprint/plugins/virtual_printer/virtual.py index 633aa301..8f54cb28 100644 --- a/src/octoprint/plugins/virtual_printer/virtual.py +++ b/src/octoprint/plugins/virtual_printer/virtual.py @@ -59,6 +59,8 @@ class VirtualPrinter(): self._newSdFilePos = None self._heatupThread = None + self._okBeforeCommandOutput = settings().getBoolean(["devel", "virtualPrinter", "okBeforeCommandOutput"]) + self.currentLine = 0 self.lastN = 0 @@ -147,14 +149,15 @@ class VirtualPrinter(): self._sendOk() continue + if len(data.strip()) > 0 and self._okBeforeCommandOutput: + self._sendOk() + #print "Send: %s" % (data.rstrip()) if 'M104' in data or 'M109' in data: self._parseHotendCommand(data) - continue if 'M140' in data or 'M190' in data: self._parseBedCommand(data) - continue if 'M105' in data: self._processTemperatureQuery() @@ -197,7 +200,10 @@ class VirtualPrinter(): self._deleteSdFile(filename) elif "M114" in data: # send dummy position report - self.outgoing.put("ok C: X:10.00 Y:3.20 Z:5.20 E:1.24") + output = "C: X:10.00 Y:3.20 Z:5.20 E:1.24" + if not self._okBeforeCommandOutput: + output = "ok " + output + self.outgoing.put(output) continue elif "M117" in data: # we'll just use this to echo a message, to allow playing around with pause triggers @@ -259,7 +265,7 @@ class VirtualPrinter(): self.outgoing.put("// sleeping for {interval} seconds".format(interval=interval)) time.sleep(interval) - if len(data.strip()) > 0: + if len(data.strip()) > 0 and not self._okBeforeCommandOutput: self._sendOk() def _debugTrigger(self, data): @@ -343,6 +349,7 @@ class VirtualPrinter(): def _processTemperatureQuery(self): includeTarget = not settings().getBoolean(["devel", "virtualPrinter", "repetierStyleTargetTemperature"]) + includeOk = not self._okBeforeCommandOutput # send simulated temperature data if settings().getInt(["devel", "virtualPrinter", "numExtruders"]) > 1: @@ -362,16 +369,20 @@ class VirtualPrinter(): if settings().getBoolean(["devel", "virtualPrinter", "includeCurrentToolInTemps"]): if includeTarget: - self.outgoing.put("ok T:%.2f /%.2f %s @:64\n" % (self.temp[self.currentExtruder], self.targetTemp[self.currentExtruder] + 1, allTempsString)) + output = "T:%.2f /%.2f %s @:64\n" % (self.temp[self.currentExtruder], self.targetTemp[self.currentExtruder] + 1, allTempsString) else: - self.outgoing.put("ok T:%.2f %s @:64\n" % (self.temp[self.currentExtruder], allTempsString)) + output = "T:%.2f %s @:64\n" % (self.temp[self.currentExtruder], allTempsString) else: - self.outgoing.put("ok %s @:64\n" % allTempsString) + output = "%s @:64\n" % allTempsString else: if includeTarget: - self.outgoing.put("ok T:%.2f /%.2f B:%.2f /%.2f @:64\n" % (self.temp[0], self.targetTemp[0], self.bedTemp, self.bedTargetTemp)) + output = "T:%.2f /%.2f B:%.2f /%.2f @:64\n" % (self.temp[0], self.targetTemp[0], self.bedTemp, self.bedTargetTemp) else: - self.outgoing.put("ok T:%.2f B:%.2f @:64\n" % (self.temp[0], self.bedTemp)) + output = "T:%.2f B:%.2f @:64\n" % (self.temp[0], self.bedTemp) + + if includeOk: + output = "ok " + output + self.outgoing.put(output) def _parseHotendCommand(self, line): tool = 0 diff --git a/src/octoprint/server/api/settings.py b/src/octoprint/server/api/settings.py index 4c24cb2b..f57b8799 100644 --- a/src/octoprint/server/api/settings.py +++ b/src/octoprint/server/api/settings.py @@ -64,6 +64,7 @@ def getSettings(): "sdAlwaysAvailable": s.getBoolean(["feature", "sdAlwaysAvailable"]), "swallowOkAfterResend": s.getBoolean(["feature", "swallowOkAfterResend"]), "repetierTargetTemp": s.getBoolean(["feature", "repetierTargetTemp"]), + "externalHeatupDetection": s.getBoolean(["feature", "externalHeatupDetection"]), "keyboardControl": s.getBoolean(["feature", "keyboardControl"]) }, "serial": { @@ -175,6 +176,7 @@ def setSettings(): if "sdAlwaysAvailable" in data["feature"].keys(): s.setBoolean(["feature", "sdAlwaysAvailable"], data["feature"]["sdAlwaysAvailable"]) if "swallowOkAfterResend" in data["feature"].keys(): s.setBoolean(["feature", "swallowOkAfterResend"], data["feature"]["swallowOkAfterResend"]) if "repetierTargetTemp" in data["feature"].keys(): s.setBoolean(["feature", "repetierTargetTemp"], data["feature"]["repetierTargetTemp"]) + if "externalHeatupDetection" in data["feature"].keys(): s.setBoolean(["feature", "externalHeatupDetection"], data["feature"]["externalHeatupDetection"]) if "keyboardControl" in data["feature"].keys(): s.setBoolean(["feature", "keyboardControl"], data["feature"]["keyboardControl"]) if "serial" in data.keys(): diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index 27dec306..8257cb6a 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -136,6 +136,7 @@ default_settings = { "sdAlwaysAvailable": False, "swallowOkAfterResend": True, "repetierTargetTemp": False, + "externalHeatupDetection": True, "keyboardControl": True }, "folder": { @@ -255,6 +256,7 @@ default_settings = { }, "hasBed": True, "repetierStyleTargetTemperature": False, + "okBeforeCommandOutput": False, "smoothieTemperatureReporting": False, "extendedSdFileList": False, "throttle": 0.01, @@ -501,7 +503,7 @@ class Settings(object): elif "children" in result: # if it has children we need to process them recursively - result["children"] = map(process_control, result["children"]) + result["children"] = map(process_control, [child for child in result["children"] if child is not None]) return result diff --git a/src/octoprint/static/js/app/viewmodels/settings.js b/src/octoprint/static/js/app/viewmodels/settings.js index ef62f8f7..9fbdd38b 100644 --- a/src/octoprint/static/js/app/viewmodels/settings.js +++ b/src/octoprint/static/js/app/viewmodels/settings.js @@ -79,6 +79,7 @@ $(function() { self.feature_sdAlwaysAvailable = ko.observable(undefined); self.feature_swallowOkAfterResend = ko.observable(undefined); self.feature_repetierTargetTemp = ko.observable(undefined); + self.feature_disableExternalHeatupDetection = ko.observable(undefined); self.feature_keyboardControl = ko.observable(undefined); self.serial_port = ko.observable(); @@ -227,6 +228,7 @@ $(function() { self.feature_sdAlwaysAvailable(response.feature.sdAlwaysAvailable); self.feature_swallowOkAfterResend(response.feature.swallowOkAfterResend); self.feature_repetierTargetTemp(response.feature.repetierTargetTemp); + self.feature_disableExternalHeatupDetection(!response.feature.externalHeatupDetection); self.feature_keyboardControl(response.feature.keyboardControl); self.serial_port(response.serial.port); @@ -303,6 +305,7 @@ $(function() { "sdAlwaysAvailable": self.feature_sdAlwaysAvailable(), "swallowOkAfterResend": self.feature_swallowOkAfterResend(), "repetierTargetTemp": self.feature_repetierTargetTemp(), + "externalHeatupDetection": !self.feature_disableExternalHeatupDetection(), "keyboardControl": self.feature_keyboardControl() }, "serial": { diff --git a/src/octoprint/templates/dialogs/settings/features.jinja2 b/src/octoprint/templates/dialogs/settings/features.jinja2 index f00b4640..cf669653 100644 --- a/src/octoprint/templates/dialogs/settings/features.jinja2 +++ b/src/octoprint/templates/dialogs/settings/features.jinja2 @@ -30,14 +30,14 @@
@@ -55,6 +55,13 @@ +
+
+ +
+