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
This commit is contained in:
parent
c6fdab554b
commit
9ee9f7bffb
7 changed files with 45 additions and 13 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@
|
|||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: feature_sdAlwaysAvailable" id="settings-featureSdAlwaysAvailable"> {{ _('Always assume SD card is present') }} <span class="label">{{ _('Repetier') }}</span>
|
||||
<input type="checkbox" data-bind="checked: feature_waitForStart" id="settings-featureWaitForStart"> {{ _('Wait for <code>start</code> on connect') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: feature_waitForStart" id="settings-featureWaitForStart"> {{ _('Wait for <code>start</code> on connect') }}
|
||||
<input type="checkbox" data-bind="checked: feature_sdAlwaysAvailable" id="settings-featureSdAlwaysAvailable"> {{ _('Always assume SD card is present') }} <span class="label">{{ _('Repetier') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -55,6 +55,13 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: feature_disableExternalHeatupDetection" id="settings-featureExternalHeatupDetection"> {{ _('Disable detection of external heatups') }} <span class="label">{{ _('Repetier') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
|
|
|
|||
|
|
@ -770,6 +770,8 @@ class MachineCom(object):
|
|||
feedback_errors = []
|
||||
pause_triggers = convert_pause_triggers(settings().get(["printerParameters", "pauseTriggers"]))
|
||||
|
||||
disable_external_heatup_detection = not settings().getBoolean(["feature", "externalHeatupDetection"])
|
||||
|
||||
#Open the serial port.
|
||||
if not self._openSerial():
|
||||
return
|
||||
|
|
@ -860,7 +862,7 @@ class MachineCom(object):
|
|||
|
||||
##~~ Temperature processing
|
||||
if ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:'):
|
||||
if not line.strip().startswith("ok") and not self._heating:
|
||||
if not disable_external_heatup_detection and not line.strip().startswith("ok") and not self._heating:
|
||||
self._logger.debug("Externally triggered heatup detected")
|
||||
self._heating = True
|
||||
self._heatupWaitStartTime = time.time()
|
||||
|
|
|
|||
Loading…
Reference in a new issue