Fix: moved line number incrementing to send loop
Should fix issues where too fast a temperature polling could cause skipped line numbers, triggering nasty resend loops in the process.
This commit is contained in:
parent
4c1ba0fd0b
commit
5765180462
1 changed files with 101 additions and 70 deletions
|
|
@ -420,7 +420,7 @@ class MachineCom(object):
|
|||
if self.isPrinting() and not self.isSdFileSelected():
|
||||
self._commandQueue.put((cmd, cmd_type))
|
||||
elif self.isOperational():
|
||||
self._sendCommand((cmd, cmd_type))
|
||||
self._sendCommand(cmd, cmd_type=cmd_type)
|
||||
|
||||
def sendGcodeScript(self, scriptName, replacements=None):
|
||||
context = dict()
|
||||
|
|
@ -520,7 +520,7 @@ class MachineCom(object):
|
|||
self.sendCommand(line)
|
||||
|
||||
# now make sure we actually do something, up until now we only filled up the queue
|
||||
self._sendFromQueue(sendChecksum=True)
|
||||
self._sendFromQueue()
|
||||
except:
|
||||
self._logger.exception("Error while trying to start printing")
|
||||
self._errorValue = get_exception_string()
|
||||
|
|
@ -621,7 +621,7 @@ class MachineCom(object):
|
|||
self.sendCommand(line)
|
||||
|
||||
# now make sure we actually do something, up until now we only filled up the queue
|
||||
self._sendFromQueue(sendChecksum=True)
|
||||
self._sendFromQueue()
|
||||
|
||||
eventManager().fire(Events.PRINT_RESUMED, payload)
|
||||
elif pause and self.isPrinting():
|
||||
|
|
@ -1074,7 +1074,7 @@ class MachineCom(object):
|
|||
self._resendNextCommand()
|
||||
|
||||
else:
|
||||
if self._sendFromQueue(sendChecksum=True):
|
||||
if self._sendFromQueue():
|
||||
pass
|
||||
elif not self.isSdPrinting():
|
||||
self._sendNext()
|
||||
|
|
@ -1164,9 +1164,18 @@ class MachineCom(object):
|
|||
eventManager().fire(Events.CONNECTED, payload)
|
||||
self.sendGcodeScript("afterPrinterConnected", replacements=dict(event=payload))
|
||||
|
||||
def _sendFromQueue(self, sendChecksum=False):
|
||||
def _sendFromQueue(self):
|
||||
if not self._commandQueue.empty() and not self.isStreaming():
|
||||
self._sendCommand(self._commandQueue.get(), sendChecksum)
|
||||
entry = self._commandQueue.get()
|
||||
if isinstance(entry, tuple):
|
||||
if not len(entry) == 2:
|
||||
return False
|
||||
cmd, cmd_type = entry
|
||||
else:
|
||||
cmd = entry
|
||||
cmd_type = None
|
||||
|
||||
self._sendCommand(cmd, cmd_type=cmd_type)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
@ -1325,7 +1334,7 @@ class MachineCom(object):
|
|||
with self._sendNextLock:
|
||||
line = self._getNext()
|
||||
if line is not None:
|
||||
self._sendCommand(line, True)
|
||||
self._sendCommand(line)
|
||||
self._callback.on_comm_progress()
|
||||
|
||||
def _handleResendRequest(self, line):
|
||||
|
|
@ -1385,64 +1394,53 @@ class MachineCom(object):
|
|||
self._lastResendNumber = None
|
||||
self._currentResendCount = 0
|
||||
|
||||
def _sendCommand(self, cmd_tuple, sendChecksum=False):
|
||||
if isinstance(cmd_tuple, tuple):
|
||||
cmd, cmd_type = cmd_tuple
|
||||
else:
|
||||
cmd = cmd_tuple
|
||||
cmd_type = None
|
||||
|
||||
def _sendCommand(self, cmd, cmd_type=None):
|
||||
# Make sure we are only handling one sending job at a time
|
||||
with self._sendingLock:
|
||||
if self._serial is None:
|
||||
return
|
||||
|
||||
if not self.isStreaming():
|
||||
for hook in self._gcode_hooks:
|
||||
hook_cmd = self._gcode_hooks[hook](self, cmd, cmd_type=cmd_type, send_checksum=sendChecksum)
|
||||
for name, hook in self._gcode_hooks.items():
|
||||
hook_cmd = hook(self, cmd, cmd_type=cmd_type)
|
||||
|
||||
if hook_cmd is None:
|
||||
cmd = None
|
||||
|
||||
# hook might have returned (cmd, sendChecksum) or (cmd, sendChecksum, cmd_type), split that
|
||||
if isinstance(hook_cmd, tuple):
|
||||
elif isinstance(hook_cmd, tuple):
|
||||
if len(hook_cmd) == 2:
|
||||
hook_cmd, cmd_type = hook_cmd
|
||||
elif len(hook_cmd) == 3:
|
||||
hook_cmd, cmd_type, sendChecksum = hook_cmd
|
||||
|
||||
# hook might have returned None for cmd, if so stop processing, we won't send this command
|
||||
# to the printer
|
||||
if hook_cmd is None:
|
||||
cmd = None
|
||||
break
|
||||
# legacy hook handler, ignore returned send_checksum
|
||||
hook_cmd, cmd_type, _ = hook_cmd
|
||||
|
||||
# if hook_cmd is a string, we'll replace cmd with it (it's been rewritten by the hook handler
|
||||
elif isinstance(hook_cmd, basestring):
|
||||
if isinstance(hook_cmd, basestring):
|
||||
cmd = hook_cmd
|
||||
|
||||
else:
|
||||
self._logger.warn("Hook {name} returned unintelligible result, ignoring it: {hook_cmd!r}".format(**locals()))
|
||||
continue
|
||||
|
||||
if cmd is None:
|
||||
break
|
||||
|
||||
# try to parse the cmd and extract the gcode type
|
||||
gcode = self._regex_command.search(cmd)
|
||||
if gcode:
|
||||
gcode = gcode.group(1)
|
||||
if cmd is not None:
|
||||
gcode = self._regex_command.search(cmd)
|
||||
if gcode:
|
||||
gcode = gcode.group(1)
|
||||
|
||||
# fire events if necessary
|
||||
if gcode in gcodeToEvent:
|
||||
eventManager().fire(gcodeToEvent[gcode])
|
||||
# fire events if necessary
|
||||
if gcode in gcodeToEvent:
|
||||
eventManager().fire(gcodeToEvent[gcode])
|
||||
|
||||
# send it through the specific handler if it exists
|
||||
gcodeHandler = "_gcode_" + gcode
|
||||
if hasattr(self, gcodeHandler):
|
||||
cmd = getattr(self, gcodeHandler)(cmd)
|
||||
# send it through the specific handler if it exists
|
||||
cmd = self._process_command_phase("queue", cmd, gcode=gcode)
|
||||
|
||||
if cmd is not None:
|
||||
self._doSend(cmd, send_checksum=sendChecksum, cmd_type=cmd_type)
|
||||
|
||||
def _doSend(self, cmd, send_checksum=False, cmd_type=None):
|
||||
if send_checksum or self._alwaysSendChecksum:
|
||||
lineNumber = self._currentLine
|
||||
self._addToLastLines(cmd)
|
||||
self._currentLine += 1
|
||||
self._enqueue_for_sending(cmd, linenumber=lineNumber, command_type=cmd_type)
|
||||
else:
|
||||
self._enqueue_for_sending(cmd, command_type=cmd_type)
|
||||
self._enqueue_for_sending(cmd, command_type=cmd_type)
|
||||
|
||||
def gcode_command_for_cmd(self, cmd):
|
||||
"""
|
||||
|
|
@ -1497,20 +1495,54 @@ class MachineCom(object):
|
|||
if not self._send_queue_active:
|
||||
break
|
||||
|
||||
# fetch command and optional linenumber from queue, send it
|
||||
# fetch command and optional linenumber from queue
|
||||
command, linenumber, _ = entry
|
||||
|
||||
gcode_match = self._regex_command.search(command)
|
||||
is_gcode = gcode_match is not None
|
||||
|
||||
if is_gcode:
|
||||
# trigger "sending" phase
|
||||
command = self._process_command_phase("sending", command, gcode=gcode_match.group(1))
|
||||
|
||||
if linenumber is not None:
|
||||
# line number predetermined, use that
|
||||
self._doSendWithChecksum(command, linenumber)
|
||||
else:
|
||||
self._doSendWithoutChecksum(command)
|
||||
if self.isPrinting() or self._alwaysSendChecksum:
|
||||
linenumber = self._currentLine
|
||||
self._addToLastLines(command)
|
||||
self._currentLine += 1
|
||||
self._doSendWithChecksum(command, linenumber)
|
||||
else:
|
||||
self._doSendWithoutChecksum(command)
|
||||
|
||||
# we just used up one ok, clear it, wait for the next clear
|
||||
if is_gcode:
|
||||
# trigger "sent" phase
|
||||
self._process_command_phase("sent", command, gcode=gcode_match.group(1))
|
||||
|
||||
# wait for the next clear
|
||||
self._clear_to_send.clear()
|
||||
self._clear_to_send.wait()
|
||||
except:
|
||||
self._logger.exception("Caught an exception in the send loop")
|
||||
self._log("Closing down send loop")
|
||||
|
||||
def _process_command_phase(self, phase, command, gcode=None):
|
||||
if gcode is None:
|
||||
gcode_match = self._regex_command.search(command)
|
||||
if gcode_match is None:
|
||||
return command
|
||||
|
||||
gcode = gcode.group(1)
|
||||
|
||||
# send it through the specific handler if it exists
|
||||
gcodeHandler = "_gcode_" + gcode + "_" + phase
|
||||
if hasattr(self, gcodeHandler):
|
||||
command = getattr(self, gcodeHandler)(command)
|
||||
|
||||
return command
|
||||
|
||||
##~~ actual sending via serial
|
||||
|
||||
def _doSendWithChecksum(self, cmd, lineNumber):
|
||||
|
|
@ -1538,13 +1570,13 @@ class MachineCom(object):
|
|||
|
||||
##~~ command handlers
|
||||
|
||||
def _gcode_T(self, cmd):
|
||||
def _gcode_T_sent(self, cmd):
|
||||
toolMatch = self._regex_paramTInt.search(cmd)
|
||||
if toolMatch:
|
||||
self._currentTool = int(toolMatch.group(1))
|
||||
return cmd
|
||||
|
||||
def _gcode_G0(self, cmd):
|
||||
def _gcode_G0_sent(self, cmd):
|
||||
if 'Z' in cmd:
|
||||
match = self._regex_paramZFloat.search(cmd)
|
||||
if match:
|
||||
|
|
@ -1556,14 +1588,14 @@ class MachineCom(object):
|
|||
except ValueError:
|
||||
pass
|
||||
return cmd
|
||||
_gcode_G1 = _gcode_G0
|
||||
_gcode_G0_sent = _gcode_G0_sent
|
||||
|
||||
def _gcode_M0(self, cmd):
|
||||
def _gcode_M0_queue(self, cmd):
|
||||
self.setPause(True)
|
||||
return "M105" # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
||||
_gcode_M1 = _gcode_M0
|
||||
return None # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
||||
_gcode_M1_queued = _gcode_M0_queue
|
||||
|
||||
def _gcode_M104(self, cmd):
|
||||
def _gcode_M104_sent(self, cmd):
|
||||
toolNum = self._currentTool
|
||||
toolMatch = self._regex_paramTInt.search(cmd)
|
||||
if toolMatch:
|
||||
|
|
@ -1581,7 +1613,7 @@ class MachineCom(object):
|
|||
pass
|
||||
return cmd
|
||||
|
||||
def _gcode_M140(self, cmd):
|
||||
def _gcode_M140_sent(self, cmd):
|
||||
match = self._regex_paramSInt.search(cmd)
|
||||
if match:
|
||||
try:
|
||||
|
|
@ -1595,19 +1627,19 @@ class MachineCom(object):
|
|||
pass
|
||||
return cmd
|
||||
|
||||
def _gcode_M109(self, cmd):
|
||||
def _gcode_M109_sent(self, cmd):
|
||||
self._heatupWaitStartTime = time.time()
|
||||
self._blocking_command = True
|
||||
self._heating = True
|
||||
return self._gcode_M104(cmd)
|
||||
return self._gcode_M104_sent(cmd)
|
||||
|
||||
def _gcode_M190(self, cmd):
|
||||
def _gcode_M190_sent(self, cmd):
|
||||
self._heatupWaitStartTime = time.time()
|
||||
self._blocking_command = True
|
||||
self._heating = True
|
||||
return self._gcode_M140(cmd)
|
||||
return self._gcode_M140_sent(cmd)
|
||||
|
||||
def _gcode_M110(self, cmd):
|
||||
def _gcode_M110_sending(self, cmd):
|
||||
newLineNumber = None
|
||||
match = self._regex_paramNInt.search(cmd)
|
||||
if match:
|
||||
|
|
@ -1619,20 +1651,19 @@ class MachineCom(object):
|
|||
newLineNumber = 0
|
||||
|
||||
# send M110 command with new line number
|
||||
self._enqueue_for_sending(cmd, linenumber=newLineNumber)
|
||||
self._currentLine = newLineNumber + 1
|
||||
self._currentLine = newLineNumber
|
||||
|
||||
# after a reset of the line number we have no way to determine what line exactly the printer now wants
|
||||
self._lastLines.clear()
|
||||
self._resendDelta = None
|
||||
|
||||
return None
|
||||
return cmd
|
||||
|
||||
def _gcode_M112(self, cmd): # It's an emergency what todo? Canceling the print should be the minimum
|
||||
def _gcode_M112_queue(self, cmd): # It's an emergency what todo? Canceling the print should be the minimum
|
||||
self.cancelPrint()
|
||||
return cmd
|
||||
|
||||
def _gcode_G4(self, cmd):
|
||||
def _gcode_G4_sent(self, cmd):
|
||||
# we are intending to dwell for a period of time, increase the timeout to match
|
||||
cmd = cmd.upper()
|
||||
p_idx = cmd.find('P')
|
||||
|
|
@ -1648,12 +1679,12 @@ class MachineCom(object):
|
|||
self._blocking_command = True
|
||||
return cmd
|
||||
|
||||
def _gcode_G28(self, cmd):
|
||||
def _gcode_G28_sending(self, cmd):
|
||||
self._blocking_command = True
|
||||
return cmd
|
||||
_gcode_G29 = _gcode_G28
|
||||
_gcode_G30 = _gcode_G28
|
||||
_gcode_G32 = _gcode_G28
|
||||
_gcode_G29_sending = _gcode_G28_sending
|
||||
_gcode_G30_sending = _gcode_G28_sending
|
||||
_gcode_G32_sending = _gcode_G28_sending
|
||||
|
||||
### MachineCom callback ################################################################################################
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue