mirror of
				https://github.com/Klipper3d/klipper.git
				synced 2025-10-31 10:25:57 +01:00 
			
		
		
		
	gcode: Support reading from gcode input before mcu is ready
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
		| @@ -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,33 +44,38 @@ 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: | ||||||
|  |             self.fd_handle = self.reactor.register_fd(self.fd, self.process_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: |             for eventtime, data in self.input_log: | ||||||
|                 logging.info("Read %f: %s" % (eventtime, repr(data))) |                 logging.info("Read %f: %s" % (eventtime, repr(data))) | ||||||
|     # Parse input into commands |     # Parse input into commands | ||||||
| @@ -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: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user