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
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)
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)