def disconnect(self): """disconnects from the active serial port.""" self._keep_working = False if self.is_serial_port_connected: port_name = self._get_active_serial_port_name() read_thread = next( filter(lambda t: t.port == port_name, self._read_threads)) if read_thread: read_thread.stop = True if threading.current_thread() != read_thread.thread: read_thread.thread.join() self._read_threads.remove(read_thread) if self._working_thread: self._working_thread.join() self._working_thread = None if self.is_serial_port_connected: self._serial.close_port() time.sleep(self._YIELD_TIMEOUT * 5) self._is_new_connection = False self._connected_on = None print_info_msg(self.console, f'Disconnected from device {port_name}.')
def _worker(self, resuming=False, extra_callback=None) -> None: """Implements a worker thread.""" t_name = self.work_type_name state = "resumed" if resuming else "started" print_debug_msg(self.console, f'{t_name} thread {state}', self._is_dev_env) def callback(): if extra_callback: extra_callback() print_info_msg(self.console, f'{t_name} ended.') dispatcher.connect(callback, signal='notify_machine_idle') print_info_msg(self.console, f'{t_name} started.') had_error = False try: while self._keep_working and self.is_serial_port_connected: self._send_next() except AttributeError as err: print_error_msg(self.console, f'{t_name} thread stopped unexpectedly: {err.args[0]}') had_error = True finally: self._working_thread = None self._keep_working = False if not self._is_machine_paused: self._work_type = None if not had_error: print_debug_msg(self.console, f'{t_name} thread stopped.', self._is_dev_env)
def connect(self, baud: int = serial_controller.BAUDS[-1]) -> bool: """Connects to the active serial port.""" if not self._is_serial_enabled: print_error_msg(self.console, 'Serial is not enabled') else: connected = self._serial.open_port(baud) if connected: self._connected_on = datetime.now() port_name = next( filter(lambda p: p.is_connected and p.is_active, self.serial_port_list)).name print_info_msg(self.console, f'Connected to device {port_name}.') read_thread = threading.Thread(target=self._listener, name=f'read thread {port_name}') self._read_threads.append( ReadThread(thread=read_thread, port=port_name)) read_thread.start() else: print_error_msg(self.console, 'Unable to connect to device.') self._is_new_connection = connected return connected
def stop_work(self) -> None: """Stops work in progress.""" if self.pause_work(): self._mainqueue = [] self._is_machine_paused = False self._clear_to_send = True print_info_msg(self.console, f'{self.work_type_name} stopped.') self._work_type = None
def start_homing(self) -> bool: """Start the homing sequence, following the steps in the configuration.""" def homing_callback(): for dvc in self.devices: dvc.is_homed = True if not self.is_serial_port_connected: print_error_msg( self.console, 'The machine needs to be connected before homing can start.') return False if self._is_machine_busy: print_error_msg(self.console, 'The machine is busy.') return False homing_actions = self.config.machine_settings.machine.homing_actions.copy( ) if not homing_actions or len(homing_actions) == 0: print_error_msg(self.console, 'No homing sequence to provided.') return False # Only send homing commands for connected devices. all_device_ids = [d.device_id for d in self.devices] homing_actions = list( filter(lambda c: c.device in all_device_ids, homing_actions)) device_ids = list(set(a.device for a in homing_actions)) batch_size = len(device_ids) header = self._get_move_commands(True, *device_ids) body = self._chunk_actions(batch_size, homing_actions) footer = self._get_initialization_commands(ActionType.G1) footer.extend(self._disengage_motors_commands) self._mainqueue = [] self._mainqueue.extend(header) self._mainqueue.extend(body) self._mainqueue.extend(footer) self._work_type = WorkType.HOMING self._keep_working = True self._clear_to_send = True self._working_thread = threading.Thread( target=self._worker, name='working thread', kwargs={"extra_callback": homing_callback}) self._working_thread.start() print_info_msg(self.console, 'Homing started.') return True
def on_refresh_ports(self, event: wx.CommandEvent) -> None: """On refresh button pressed, update port list.""" refresh_btn = self.FindControl(event.Id) refresh_btn.Disable() self.port_cb.Selection = -1 self.baud_cb.Selection = -1 self.baud_cb.Items = [] self.connect_btn.Label = 'Connect' self._core.update_serial_ports() print_info_msg(self._core.console, 'Serial ports refreshed.') self.update_ports() self.port_cb.Popup() refresh_btn.Enable()
def pause_work(self) -> bool: """Pause work in progress, saving the current position.""" if not self._working_thread: print_error_msg(self.console, 'Cannot pause. The machine is not busy.') return False self._is_machine_paused = True self._keep_working = False # try joining the print thread: enclose it in try/except because we # might be calling it from the thread itself try: self._working_thread.join() self._working_thread = None print_info_msg(self.console, f'{self.work_type_name} paused.') return True except RuntimeError as err: print_error_msg(self.console, f'Cannot join working thread: {err.args[0]}') return False
def callback(): if extra_callback: extra_callback() print_info_msg(self.console, f'{t_name} ended.')