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 _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
Exemple #3
0
    def _send(self, *commands):
        """Send command to machine."""

        if not self.is_serial_port_connected:
            return

        dvcs = []
        cmds = []
        for command in commands:
            if not any(d.device_id == command.device for d in dvcs):
                dvcs.append(self._get_device(command.device))

            cmds.append(serialize_command(command))

        cmd_lines = '\r'.join(cmds)

        if self._serial.is_port_open:

            print_debug_msg(
                self.console, 'Writing> [{0}] to device{1} '.format(
                    cmd_lines.replace("\r", "\\r"),
                    "s" if len(dvcs) > 1 else "") +
                f'{", ".join([str(d.device_id) for d in dvcs])}.',
                self._is_dev_env)

            for dvc in dvcs:
                dvc.set_is_writing()

            self._serial.write(cmd_lines)
Exemple #4
0
    def _send_next(self):
        if not self.is_serial_port_connected:
            return

        # Wait until we get the ok from listener.
        while self.is_serial_port_connected and not self._clear_to_send \
            and self._keep_working:
            time.sleep(self._YIELD_TIMEOUT)

        if self._keep_working and len(self._mainqueue) > 0:
            packet = self._mainqueue.pop(0)

            # dvc_360s = self._get_imminent_360s(packet)
            # for dvc_360 in dvc_360s:
            #     did = dvc_360[0]
            #     print_debug_msg(self.console, f'**** DEVICE: {did} IS ABOUT TO TURN!!! ****',
            #         self._is_dev_env)
            #     pts = self._back_off(dvc_360)

            #     for i, pt in enumerate(pts):
            #         args = create_action_args(list(pt))
            #         jog = Action(ActionType.G1, did, len(args), args)
            #         packet.insert(i, jog)

            print_debug_msg(self.console, f'Packet size is: {len(packet)}',
                            self._is_dev_env)

            self._send(*packet)
            self._clear_to_send = False

        else:
            self._keep_working = False
            self._clear_to_send = True
    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
    def on_tool_selected(self, event: wx.CommandEvent) -> None:
        """On toolbar tool selected, check which and process accordingly.

        TODO: Link with copiscore when implemented.
        """
        if event.Id == ToolIds.PLAY.value:
            # if self.core.paused:
            #     self.core.resume_work()
            # else:
            #     self.core.start_imaging()

            is_connected = self._core.is_serial_port_connected
            has_path = len(self._core.actions)
            is_homed = self._core.is_machine_homed
            can_image = is_connected and has_path and is_homed

            if not can_image:
                msg = 'The machine needs to be homed before imaging.'
                if not is_connected:
                    msg = 'The machine needs to be connected for imaging.'
                elif not has_path:
                    msg = 'The machine needs a path for imaging.'

                set_dialog(msg)
                return

            self._core.start_imaging()

        elif event.Id == ToolIds.PAUSE.value:
            self._core.pause_work()

        elif event.Id == ToolIds.STOP.value:
            self._core.stop_work()

        elif event.Id == ToolIds.SETTINGS.value:
            with MachineSettingsDialog(self) as dlg:
                print_debug_msg(self._core.console, 'Machine Settings opened.', self._core.is_dev_env)

        elif event.Id == ToolIds.EXPORT.value:
            self._core.export_actions('actions.txt')
    def _listener(self) -> None:
        """Implements a listening thread."""
        read_thread = \
            next(filter(lambda t: t.thread == threading.current_thread(), self._read_threads))

        continue_listening = lambda t = read_thread: not t.stop

        machine_queried = False

        print_debug_msg(self.console,
            f'{read_thread.thread.name.capitalize()} started.', self._is_dev_env)

        while continue_listening():
            time.sleep(self._YIELD_TIMEOUT)
            #if not self._edsdk.is_waiting_for_image:
            resp = self._serial.read(read_thread.port)
            controllers_unlocked = False

            if resp:
                if isinstance(resp, SerialResponse):
                    dvc = self._get_device(resp.device_id)

                    if dvc:
                        dvc.set_serial_response(resp)

                if self._keep_working and self._is_machine_locked:

                    print_debug_msg(self.console,
                        '**** Machine error-locked. stoping imaging!! ****', self._is_dev_env)

                    self.stop_work()
                else:
                    self._clear_to_send = controllers_unlocked or self.is_machine_idle

                if self.is_machine_idle:
                    print_debug_msg(self.console, '**** Machine is idle ****', self._is_dev_env)

                    if len(self._mainqueue) <= 0:
                        dispatcher.send('notify_machine_idle')

            if self._is_new_connection:
                if self._has_machine_reported:
                    if self._is_machine_locked and not controllers_unlocked:
                        controllers_unlocked = self._unlock_machine()
                        self._clear_to_send = controllers_unlocked or self.is_machine_idle

                        if controllers_unlocked:
                            self._connected_on = None
                            self._is_new_connection = False
                            machine_queried = False
                    else:
                        # if this connection happened after the devices last reported, query them.
                        if not machine_queried and \
                            self._connected_on >= self._machine_last_reported_on:
                            print_debug_msg(self.console,
                            f'Machine status stale (last: {self._machine_status}).',
                            self._is_dev_env)

                            self._query_machine()
                            machine_queried = True
                        elif self.is_machine_idle:
                            self._connected_on = None
                            self._is_new_connection = False
                            machine_queried = False
                else:
                    no_report_span = (datetime.now() - self._connected_on).total_seconds()

                    if not self._machine_last_reported_on or \
                        self._connected_on >= self._machine_last_reported_on:
                        print_debug_msg(self.console,
                            'Machine status stale (last: {0}) for {1} seconds.'
                                .format(self._machine_status, round(no_report_span, 2)),
                            self._is_dev_env)

                    # If no device has reported for 1 second since connecting, query the devices.
                    if not machine_queried and no_report_span > 1:
                        self._query_machine()
                        machine_queried = True

        print_debug_msg(self.console,
            f'{read_thread.thread.name.capitalize()} stopped.', self._is_dev_env)