Fix handling of "missing line number" errors
We so far assumed that a resend request would follow that. Alas, it won't and we'll simply get stuck due to a missing ack from the printer. So let's simulate that here to keep things flowing. Fixes #2226
This commit is contained in:
parent
59ca2188d9
commit
c7e248b142
1 changed files with 41 additions and 19 deletions
|
|
@ -1243,7 +1243,7 @@ class MachineCom(object):
|
|||
return stripped_line, stripped_line.lower()
|
||||
|
||||
##~~ Error handling
|
||||
line = self._handleErrors(line)
|
||||
line = self._handle_errors(line)
|
||||
line, lower_line = convert_line(line)
|
||||
|
||||
##~~ SD file list
|
||||
|
|
@ -1950,36 +1950,53 @@ class MachineCom(object):
|
|||
|
||||
return False
|
||||
|
||||
def _handleErrors(self, line):
|
||||
_resend_request_communication_errors = ("line number",
|
||||
"wrong checksum",
|
||||
"missing checksum",
|
||||
"format error",
|
||||
"expected line")
|
||||
_recoverable_communication_errors = ("no line number with checksum",)
|
||||
_sd_card_errors = ("volume.init",
|
||||
"openroot",
|
||||
"workdir",
|
||||
"error writing to file",
|
||||
"cannot open",
|
||||
"cannot enter")
|
||||
def _handle_errors(self, line):
|
||||
if line is None:
|
||||
return
|
||||
|
||||
lower_line = line.lower()
|
||||
|
||||
# No matter the state, if we see an error, goto the error state and store the error for reference.
|
||||
if lower_line.startswith('error:') or line.startswith('!!'):
|
||||
#Oh YEAH, consistency.
|
||||
# Marlin reports an MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
||||
# But a bed temp error is reported as "Error: Temperature heated bed switched off. MAXTEMP triggered !!"
|
||||
# So we can have an extra newline in the most common case. Awesome work people.
|
||||
if regex_minMaxError.match(line):
|
||||
# special delivery for firmware that goes "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
||||
line = line.rstrip() + self._readline()
|
||||
|
||||
if 'line number' in lower_line or 'checksum' in lower_line or 'format error' in lower_line or 'expected line' in lower_line:
|
||||
#Skip the communication errors, as those get corrected.
|
||||
if any(map(lambda x: x in lower_line, self._recoverable_communication_errors)):
|
||||
# manually trigger an ack for comm errors the printer doesn't send a resend request for but
|
||||
# from which we can recover from by just pushing on (because that then WILL trigger a fitting
|
||||
# resend request)
|
||||
self._handle_ok()
|
||||
|
||||
elif any(map(lambda x: x in lower_line, self._resend_request_communication_errors)):
|
||||
# skip comm errors that the printer sends a resend request for anyhow
|
||||
self._lastCommError = line[6:] if lower_line.startswith("error:") else line[2:]
|
||||
|
||||
elif any(map(lambda x: x in lower_line, self._sd_card_errors)):
|
||||
# skip errors with the SD card
|
||||
pass
|
||||
elif 'volume.init' in lower_line or "openroot" in lower_line or 'workdir' in lower_line\
|
||||
or "error writing to file" in lower_line or "cannot open" in lower_line\
|
||||
or "cannot enter" in lower_line:
|
||||
#Also skip errors with the SD card
|
||||
pass
|
||||
|
||||
elif 'unknown command' in lower_line:
|
||||
#Ignore unknown command errors, it could be a typo or some missing feature
|
||||
# ignore unknown command errors, it could be a typo or some missing feature
|
||||
pass
|
||||
|
||||
elif not self.isError():
|
||||
# handle everything else
|
||||
error_text = line[6:] if lower_line.startswith("error:") else line[2:]
|
||||
self._to_logfile_with_terminal("Received an error from the printer's firmware: {}".format(error_text), level=logging.WARN)
|
||||
self._to_logfile_with_terminal("Received an error from the printer's firmware: {}".format(error_text),
|
||||
level=logging.WARN)
|
||||
|
||||
if not self._ignore_errors:
|
||||
if self._disconnect_on_errors:
|
||||
self._errorValue = error_text
|
||||
|
|
@ -1991,6 +2008,8 @@ class MachineCom(object):
|
|||
else:
|
||||
self._log("WARNING! Received an error from the printer's firmware, ignoring that as configured but you might want to investigate what happened here! Error: {}".format(error_text))
|
||||
self._clear_to_send.set()
|
||||
|
||||
# finally return the line
|
||||
return line
|
||||
|
||||
def _readline(self):
|
||||
|
|
@ -2077,7 +2096,8 @@ class MachineCom(object):
|
|||
# an active (prior) resend request.
|
||||
#
|
||||
# We will ignore this resend request and just continue normally.
|
||||
self._logger.debug("Ignoring resend request for line %d == current line, we haven't sent that yet so the printer got N-1 twice from us, probably due to a timeout" % lineToResend)
|
||||
self._logger.info("Ignoring resend request for line %d == current line, we haven't sent that yet so "
|
||||
"the printer got N-1 twice from us, probably due to a timeout" % lineToResend)
|
||||
return False
|
||||
|
||||
lastCommError = self._lastCommError
|
||||
|
|
@ -2089,7 +2109,8 @@ class MachineCom(object):
|
|||
and ("line number" in lastCommError.lower() or "expected line" in lastCommError.lower()) \
|
||||
and lineToResend == self._lastResendNumber \
|
||||
and self._resendDelta is not None and self._currentResendCount < self._resendDelta:
|
||||
self._logger.debug("Ignoring resend request for line %d, that still originates from lines we sent before we got the first resend request" % lineToResend)
|
||||
self._logger.info("Ignoring resend request for line %d, that still originates from lines we sent "
|
||||
"before we got the first resend request" % lineToResend)
|
||||
self._currentResendCount += 1
|
||||
return True
|
||||
|
||||
|
|
@ -2097,7 +2118,8 @@ class MachineCom(object):
|
|||
# need to do this now. If the same line number has been requested we
|
||||
# already saw and resent, we'll ignore it up to <counter> times.
|
||||
if self._resendSwallowRepetitions and lineToResend == self._lastResendNumber and self._resendSwallowRepetitionsCounter > 0:
|
||||
self._logger.debug("Ignoring resend request for line %d, that is probably a repetition sent by the firmware to ensure it arrives, not a real request" % lineToResend)
|
||||
self._logger.info("Ignoring resend request for line %d, that is probably a repetition sent by the "
|
||||
"firmware to ensure it arrives, not a real request" % lineToResend)
|
||||
self._resendSwallowRepetitionsCounter -= 1
|
||||
return True
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue