aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/gcode.py
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-02-02 09:38:04 -0500
committerKevin O'Connor <kevin@koconnor.net>2018-02-02 11:00:46 -0500
commit56bfb3280a756ff4f71de258e37f6e230d4292d2 (patch)
tree7ae32746af926dbb4e86171cc79a7ffee095dd89 /klippy/gcode.py
parent3ddbd34a7c4b9cbe1676625162d4638cfad0b408 (diff)
downloadkutter-56bfb3280a756ff4f71de258e37f6e230d4292d2.tar.gz
kutter-56bfb3280a756ff4f71de258e37f6e230d4292d2.tar.xz
kutter-56bfb3280a756ff4f71de258e37f6e230d4292d2.zip
gcode: Keep reading input to check for M112 (emergency stop)
OctoPrint (and other software) will sometimes send additional commands even if the previous command has not yet responded with an "ok". Change the g-code input reading code to keep reading input so that an M112 can be detected (and processed out-of-order). To avoid the extreme case where one writes an entire g-code file to the input without any pacing, disable the input reading if more than 20 commands are pending. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/gcode.py')
-rw-r--r--klippy/gcode.py37
1 files changed, 26 insertions, 11 deletions
diff --git a/klippy/gcode.py b/klippy/gcode.py
index 5a7c50f2..38ff348a 100644
--- a/klippy/gcode.py
+++ b/klippy/gcode.py
@@ -24,6 +24,7 @@ class GCodeParser:
if not self.is_fileinput:
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
self.partial_input = ""
+ self.pending_commands = []
self.bytes_read = 0
self.input_log = collections.deque([], 50)
# Command handling
@@ -172,31 +173,45 @@ class GCodeParser:
raise
self.ack()
self.need_ack = prev_need_ack
+ m112_r = re.compile('^(?:[nN][0-9]+)?\s*[mM]112(?:\s|$)')
def process_data(self, eventtime):
+ # Read input, separate by newline, and add to pending_commands
data = os.read(self.fd, 4096)
self.input_log.append((eventtime, data))
self.bytes_read += len(data)
lines = data.split('\n')
lines[0] = self.partial_input + lines[0]
self.partial_input = lines.pop()
+ pending_commands = self.pending_commands
+ pending_commands.extend(lines)
+ # Check for M112 out-of-order
+ if ((len(pending_commands) > 1 or self.is_processing_data)
+ and len(pending_commands) < 20):
+ for line in lines:
+ if self.m112_r.match(line) is not None:
+ self.cmd_M112({})
+ # Check if already processing data
if self.is_processing_data:
- if not self.is_fileinput and not lines:
- return
- self.reactor.unregister_fd(self.fd_handle)
- self.fd_handle = None
- if not self.is_fileinput and lines[0].strip().upper() == 'M112':
- self.cmd_M112({})
- while self.is_processing_data:
- eventtime = self.reactor.pause(eventtime + 0.100)
- self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
+ if len(pending_commands) >= 20 or not data:
+ # Stop reading input
+ self.reactor.unregister_fd(self.fd_handle)
+ self.fd_handle = None
+ return
+ # Process commands
self.is_processing_data = True
- self.process_commands(lines)
+ while pending_commands:
+ self.pending_commands = []
+ self.process_commands(pending_commands)
+ pending_commands = self.pending_commands
+ self.is_processing_data = False
+ # Reenable input reading if it was stopped
+ if self.fd_handle is None:
+ self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
if not data and self.is_fileinput:
self.motor_heater_off()
if self.toolhead is not None:
self.toolhead.wait_moves()
self.printer.request_exit()
- self.is_processing_data = False
def run_script(self, script):
self.process_commands(script.split('\n'), need_ack=False)
# Response handling