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