gcode: Support reading from gcode input before mcu is ready
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
6ebb1a68cb
commit
dbdf1e137e
|
@ -16,8 +16,9 @@ class GCodeParser:
|
||||||
# Input handling
|
# Input handling
|
||||||
self.reactor = printer.reactor
|
self.reactor = printer.reactor
|
||||||
self.fd_handle = None
|
self.fd_handle = None
|
||||||
|
if not is_fileinput:
|
||||||
|
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
||||||
self.input_commands = [""]
|
self.input_commands = [""]
|
||||||
self.need_register_fd = False
|
|
||||||
self.bytes_read = 0
|
self.bytes_read = 0
|
||||||
self.input_log = collections.deque([], 50)
|
self.input_log = collections.deque([], 50)
|
||||||
# Busy handling
|
# Busy handling
|
||||||
|
@ -25,7 +26,7 @@ class GCodeParser:
|
||||||
self.busy_state = None
|
self.busy_state = None
|
||||||
# Command handling
|
# Command handling
|
||||||
self.gcode_handlers = {}
|
self.gcode_handlers = {}
|
||||||
self.is_shutdown = False
|
self.is_printer_ready = False
|
||||||
self.need_ack = False
|
self.need_ack = False
|
||||||
self.toolhead = self.heater_nozzle = self.heater_bed = self.fan = None
|
self.toolhead = self.heater_nozzle = self.heater_bed = self.fan = None
|
||||||
self.speed = 1.0
|
self.speed = 1.0
|
||||||
|
@ -34,6 +35,7 @@ class GCodeParser:
|
||||||
self.last_position = [0.0, 0.0, 0.0, 0.0]
|
self.last_position = [0.0, 0.0, 0.0, 0.0]
|
||||||
self.homing_add = [0.0, 0.0, 0.0, 0.0]
|
self.homing_add = [0.0, 0.0, 0.0, 0.0]
|
||||||
self.axis2pos = {'X': 0, 'Y': 1, 'Z': 2, 'E': 3}
|
self.axis2pos = {'X': 0, 'Y': 1, 'Z': 2, 'E': 3}
|
||||||
|
self.build_handlers()
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
self.toolhead = self.printer.objects['toolhead']
|
self.toolhead = self.printer.objects['toolhead']
|
||||||
self.heater_nozzle = None
|
self.heater_nozzle = None
|
||||||
|
@ -42,35 +44,40 @@ class GCodeParser:
|
||||||
self.heater_nozzle = extruder.heater
|
self.heater_nozzle = extruder.heater
|
||||||
self.heater_bed = self.printer.objects.get('heater_bed')
|
self.heater_bed = self.printer.objects.get('heater_bed')
|
||||||
self.fan = self.printer.objects.get('fan')
|
self.fan = self.printer.objects.get('fan')
|
||||||
self.build_handlers()
|
|
||||||
def build_handlers(self):
|
def build_handlers(self):
|
||||||
shutdown_handlers = ['M105', 'M110', 'M114']
|
shutdown_handlers = ['M105', 'M110', 'M114']
|
||||||
handlers = ['G0', 'G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
handlers = ['G0', 'G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
||||||
'M18', 'M82', 'M83', 'M84', 'M110', 'M114', 'M119', 'M206']
|
'M18', 'M82', 'M83', 'M84',
|
||||||
|
'M105', 'M110', 'M114', 'M119', 'M206']
|
||||||
if self.heater_nozzle is not None:
|
if self.heater_nozzle is not None:
|
||||||
handlers.extend(['M104', 'M105', 'M109', 'M303'])
|
handlers.extend(['M104', 'M109', 'M303'])
|
||||||
if self.heater_bed is not None:
|
if self.heater_bed is not None:
|
||||||
handlers.extend(['M140', 'M190'])
|
handlers.extend(['M140', 'M190'])
|
||||||
if self.fan is not None:
|
if self.fan is not None:
|
||||||
handlers.extend(['M106', 'M107'])
|
handlers.extend(['M106', 'M107'])
|
||||||
if self.is_shutdown:
|
if not self.is_printer_ready:
|
||||||
handlers = [h for h in handlers if h in shutdown_handlers]
|
handlers = [h for h in handlers if h in shutdown_handlers]
|
||||||
self.gcode_handlers = dict((h, getattr(self, 'cmd_'+h))
|
self.gcode_handlers = dict((h, getattr(self, 'cmd_'+h))
|
||||||
for h in handlers)
|
for h in handlers)
|
||||||
def run(self):
|
|
||||||
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
self.reactor.end()
|
self.reactor.end()
|
||||||
self.toolhead.motor_off()
|
self.toolhead.motor_off()
|
||||||
logging.debug('Completed translation by klippy')
|
logging.debug('Completed translation by klippy')
|
||||||
def stats(self, eventtime):
|
def stats(self, eventtime):
|
||||||
return "gcodein=%d" % (self.bytes_read,)
|
return "gcodein=%d" % (self.bytes_read,)
|
||||||
def shutdown(self):
|
def set_printer_ready(self, is_ready):
|
||||||
self.is_shutdown = True
|
if self.is_printer_ready == is_ready:
|
||||||
|
return
|
||||||
|
self.is_printer_ready = is_ready
|
||||||
self.build_handlers()
|
self.build_handlers()
|
||||||
logging.info("Dumping gcode input %d blocks" % (len(self.input_log),))
|
if is_ready and self.is_fileinput and self.fd_handle is None:
|
||||||
for eventtime, data in self.input_log:
|
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
||||||
logging.info("Read %f: %s" % (eventtime, repr(data)))
|
if not is_ready:
|
||||||
|
logging.info("Dumping gcode input %d blocks" % (
|
||||||
|
len(self.input_log),))
|
||||||
|
# XXX - read from self.input_log is not thread safe
|
||||||
|
for eventtime, data in self.input_log:
|
||||||
|
logging.info("Read %f: %s" % (eventtime, repr(data)))
|
||||||
# Parse input into commands
|
# Parse input into commands
|
||||||
args_r = re.compile('([a-zA-Z*])')
|
args_r = re.compile('([a-zA-Z*])')
|
||||||
def process_commands(self, eventtime):
|
def process_commands(self, eventtime):
|
||||||
|
@ -106,7 +113,7 @@ class GCodeParser:
|
||||||
# Check if machine can process next command or must stall input
|
# Check if machine can process next command or must stall input
|
||||||
if self.busy_state is not None:
|
if self.busy_state is not None:
|
||||||
break
|
break
|
||||||
if self.toolhead.check_busy(eventtime):
|
if self.is_printer_ready and self.toolhead.check_busy(eventtime):
|
||||||
self.set_busy(self.toolhead)
|
self.set_busy(self.toolhead)
|
||||||
break
|
break
|
||||||
self.ack()
|
self.ack()
|
||||||
|
@ -114,7 +121,7 @@ class GCodeParser:
|
||||||
def process_data(self, eventtime):
|
def process_data(self, eventtime):
|
||||||
if self.busy_state is not None:
|
if self.busy_state is not None:
|
||||||
self.reactor.unregister_fd(self.fd_handle)
|
self.reactor.unregister_fd(self.fd_handle)
|
||||||
self.need_register_fd = True
|
self.fd_handle = None
|
||||||
return
|
return
|
||||||
data = os.read(self.fd, 4096)
|
data = os.read(self.fd, 4096)
|
||||||
self.input_log.append((eventtime, data))
|
self.input_log.append((eventtime, data))
|
||||||
|
@ -162,12 +169,13 @@ class GCodeParser:
|
||||||
self.process_commands(eventtime)
|
self.process_commands(eventtime)
|
||||||
if self.busy_state is not None:
|
if self.busy_state is not None:
|
||||||
return self.reactor.NOW
|
return self.reactor.NOW
|
||||||
if self.need_register_fd:
|
if self.fd_handle is None:
|
||||||
self.need_register_fd = False
|
|
||||||
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
||||||
return self.reactor.NEVER
|
return self.reactor.NEVER
|
||||||
# Temperature wrappers
|
# Temperature wrappers
|
||||||
def get_temp(self):
|
def get_temp(self):
|
||||||
|
if not self.is_printer_ready:
|
||||||
|
return "T:0"
|
||||||
# T:XXX /YYY B:XXX /YYY
|
# T:XXX /YYY B:XXX /YYY
|
||||||
out = []
|
out = []
|
||||||
if self.heater_nozzle:
|
if self.heater_nozzle:
|
||||||
|
@ -199,8 +207,8 @@ class GCodeParser:
|
||||||
self.bg_temp(heater)
|
self.bg_temp(heater)
|
||||||
# Individual command handlers
|
# Individual command handlers
|
||||||
def cmd_default(self, params):
|
def cmd_default(self, params):
|
||||||
if self.is_shutdown:
|
if not self.is_printer_ready:
|
||||||
self.respond('Error: Machine is shutdown')
|
self.respond('Error: Printer is not ready')
|
||||||
return
|
return
|
||||||
cmd = params.get('#command')
|
cmd = params.get('#command')
|
||||||
if not cmd:
|
if not cmd:
|
||||||
|
@ -300,6 +308,9 @@ class GCodeParser:
|
||||||
pass
|
pass
|
||||||
def cmd_M114(self, params):
|
def cmd_M114(self, params):
|
||||||
# Get Current Position
|
# Get Current Position
|
||||||
|
if self.toolhead is None:
|
||||||
|
self.cmd_default(params)
|
||||||
|
return
|
||||||
kinpos = self.toolhead.get_position()
|
kinpos = self.toolhead.get_position()
|
||||||
self.respond("X:%.3f Y:%.3f Z:%.3f E:%.3f Count X:%.3f Y:%.3f Z:%.3f" % (
|
self.respond("X:%.3f Y:%.3f Z:%.3f E:%.3f Count X:%.3f Y:%.3f Z:%.3f" % (
|
||||||
self.last_position[0], self.last_position[1],
|
self.last_position[0], self.last_position[1],
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Printer:
|
||||||
self.mcu.connect_file(self.debugoutput, self.dictionary)
|
self.mcu.connect_file(self.debugoutput, self.dictionary)
|
||||||
self.mcu.connect()
|
self.mcu.connect()
|
||||||
self.build_config()
|
self.build_config()
|
||||||
self.gcode.run()
|
self.gcode.set_printer_ready(True)
|
||||||
self.reactor.unregister_timer(self.connect_timer)
|
self.reactor.unregister_timer(self.connect_timer)
|
||||||
return self.reactor.NEVER
|
return self.reactor.NEVER
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -90,8 +90,8 @@ class Printer:
|
||||||
self.stats(time.time())
|
self.stats(time.time())
|
||||||
self.mcu.disconnect()
|
self.mcu.disconnect()
|
||||||
self.stats(time.time())
|
self.stats(time.time())
|
||||||
def shutdown(self):
|
def note_shutdown(self):
|
||||||
self.gcode.shutdown()
|
self.gcode.set_printer_ready(False)
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
@ -336,7 +336,7 @@ class MCU:
|
||||||
self.is_shutdown = True
|
self.is_shutdown = True
|
||||||
logging.info("%s: %s" % (params['#name'], params['#msg']))
|
logging.info("%s: %s" % (params['#name'], params['#msg']))
|
||||||
self.serial.dump_debug()
|
self.serial.dump_debug()
|
||||||
self._printer.shutdown()
|
self._printer.note_shutdown()
|
||||||
# Connection phase
|
# Connection phase
|
||||||
def connect(self):
|
def connect(self):
|
||||||
if not self._is_fileoutput:
|
if not self._is_fileoutput:
|
||||||
|
|
Loading…
Reference in New Issue