Shorter timeout during heatup & no scary message on end

Set read timeout on serial port to a much shorter value (default 2.0s)
during a heatup. Firmware should usually send the current temperature
back every second, so if that stops we can consider the heatup to be finished
even if we don't see an ok.

That is important in cases such as SD printing, where we might see a
heatup sequence we didn't trigger ourselves, during which we shouldn't spam
the printer with commands it potentially can't process but after which we
still should take up normal communication again. In case of a heatup sequence
triggered by an SD print we won't see an ok and hence only can now through a
timeout that things are now done printer side. In such a case the user should not
get thrown a scary timeout message in their general direction either.

Solves #1409
This commit is contained in:
Gina Häußge 2016-07-13 17:21:45 +02:00
parent 2cc9631791
commit 937487037a
3 changed files with 45 additions and 13 deletions

View file

@ -16,7 +16,7 @@ from serial import SerialTimeoutException
from octoprint.settings import settings from octoprint.settings import settings
from octoprint.plugin import plugin_manager from octoprint.plugin import plugin_manager
class VirtualPrinter(): class VirtualPrinter(object):
command_regex = re.compile("[GM]\d+") command_regex = re.compile("[GM]\d+")
sleep_regex = re.compile("sleep (\d+)") sleep_regex = re.compile("sleep (\d+)")
sleep_after_regex = re.compile("sleep_after ([GM]\d+) (\d+)") sleep_after_regex = re.compile("sleep_after ([GM]\d+) (\d+)")
@ -25,7 +25,7 @@ class VirtualPrinter():
def __init__(self, read_timeout=5.0, write_timeout=10.0): def __init__(self, read_timeout=5.0, write_timeout=10.0):
import logging import logging
self._logger = logging.getLogger("octoprint.plugin.virtual_printer.VirtualPrinter") self._logger = logging.getLogger("octoprint.plugins.virtual_printer.VirtualPrinter")
self._read_timeout = read_timeout self._read_timeout = read_timeout
self._write_timeout = write_timeout self._write_timeout = write_timeout
@ -108,6 +108,24 @@ class VirtualPrinter():
return "VIRTUAL(read_timeout={read_timeout},write_timeout={write_timeout},options={options})"\ return "VIRTUAL(read_timeout={read_timeout},write_timeout={write_timeout},options={options})"\
.format(read_timeout=self._read_timeout, write_timeout=self._write_timeout, options=settings().get(["devel", "virtualPrinter"])) .format(read_timeout=self._read_timeout, write_timeout=self._write_timeout, options=settings().get(["devel", "virtualPrinter"]))
@property
def timeout(self):
return self._read_timeout
@timeout.setter
def timeout(self, value):
self._logger.debug("Setting read timeout to {}s".format(value))
self._read_timeout = value
@property
def write_timeout(self):
return self._write_timeout
@write_timeout.setter
def write_timeout(self, value):
self._logger.debug("Setting write timeout to {}s".format(value))
self._write_timeout = value
def _clearQueue(self, queue): def _clearQueue(self, queue):
try: try:
while queue.get(block=False): while queue.get(block=False):

View file

@ -81,6 +81,7 @@ default_settings = {
"detection": 0.5, "detection": 0.5,
"connection": 10, "connection": 10,
"communication": 30, "communication": 30,
"heatup": 2,
"temperature": 5, "temperature": 5,
"sdStatus": 1 "sdStatus": 1
}, },

View file

@ -956,7 +956,10 @@ class MachineCom(object):
if line is None: if line is None:
break break
if line.strip() is not "": if line.strip() is not "":
self._timeout = get_new_timeout("communication", self._timeout_intervals) if self._heating:
self._timeout = get_new_timeout("heatup", self._timeout_intervals)
else:
self._timeout = get_new_timeout("communication", self._timeout_intervals)
##~~ debugging output handling ##~~ debugging output handling
if line.startswith("//"): if line.startswith("//"):
@ -1059,8 +1062,7 @@ class MachineCom(object):
elif ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:') or ((' B:' in line or line.startswith('B:')) and not 'A:' in line): elif ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:') or ((' B:' in line or line.startswith('B:')) and not 'A:' in line):
if not disable_external_heatup_detection and 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._logger.debug("Externally triggered heatup detected")
self._heating = True self._track_heatup()
self._heatupWaitStartTime = time.time()
self._processTemperatures(line) self._processTemperatures(line)
self._callback.on_comm_temperature_update(self._temp, self._bedTemp) self._callback.on_comm_temperature_update(self._temp, self._bedTemp)
@ -1259,10 +1261,7 @@ class MachineCom(object):
self._currentTool = self._formerTool self._currentTool = self._formerTool
self._formerTool = None self._formerTool = None
if self._heatupWaitStartTime: self._finish_heatup()
self._heatupWaitTimeLost = self._heatupWaitTimeLost + (time.time() - self._heatupWaitStartTime)
self._heatupWaitStartTime = None
self._heating = False
if not self._state in (self.STATE_PRINTING, self.STATE_OPERATIONAL, self.STATE_PAUSED): if not self._state in (self.STATE_PRINTING, self.STATE_OPERATIONAL, self.STATE_PAUSED):
return return
@ -1291,6 +1290,10 @@ class MachineCom(object):
self._resendSameCommand() self._resendSameCommand()
self._clear_to_send.set() self._clear_to_send.set()
elif self._heating:
self._logger.debug("Timeout while in an active heatup, considering heatup to be over then")
self._finish_heatup()
else: else:
self._log("Communication timeout while printing, trying to trigger response from printer. " + general_message) self._log("Communication timeout while printing, trying to trigger response from printer. " + general_message)
self._sendCommand("M105", cmd_type="temperature") self._sendCommand("M105", cmd_type="temperature")
@ -1298,6 +1301,18 @@ class MachineCom(object):
return return
def _track_heatup(self):
self._heating = True
self._heatupWaitStartTime = time.time()
self._serial.timeout = settings().getFloat(["serial", "timeout", "heatup"])
def _finish_heatup(self):
if self._heatupWaitStartTime:
self._heatupWaitTimeLost = self._heatupWaitTimeLost + (time.time() - self._heatupWaitStartTime)
self._heatupWaitStartTime = None
self._heating = False
self._serial.timeout = settings().getFloat(["serial", "timeout", "communication"])
def _continue_sending(self): def _continue_sending(self):
if self._state == self.STATE_PRINTING: if self._state == self.STATE_PRINTING:
if not self._sendFromQueue() and not self.isSdPrinting(): if not self._sendFromQueue() and not self.isSdPrinting():
@ -2036,15 +2051,13 @@ class MachineCom(object):
pass pass
def _gcode_M109_sent(self, cmd, cmd_type=None): def _gcode_M109_sent(self, cmd, cmd_type=None):
self._heatupWaitStartTime = time.time()
self._long_running_command = True self._long_running_command = True
self._heating = True self._track_heatup()
self._gcode_M104_sent(cmd, cmd_type, wait=True) self._gcode_M104_sent(cmd, cmd_type, wait=True)
def _gcode_M190_sent(self, cmd, cmd_type=None): def _gcode_M190_sent(self, cmd, cmd_type=None):
self._heatupWaitStartTime = time.time()
self._long_running_command = True self._long_running_command = True
self._heating = True self._track_heatup()
self._gcode_M140_sent(cmd, cmd_type, wait=True) self._gcode_M140_sent(cmd, cmd_type, wait=True)
def _gcode_M110_sending(self, cmd, cmd_type=None): def _gcode_M110_sending(self, cmd, cmd_type=None):