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
Пример #4
0
    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
Пример #5
0
    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()
Пример #7
0
    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.')