def set_ready(self):
        """Initializes the gantries to their current positions."""
        def set_ready_callback():
            for dvc in self.devices:
                dvc.is_homed = True

        if self._is_machine_busy:
            print_error_msg(self.console,
                            'Cannot set or go to ready. The machine is busy.')
            return

        init_code = ActionType.G1 if self.is_machine_homed else ActionType.G92
        cmds = self._get_initialization_commands(init_code)

        if cmds:
            self._mainqueue = []
            self._mainqueue.extend(cmds)
            self._mainqueue.extend(self._disengage_motors_commands)
            self._work_type = WorkType.SET_READY

            self._keep_working = True
            self._clear_to_send = True
            self._working_thread = threading.Thread(
                target=self._worker,
                name='working thread',
                kwargs={"extra_callback": set_ready_callback})
            self._working_thread.start()
    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 _unlock_machine(self):
        print_debug_msg(self.console, '**** Unlocking machine ****',
                        self._is_dev_env)
        cmds = []

        if self._is_machine_busy:
            print_error_msg(self.console,
                            'Cannot unlock. The machine is busy.')
            return False

        for dvc in self.devices:
            if dvc.serial_response:
                flags = dvc.serial_response.system_status_flags

                if flags and len(flags) == 8 and int(flags[0]):
                    cmd = Action(ActionType.M511, dvc.device_id)
                    cmds.append(cmd)

        if cmds:
            self._keep_working = True
            self._clear_to_send = True
            self._mainqueue = []
            self._mainqueue.append(cmds)
            self._send_next()
            self._keep_working = False
            return True

        return False
Ejemplo n.º 4
0
    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 select_serial_port(self, name: str) -> bool:
        """Sets the active serial port to the provided one."""
        selected = self._serial.select_port(name)
        if not selected:
            print_error_msg(self.console, 'Unable to select serial port.')

        return selected
    def select_device(self, index: int) -> None:
        """Select device given index in devices list."""
        if index < 0:
            self._selected_device = -1
            dispatcher.send('core_d_deselected')

        elif index < len(self._devices):
            self._selected_device = index
            self.select_point(-1)
            dispatcher.send('core_o_deselected')
            dispatcher.send('core_d_selected', device=self._devices[index])

        else:
            print_error_msg(self.console, f'invalid device index {index}.')
Ejemplo n.º 7
0
    def resume_work(self) -> bool:
        """Resume the current run."""

        if not self._is_machine_paused:
            print_error_msg(self.console,
                            'Cannot resume; machine is not paused.')
            return False

        self._is_machine_paused = False
        self._keep_working = True
        self._clear_to_send = True
        self._working_thread = threading.Thread(target=self._worker,
                                                name='working thread',
                                                kwargs={"resume": True})
        self._working_thread.start()
        return True
Ejemplo n.º 8
0
    def select_object(self, id_: int) -> None:
        """Select proxy object given id."""
        if id_ < 0:
            self._deselect_object()
            dispatcher.send('core_o_deselected')

        elif id_ in (x.object_id for x in self._objectvis.objects):
            self.core.select_point(-1)
            self.core.select_device(-1)
            for obj in self._objectvis.objects:
                obj.selected = obj.object_id == id_
            dispatcher.send('core_o_selected', object=self.core.objects[id_])
            self._dirty = True

        else:
            print_error_msg(self.core.console,
                            f'invalid proxy object id {id_}.')
    def _query_machine(self):
        print_debug_msg(self.console, '**** Querying machine ****',
                        self._is_dev_env)
        cmds = []

        if self._is_machine_busy:
            print_error_msg(self.console, 'Cannot query. The machine is busy.')
            return

        for dvc in self.devices:
            cmds.append(Action(ActionType.G0, dvc.device_id))

        if cmds:
            self._keep_working = True
            self._clear_to_send = True
            self._mainqueue = []
            self._mainqueue.append(cmds)
            self._send_next()
            self._keep_working = False
Ejemplo n.º 10
0
    def jog(self, action: Action):
        """Jogs the machine according to the provided action."""
        if self._is_machine_busy:
            print_error_msg(self.console, 'Cannot jog. The machine is busy.')
            return

        header = self._get_move_commands(False, action.device)
        body = [action]
        footer = self._get_move_commands(True, action.device)

        self._mainqueue = []
        self._mainqueue.extend(header)
        self._mainqueue.append(body)
        self._mainqueue.extend(footer)
        self._work_type = WorkType.JOGGING

        self._keep_working = True
        self._clear_to_send = True
        self._working_thread = threading.Thread(target=self._worker,
                                                name='working thread')
        self._working_thread.start()
Ejemplo n.º 11
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
Ejemplo n.º 12
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
Ejemplo n.º 13
0
    def start_imaging(self) -> bool:
        """Starts the imaging sequence, following the define action path."""
        if not self.is_serial_port_connected:
            print_error_msg(
                self.console,
                'The machine needs to be connected before imaging can start.')
            return False

        if self._is_machine_busy:
            print_error_msg(self.console, 'The machine is busy.')
            return False

        if not self.is_machine_idle:
            print_error_msg(
                self.console,
                'The machine needs to be homed before imaging can start.')
            return False

        device_ids = list(set(a.device for a in self._actions))
        # 1 move command * 1 shutter command.
        batch_size = 2
        if self.config.machine_settings.machine.is_parallel_execution:
            batch_size = batch_size * len(device_ids)

        header = self._get_move_commands(
            True, *[dvc.device_id for dvc in self.devices])
        body = self._chunk_actions(batch_size)
        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.IMAGING

        self._keep_working = True
        self._clear_to_send = True
        self._working_thread = threading.Thread(target=self._worker,
                                                name='working thread')
        self._working_thread.start()
        return True