def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway( self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService( self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None
def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway(self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService(self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None
class PrintAPI(object): def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway(self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService(self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None @property def configuration(self): return self._configuration def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False): self._current_file_name = file_name self._current_file = open(file_name, 'r') gcode_reader = GCodeReader(self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height) gcode_layer_generator = gcode_reader.get_layers() layer_generator = gcode_layer_generator self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed) def _get_zaxis(self, dry_run): if dry_run: return None elif self._configuration.dripper.dripper_type == 'photo': logger.info("Photo Zaxis") return PhotoZAxis( self._start_height, self._configuration.dripper.photo_zaxis_delay ) elif self._configuration.dripper.dripper_type == 'emulated': logger.info("Emulated Zaxis") return TimedDripZAxis( self._configuration.dripper.drips_per_mm, self._start_height, drips_per_second=self._configuration.dripper.emulated_drips_per_second ) elif self._configuration.dripper.dripper_type == 'microcontroller': logger.info("Micro Controller Zaxis") return SerialDripZAxis( self._get_communicator(dry_run), self._configuration.dripper.drips_per_mm, self._start_height, ) def _get_communicator(self, dry_run): if hasattr(self, '_communicator'): return self._communicator if dry_run: self._communicator = NullCommunicator() else: self._communicator = UsbPacketCommunicator(self._configuration.circut.print_queue_length) self._communicator.start() return self._communicator def _get_digital_disseminator(self, dry_run): return MicroDisseminator( self.laser_control, self._get_communicator(dry_run), self._configuration.circut.data_rate ) def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False): logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers) logger.info("Sublayered: %s" % self._configuration.options.use_sublayers) logger.info("Overlapped: %s" % self._configuration.options.use_overlap) if self._configuration.options.use_sublayers and print_sub_layers: layer_generator = SubLayerGenerator(layer_generator, self._configuration.options.sublayer_height_mm) if self._configuration.options.use_shufflelayers: layer_generator = ShuffleGenerator(layer_generator, self._configuration.options.shuffle_layers_amount) if self._configuration.options.use_overlap: layer_generator = OverLapGenerator(layer_generator, self._configuration.options.overlap_amount) if self._configuration.serial.on: self._commander = SerialCommander(self._configuration.serial.port) else: self._commander = NullCommander() self.laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount) transformer = HomogenousTransformer( self._configuration.calibration.max_deflection, self._configuration.calibration.height, self._configuration.calibration.lower_points, self._configuration.calibration.upper_points, ) state = MachineState() self._status = MachineStatus() if dry_run: abort_on_error = False else: abort_on_error = True self._zaxis = self._get_zaxis(dry_run) disseminator = self._get_digital_disseminator(dry_run) path_to_points = PathToPoints( disseminator.samples_per_second, transformer, self._configuration.options.laser_thickness_mm ) if force_source_speed: override_draw_speed = None override_move_speed = None else: override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0 post_fire_delay_speed = None slew_delay_speed = None if self._configuration.options.post_fire_delay: post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0) if self._configuration.options.slew_delay: slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0) if self._configuration.options.wait_after_move_milliseconds > 0: wait_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.wait_after_move_milliseconds) / 1000.0) else: wait_speed = None self._writer = LayerWriter( disseminator, path_to_points, self.laser_control, state, move_distance_to_ignore=self._configuration.options.laser_thickness_mm, override_draw_speed=override_draw_speed, override_move_speed=override_move_speed, wait_speed=wait_speed, post_fire_delay_speed=post_fire_delay_speed, slew_delay_speed=slew_delay_speed ) self._layer_processing = LayerProcessing( self._writer, state, self._status, self._zaxis, self._configuration.dripper.max_lead_distance_mm, self._commander, pre_layer_delay, self._configuration.serial.layer_started, self._configuration.serial.layer_ended, self._configuration.serial.print_ended, self._configuration.serial.on_command, self._configuration.serial.off_command, ) if self._zaxis: self._zaxis.set_call_back(self._status.drip_call_back) self._zaxis.start() self._controller = Controller( self._writer, self._layer_processing, layer_generator, self._status, abort_on_error=abort_on_error, ) self._controller.start() def get_status(self): return self._controller.get_status() def can_set_drips_per_second(self): if getattr(self._zaxis, 'set_drips_per_second', False): return True else: return False def set_drips_per_second(self, drips_per_second): if getattr(self._zaxis, 'set_drips_per_second', False): self._zaxis.set_drips_per_second(drips_per_second) else: logger.error('Cannot change drips per second on %s' % type(self._zaxis)) raise Exception('Cannot change drips per second on %s' % type(self._zaxis)) def get_drips_per_second(self): if getattr(self._zaxis, 'get_drips_per_second'): return self._zaxis.get_drips_per_second() else: logger.warning("Drips per second requested but does not exist") return 0.0 def verify_gcode(self, file_name): self.print_gcode(file_name, print_sub_layers=False, dry_run=True) def close(self): if self._zaxis: self._zaxis.close() if self._controller: self._controller.close() else: logger.warning('Stopped before printing') if self._current_file: self._current_file.close() logger.info("File Closed") if self._notification_service: self._notification_service.send_message("Print Complete", "%s is complete" % self._current_file_name)
class PrintAPI(object): def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway( self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService( self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None @property def configuration(self): return self._configuration def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False): self._current_file_name = file_name self._current_file = open(file_name, 'r') gcode_reader = GCodeReader( self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height) gcode_layer_generator = gcode_reader.get_layers() layer_generator = gcode_layer_generator self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed) def _get_zaxis(self, dry_run): if dry_run: return None elif self._configuration.dripper.dripper_type == 'photo': logger.info("Photo Zaxis") return PhotoZAxis(self._start_height, self._configuration.dripper.photo_zaxis_delay) elif self._configuration.dripper.dripper_type == 'emulated': logger.info("Emulated Zaxis") return TimedDripZAxis(self._configuration.dripper.drips_per_mm, self._start_height, drips_per_second=self._configuration.dripper. emulated_drips_per_second) elif self._configuration.dripper.dripper_type == 'microcontroller': logger.info("Micro Controller Zaxis") return SerialDripZAxis( self._get_communicator(dry_run), self._configuration.dripper.drips_per_mm, self._start_height, ) def _get_communicator(self, dry_run): if hasattr(self, '_communicator'): return self._communicator if dry_run: self._communicator = NullCommunicator() else: self._communicator = UsbPacketCommunicator( self._configuration.circut.print_queue_length) self._communicator.start() return self._communicator def _get_digital_disseminator(self, dry_run): return MicroDisseminator(self.laser_control, self._get_communicator(dry_run), self._configuration.circut.data_rate) def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False): logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers) logger.info("Sublayered: %s" % self._configuration.options.use_sublayers) logger.info("Overlapped: %s" % self._configuration.options.use_overlap) if self._configuration.options.use_sublayers and print_sub_layers: layer_generator = SubLayerGenerator( layer_generator, self._configuration.options.sublayer_height_mm) if self._configuration.options.use_shufflelayers: layer_generator = ShuffleGenerator( layer_generator, self._configuration.options.shuffle_layers_amount) if self._configuration.options.use_overlap: layer_generator = OverLapGenerator( layer_generator, self._configuration.options.overlap_amount) if self._configuration.serial.on: self._commander = SerialCommander(self._configuration.serial.port) else: self._commander = NullCommander() self.laser_control = LaserControl( self._configuration.cure_rate.override_laser_power_amount) transformer = HomogenousTransformer( self._configuration.calibration.max_deflection, self._configuration.calibration.height, self._configuration.calibration.lower_points, self._configuration.calibration.upper_points, ) state = MachineState() self._status = MachineStatus() if dry_run: abort_on_error = False else: abort_on_error = True self._zaxis = self._get_zaxis(dry_run) disseminator = self._get_digital_disseminator(dry_run) path_to_points = PathToPoints( disseminator.samples_per_second, transformer, self._configuration.options.laser_thickness_mm) if force_source_speed: override_draw_speed = None override_move_speed = None else: override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0 post_fire_delay_speed = None slew_delay_speed = None if self._configuration.options.post_fire_delay: post_fire_delay_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.post_fire_delay) / 1000.0) if self._configuration.options.slew_delay: slew_delay_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.slew_delay) / 1000.0) if self._configuration.options.wait_after_move_milliseconds > 0: wait_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.wait_after_move_milliseconds) / 1000.0) else: wait_speed = None self._writer = LayerWriter(disseminator, path_to_points, self.laser_control, state, move_distance_to_ignore=self._configuration. options.laser_thickness_mm, override_draw_speed=override_draw_speed, override_move_speed=override_move_speed, wait_speed=wait_speed, post_fire_delay_speed=post_fire_delay_speed, slew_delay_speed=slew_delay_speed) self._layer_processing = LayerProcessing( self._writer, state, self._status, self._zaxis, self._configuration.dripper.max_lead_distance_mm, self._commander, pre_layer_delay, self._configuration.serial.layer_started, self._configuration.serial.layer_ended, self._configuration.serial.print_ended, self._configuration.serial.on_command, self._configuration.serial.off_command, ) if self._zaxis: self._zaxis.set_call_back(self._status.drip_call_back) self._zaxis.start() self._controller = Controller( self._writer, self._layer_processing, layer_generator, self._status, abort_on_error=abort_on_error, ) self._controller.start() def get_status(self): return self._controller.get_status() def can_set_drips_per_second(self): if getattr(self._zaxis, 'set_drips_per_second', False): return True else: return False def set_drips_per_second(self, drips_per_second): if getattr(self._zaxis, 'set_drips_per_second', False): self._zaxis.set_drips_per_second(drips_per_second) else: logger.error('Cannot change drips per second on %s' % type(self._zaxis)) raise Exception('Cannot change drips per second on %s' % type(self._zaxis)) def get_drips_per_second(self): if getattr(self._zaxis, 'get_drips_per_second'): return self._zaxis.get_drips_per_second() else: logger.warning("Drips per second requested but does not exist") return 0.0 def verify_gcode(self, file_name): self.print_gcode(file_name, print_sub_layers=False, dry_run=True) def close(self): if self._zaxis: self._zaxis.close() if self._controller: self._controller.close() else: logger.warning('Stopped before printing') if self._current_file: self._current_file.close() logger.info("File Closed") if self._notification_service: self._notification_service.send_message( "Print Complete", "%s is complete" % self._current_file_name)
class PrintAPI(object): '''API designed to use configuration to print a thing takes a configuration object Simple Usage: print_api = PrintAPI(configuration_api.get_current_config()) print_api.print_gcode("file.gcode") while print_api.get_status()['status'] != "Complete" time.sleep(1) print_api.close() ''' def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway( self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService( self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None @property def configuration(self): '''Returns the current configuration''' return self._configuration def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False): '''Take a gcode file and starts the printing it with current settings.''' self._current_file_name = file_name self._current_file = open(file_name, 'r') gcode_reader = GCodeReader( self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height) gcode_layer_generator = gcode_reader.get_layers() layer_generator = gcode_layer_generator self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed) def subscribe_to_status(self, callback): '''Allows a subscription to printer safety status messages''' if hasattr(self, '_communicator'): self._communicator.register_handler(PrinterStatusMessage, callback) else: logger.warning("Printer not running subscription not complete") def _get_zaxis(self, dry_run): if dry_run: return None elif self._configuration.dripper.dripper_type == 'photo': logger.info("Photo Zaxis") return PhotoZAxis(self._start_height, self._configuration.dripper.photo_zaxis_delay) elif self._configuration.dripper.dripper_type == 'emulated': logger.info("Emulated Zaxis") return TimedDripZAxis(self._configuration.dripper.drips_per_mm, self._start_height, drips_per_second=self._configuration.dripper. emulated_drips_per_second) elif self._configuration.dripper.dripper_type == 'microcontroller': logger.info("Micro Controller Zaxis") return SerialDripZAxis( self._get_communicator(dry_run), self._configuration.dripper.drips_per_mm, self._start_height, ) def _get_communicator(self, dry_run): if hasattr(self, '_communicator'): return self._communicator if dry_run: self._communicator = NullCommunicator() else: self._communicator = UsbPacketCommunicator( self._configuration.circut.print_queue_length) self._communicator.start() return self._communicator def _get_digital_disseminator(self, dry_run): return MicroDisseminator(self.laser_control, self._get_communicator(dry_run), self._configuration.circut.data_rate) def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False): '''Takes a layer_generator object and starts the printing it with current settings.''' logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers) logger.info("Sublayered: %s" % self._configuration.options.use_sublayers) logger.info("Overlapped: %s" % self._configuration.options.use_overlap) if self._configuration.options.use_sublayers and print_sub_layers: layer_generator = SubLayerGenerator( layer_generator, self._configuration.options.sublayer_height_mm) if self._configuration.options.use_shufflelayers: layer_generator = ShuffleGenerator( layer_generator, self._configuration.options.shuffle_layers_amount) if self._configuration.options.use_overlap: layer_generator = OverLapGenerator( layer_generator, self._configuration.options.overlap_amount) if self._configuration.serial.on: self._commander = SerialCommander(self._configuration.serial.port) else: self._commander = NullCommander() self.laser_control = LaserControl( self._configuration.cure_rate.override_laser_power_amount) transformer = HomogenousTransformer( self._configuration.calibration.max_deflection, self._configuration.calibration.height, self._configuration.calibration.lower_points, self._configuration.calibration.upper_points, ) state = MachineState() self._status = MachineStatus() if dry_run: abort_on_error = False else: abort_on_error = True self._zaxis = self._get_zaxis(dry_run) disseminator = self._get_digital_disseminator(dry_run) path_to_points = PathToPoints( disseminator.samples_per_second, transformer, self._configuration.options.laser_thickness_mm) if force_source_speed: override_draw_speed = None override_move_speed = None else: override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0 post_fire_delay_speed = None slew_delay_speed = None if self._configuration.options.post_fire_delay: post_fire_delay_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.post_fire_delay) / 1000.0) if self._configuration.options.slew_delay: slew_delay_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.slew_delay) / 1000.0) if self._configuration.options.wait_after_move_milliseconds > 0: wait_speed = self._configuration.options.laser_thickness_mm / ( float(self._configuration.options.wait_after_move_milliseconds) / 1000.0) else: wait_speed = None self._writer = LayerWriter(disseminator, path_to_points, self.laser_control, state, move_distance_to_ignore=self._configuration. options.laser_thickness_mm, override_draw_speed=override_draw_speed, override_move_speed=override_move_speed, wait_speed=wait_speed, post_fire_delay_speed=post_fire_delay_speed, slew_delay_speed=slew_delay_speed) self._layer_processing = LayerProcessing( self._writer, state, self._status, zaxis=self._zaxis, max_lead_distance=self._configuration.dripper.max_lead_distance_mm, commander=self._commander, pre_layer_delay=pre_layer_delay, layer_start_command=self._configuration.serial.layer_started, layer_ended_command=self._configuration.serial.layer_ended, print_start_command=self._configuration.serial.print_start, print_ended_command=self._configuration.serial.print_ended, dripper_on_command=self._configuration.serial.on_command, dripper_off_command=self._configuration.serial.off_command, ) if self._zaxis: self._zaxis.set_call_back(self._status.drip_call_back) self._zaxis.start() self._controller = Controller( self._writer, self._layer_processing, layer_generator, self._status, abort_on_error=abort_on_error, ) self._controller.start() def get_status(self): '''Returns a status dictionary of the print containing: start_time elapsed_time current_layer status -> ['Complete', 'Cancelled', 'Failed', 'Starting', 'Running'] errors waiting_for_drips height drips drips_per_second model_height skipped_layers drip_histor ''' return self._controller.get_status() def can_set_drips_per_second(self): '''When using an emulated dripper this returns if the use can cahnge the drip rate manually via software''' if getattr(self._zaxis, 'set_drips_per_second', False): return True else: return False def set_drips_per_second(self, drips_per_second): '''Allows a user to set the number of drips per second in realtime whilst using the emulated dripper''' if getattr(self._zaxis, 'set_drips_per_second', False): self._zaxis.set_drips_per_second(drips_per_second) else: logger.error('Cannot change drips per second on %s' % type(self._zaxis)) raise Exception('Cannot change drips per second on %s' % type(self._zaxis)) def get_drips_per_second(self): '''Gets the current setting for drips per second when using the emulated dripper''' if getattr(self._zaxis, 'get_drips_per_second'): return self._zaxis.get_drips_per_second() else: logger.warning("Drips per second requested but does not exist") return 0.0 def verify_gcode(self, file_name): '''Runs a test of the gcode without printing to verify file intregrity ununsed at this time''' self.print_gcode(file_name, print_sub_layers=False, dry_run=True) def close(self): '''Close the api required before running a second print or shutting down''' if self._zaxis: self._zaxis.close() if self._controller: self._controller.close() else: logger.warning('Stopped before printing') if self._current_file: self._current_file.close() logger.info("File Closed") if self._notification_service: self._notification_service.send_message( "Print Complete", "%s is complete" % self._current_file_name)
class PrintAPI(object): '''API designed to use configuration to print a thing takes a configuration object Simple Usage: print_api = PrintAPI(configuration_api.get_current_config()) print_api.print_gcode("file.gcode") while print_api.get_status()['status'] != "Complete" time.sleep(1) print_api.close() ''' def __init__(self, configuration, start_height=0.0): logger.info('Print API Startup') self._configuration = configuration logger.info('Printer Name: %s' % self._configuration.name) self._controller = None self._zaxis = None self._start_height = start_height self._current_file_name = None self._current_file = None if self._configuration.email.on: self._email_gateway = EmailGateway(self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password) self._notification_service = EmailNotificationService(self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient) else: self._notification_service = None @property def configuration(self): '''Returns the current configuration''' return self._configuration def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False): '''Take a gcode file and starts the printing it with current settings.''' self._current_file_name = file_name self._current_file = open(file_name, 'r') gcode_reader = GCodeReader(self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height) gcode_layer_generator = gcode_reader.get_layers() layer_generator = gcode_layer_generator self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed) def subscribe_to_status(self, callback): '''Allows a subscription to printer safety status messages''' if hasattr(self, '_communicator'): self._communicator.register_handler(PrinterStatusMessage, callback) else: logger.warning("Printer not running subscription not complete") def _get_zaxis(self, dry_run): if dry_run: return None elif self._configuration.dripper.dripper_type == 'photo': logger.info("Photo Zaxis") return PhotoZAxis( self._start_height, self._configuration.dripper.photo_zaxis_delay ) elif self._configuration.dripper.dripper_type == 'emulated': logger.info("Emulated Zaxis") return TimedDripZAxis( self._configuration.dripper.drips_per_mm, self._start_height, drips_per_second=self._configuration.dripper.emulated_drips_per_second ) elif self._configuration.dripper.dripper_type == 'microcontroller': logger.info("Micro Controller Zaxis") return SerialDripZAxis( self._get_communicator(dry_run), self._configuration.dripper.drips_per_mm, self._start_height, ) def _get_communicator(self, dry_run): if hasattr(self, '_communicator'): return self._communicator if dry_run: self._communicator = NullCommunicator() else: self._communicator = UsbPacketCommunicator(self._configuration.circut.print_queue_length) self._communicator.start() return self._communicator def _get_digital_disseminator(self, dry_run): return MicroDisseminator( self.laser_control, self._get_communicator(dry_run), self._configuration.circut.data_rate ) def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False): '''Takes a layer_generator object and starts the printing it with current settings.''' logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers) logger.info("Sublayered: %s" % self._configuration.options.use_sublayers) logger.info("Overlapped: %s" % self._configuration.options.use_overlap) if self._configuration.options.use_sublayers and print_sub_layers: layer_generator = SubLayerGenerator(layer_generator, self._configuration.options.sublayer_height_mm) if self._configuration.options.use_shufflelayers: layer_generator = ShuffleGenerator(layer_generator, self._configuration.options.shuffle_layers_amount) if self._configuration.options.use_overlap: layer_generator = OverLapGenerator(layer_generator, self._configuration.options.overlap_amount) if self._configuration.serial.on: self._commander = SerialCommander(self._configuration.serial.port) else: self._commander = NullCommander() self.laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount) transformer = HomogenousTransformer( self._configuration.calibration.max_deflection, self._configuration.calibration.height, self._configuration.calibration.lower_points, self._configuration.calibration.upper_points, ) state = MachineState() self._status = MachineStatus() if dry_run: abort_on_error = False else: abort_on_error = True self._zaxis = self._get_zaxis(dry_run) disseminator = self._get_digital_disseminator(dry_run) path_to_points = PathToPoints( disseminator.samples_per_second, transformer, self._configuration.options.laser_thickness_mm ) if force_source_speed: override_draw_speed = None override_move_speed = None else: override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0 post_fire_delay_speed = None slew_delay_speed = None if self._configuration.options.post_fire_delay: post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0) if self._configuration.options.slew_delay: slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0) if self._configuration.options.wait_after_move_milliseconds > 0: wait_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.wait_after_move_milliseconds) / 1000.0) else: wait_speed = None self._writer = LayerWriter( disseminator, path_to_points, self.laser_control, state, move_distance_to_ignore=self._configuration.options.laser_thickness_mm, override_draw_speed=override_draw_speed, override_move_speed=override_move_speed, wait_speed=wait_speed, post_fire_delay_speed=post_fire_delay_speed, slew_delay_speed=slew_delay_speed ) self._layer_processing = LayerProcessing( self._writer, state, self._status, zaxis=self._zaxis, max_lead_distance=self._configuration.dripper.max_lead_distance_mm, commander=self._commander, pre_layer_delay=pre_layer_delay, layer_start_command=self._configuration.serial.layer_started, layer_ended_command=self._configuration.serial.layer_ended, print_start_command=self._configuration.serial.print_start, print_ended_command=self._configuration.serial.print_ended, dripper_on_command=self._configuration.serial.on_command, dripper_off_command=self._configuration.serial.off_command, ) if self._zaxis: self._zaxis.set_call_back(self._status.drip_call_back) self._zaxis.start() self._controller = Controller( self._writer, self._layer_processing, layer_generator, self._status, abort_on_error=abort_on_error, ) self._controller.start() def get_status(self): '''Returns a status dictionary of the print containing: start_time elapsed_time current_layer status -> ['Complete', 'Cancelled', 'Failed', 'Starting', 'Running'] errors waiting_for_drips height drips drips_per_second model_height skipped_layers drip_histor ''' return self._controller.get_status() def can_set_drips_per_second(self): '''When using an emulated dripper this returns if the use can cahnge the drip rate manually via software''' if getattr(self._zaxis, 'set_drips_per_second', False): return True else: return False def set_drips_per_second(self, drips_per_second): '''Allows a user to set the number of drips per second in realtime whilst using the emulated dripper''' if getattr(self._zaxis, 'set_drips_per_second', False): self._zaxis.set_drips_per_second(drips_per_second) else: logger.error('Cannot change drips per second on %s' % type(self._zaxis)) raise Exception('Cannot change drips per second on %s' % type(self._zaxis)) def get_drips_per_second(self): '''Gets the current setting for drips per second when using the emulated dripper''' if getattr(self._zaxis, 'get_drips_per_second'): return self._zaxis.get_drips_per_second() else: logger.warning("Drips per second requested but does not exist") return 0.0 def verify_gcode(self, file_name): '''Runs a test of the gcode without printing to verify file intregrity ununsed at this time''' self.print_gcode(file_name, print_sub_layers=False, dry_run=True) def close(self): '''Close the api required before running a second print or shutting down''' if self._zaxis: self._zaxis.close() if self._controller: self._controller.close() else: logger.warning('Stopped before printing') if self._current_file: self._current_file.close() logger.info("File Closed") if self._notification_service: self._notification_service.send_message("Print Complete", "%s is complete" % self._current_file_name)