def auto_cmd(self): """ Sends auto commands using a thread if they are too long. """ logger.info("Sending auto command.") self.print("Sending auto command.", "info") axis = self.auto_cmd_axis.currentText() n = self.auto_cmd_number.value() step = self.auto_cmd_step.value() if self.auto_cmd_type.currentIndex() == 1: it = [gcode_maker.step(axis, step)] else: axis2 = self.auto_cmd_axis_2.currentText() step2 = self.auto_cmd_step_2.value() # AKA "Do not do this at home kids" : it = ( ( ( gcode_maker.step(axis, step), gcode_maker.step(axis, -step) )[(i % 4) >= 2], gcode_maker.step(axis2, step2) )[i % 2] for i in range(4*n-1) ) self.run_thread(it, n)
def reset_config(self): """ Resets the configuration. """ self.drive_x.setCurrentIndex(0) self.drive_y.setCurrentIndex(0) self.drive_z.setCurrentIndex(0) self.ratio_x.setValue(1) self.ratio_y.setValue(1) self.ratio_z.setValue(1) self.play_x.setValue(0) self.play_y.setValue(0) self.play_z.setValue(0) self.reverse_x.setChecked(False) self.reverse_y.setChecked(False) self.reverse_z.setChecked(False) self.minTime_x.setValue(5) self.minTime_y.setValue(5) self.minTime_z.setValue(5) logger.info("Reset config.")
def sending_end(self): """ Manages the end of upload. If some commands are waiting, run them at the end. """ self.send_thread.read_allowed.disconnect() self.serial_manager.send_confirm.disconnect() if self.send_thread and self.send_thread.user_stop: self.print("Stopped by user.", "error") logger.error("Upload stopped by user.") elif self.send_thread and self.send_thread.error: self.print("Error while sending.", "error") logger.error("Error while sending.") else: self.print("Done.", "info") logger.info("Upload done.") self.sending_progress.setValue(0) self.btn_send_current_file.setText( _translate("MainWindow", "Send current file")) self.btn_send_current_file.clicked.disconnect() self.btn_send_current_file.clicked.connect(self.send_file) self.tabWidget.setEnabled(True) self.send_thread = None if len(self.waiting_cmd) > 0: self.run_thread(**self.waiting_cmd.pop(0))
def update_config(self, i): """ Updates the configuration widgets. """ nb_config = self.config_list.count() if i == nb_config-1: self.reset_config() else: file = self.config_list.currentText() + ".json" file = os.path.join(settings.CONFIG_DIR, file) logger.info("Loading config {}".format(file)) config = {} with open(file) as f: config = json.load(f) self.drive_x.setCurrentIndex(config.get("x_drive", 0)) self.drive_y.setCurrentIndex(config.get("y_drive", 0)) self.drive_z.setCurrentIndex(config.get("z_drive", 0)) self.ratio_x.setValue(config.get("x_ratio", 1)) self.ratio_y.setValue(config.get("y_ratio", 1)) self.ratio_z.setValue(config.get("z_ratio", 1)) self.play_x.setValue(config.get("x_play", 0)) self.play_y.setValue(config.get("y_play", 0)) self.play_z.setValue(config.get("z_play", 0)) self.reverse_x.setChecked(config.get("x_reverse", False)) self.reverse_y.setChecked(config.get("y_reverse", False)) self.reverse_z.setChecked(config.get("z_reverse", False)) self.minTime_x.setValue(config.get("x_min_time", 5)) self.minTime_y.setValue(config.get("y_min_time", 5)) self.minTime_z.setValue(config.get("z_min_time", 5))
def sendMsg(self, msg): """ Sends a message using the serial port if fake_mode is False. :param msg: The message to be sent. :returns: True if no error occurred, else False. """ if not self.fake_mode and not (self.serial and self.serial.isOpen()): self.send_print.emit("Error, no serial port to write.", "error") logger.error("Serial manager has no serial opened to send data.") return False elif self.fake_mode: self.send_print.emit(msg, "operator") logger.info( "Sending {} through fake serial port".format(repr(msg))) self.something_sent = True return True else: logger.info("Sending {} through {}".format(repr(msg), self.serial)) self.send_print.emit(msg, "operator") if msg[-1] != '\n': msg += '\n' try: self.serial.write(bytes(msg, encoding='utf8')) except serial.serialutil.SerialException as e: logger.error("Serial error : {}".format(e)) self.send_print.emit("Serial error while writing.", "error") except OSError as e: logger.error("Serial error : {}".format(e)) self.send_print.emit("Serial error while writing.", "error") self.serial_fatal_error.emit() return True
def open(self, baudrate, serial_port, timeout): """ Opens the serial port with the given parameters. :param baudrate: The baudrate. :param serial_port: The port to be used. :param timeout: Timeout for reading and writing. """ logger.info("Opening {} with baudrate {}, timeout {}".format( repr(serial_port), baudrate, timeout)) self.send_print.emit("Opening {} with baudrate {}, timeout {}".format( repr(serial_port), baudrate, timeout), "info") self.serial.port = serial_port self.serial.baudrate = baudrate self.serial.timeout = timeout self.serial.write_timeout = timeout try: self.serial.open() self.is_open = True except serial.serialutil.SerialException: self.is_open = False logger.error("Could not open serial port.") self.send_print.emit("Could not open serial port.", "error") return False logger.debug(self.serial.timeout) return True
def readMsg(self): """ Reads a line from the serial port. And emit the send_print or send_confirm signals if necessary. """ if self.fake_mode: if self.something_sent: logger.info("Received {}".format(repr("ok"))) self.send_print.emit("ok", "machine") self.something_sent = False self.send_confirm.emit(True) return elif not (self.serial and self.serial.isOpen()): self.send_print.emit("Error, no serial port to read.", "error") logger.error("Serial manager has no serial opened to read data.") self.send_confirm.emit(False) return elif not self.serial.in_waiting: return txt = "" try: txt = self.serial.readline().decode('ascii') except serial.serialutil.SerialException as e: logger.error("Serial error : {}".format(e)) self.send_print.emit("Serial error while reading.", "error") except UnicodeDecodeError as e: logger.error("Serial error : {}".format(e)) self.send_print.emit("Serial error while reading.", "error") if txt: if "error" in txt.lower(): self.send_print.emit(txt, "error") else: self.send_print.emit("m> {}".format(txt), "machine") self.send_confirm.emit("ok" in txt.lower())
def close(self): """ Closes the serial port. """ logger.info("Closing serial port.") self.send_print.emit("Closing serial port.", "info") self.is_open = False self.serial.close()
def send_file(self): """ Send a file using a different thread. """ logger.info("Sending file.") self.print("Sending file.", "info") gcode = self.code_edit.toPlainText().split('\n') self.run_thread(gcode)
def send_cmd(self): """ Sends an user command using a thread. """ gcode = [self.command_edit.text()] logger.info("Sending command.") self.print("Sending command.", "info") self.run_thread(gcode)
def send_config(self): """ Send a configuration to the machine. """ self.save_config() gcode = gcode_maker.config_as_gcode( **self.config_as_dict()).split('\n') logger.info("Sending configuration.") self.print("Sending configuration.", "info") self.run_thread(gcode)
def save_file(self): """ Saves a gcode file. """ if not self.file_loaded: self.save_file_as() else: file = self.filename.text() logger.info("Saving {}".format(repr(file))) with open(file, 'w') as f: f.write(self.code_edit.toPlainText())
def list_serials(self): """ Lists available serials ports. """ logger.debug("Listing available serial ports.") l = serial_ports() for i in range(self.serial_ports_list.count()): self.serial_ports_list.removeItem(0) for i in l: logger.info("Found {}".format(i)) self.serial_ports_list.addItem(i)
def run_custom_cmd(self): """ Sends a custom command using a thread. """ logger.info("Sending custom command.") self.print("Sending custom command.", "info") gcode = self.custom_cmd.toPlainText().split('\n') n = self.custom_cmd_number.value() l = len(gcode) it = (gcode[i % l] for i in range(n*l)) self.run_thread(it, n*l)
def load_file(self): """ Loads a gcode file. """ file = self.filename.text() try: logger.info("Loading {}".format(repr(file))) with open(file) as f: gcode = f.read() self.draw_file(gcode) self.code_edit.setText(gcode) self.file_loaded = True except FileNotFoundError: self.choose_file()
def save_config_as(self): """ Saves a configuration in a new file. """ f = QFileDialog.getSaveFileName( self, _translate("MainWindow", "Select file"), directory=settings.CONFIG_DIR, filter='JSON files (*.json)\nAll files (*)')[0] if f is not '': if not f.endswith(".json"): f = f + ".json" logger.info("Saving configuration as {}".format(f)) self.save_config(f) self.list_configs() self.update_config(self.config_list.currentIndex())
def run_thread(self, gcode, n=None, disable=True, allow_waiting=True): """ Run a thread to send the given gcode. :param gcode: The gcode as a list of commands. :param n: A length for the sending_process progress bar. :param disable: Disable ui elements which trigger sending. :param allow_waiting: Adds the command to the waiting queue. :type gcode: list :type n: int :type disable: bool :type allow_waiting: bool """ if self.send_thread and allow_waiting: logger.info("Thread already in use, waiting for the end.") self.waiting_cmd.append( {"gcode": gcode, "n": n, "disable": disable}) return elif self.send_thread: self.send_thread.stop() try: self.serial_manager.serial.flush() except : pass self.send_thread = SendThread(self.serial_manager, gcode) if n: self.sending_progress.setMaximum(n) else: self.sending_progress.setMaximum(len(gcode)) self.sending_progress.setValue(0) self.btn_send_current_file.setText( _translate("MainWindow", "Cancel sending")) self.btn_send_current_file.clicked.disconnect() self.btn_send_current_file.clicked.connect(self.send_thread.stop) if disable: self.tabWidget.setEnabled(False) self.send_thread.read_allowed.connect( self.read_thread.set_read_allowed) self.serial_manager.send_confirm.connect(self.send_thread.confirm) self.send_thread.finished.connect(self.sending_end) self.send_thread.update_progress.connect(self.update_progress) self.send_thread.start()
def save_file_as(self): """ Saves a gcode file in a nex file. """ if not self.file_loaded: directory = settings.FILE_DIR else: directory = os.path.dirname(self.filename.text()) file = QFileDialog.getSaveFileName( self, _translate("MainWindow", "Select file"), directory=directory, filter='GCode files (*.gcode, *.ngc)\nAll files (*)')[0] if file is not '': logger.info("Saving {}".format(repr(file))) self.filename.setText(file) with open(file, 'w') as f: f.write(self.code_edit.toPlainText()) self.file_loaded = True
def save_config(self, filename=None): """ Saves a configuration. :param filename: The name of the file. :type filename: str """ logger.info("Saving configuration.") logger.debug("Filename given : {}".format(filename)) current_config = self.config_list.currentIndex() nb_config = self.config_list.count() if current_config == nb_config-1 and not filename: self.save_config_as() else: if not filename: file = self.config_list.currentText() + ".json" file = os.path.join(settings.CONFIG_DIR, file) else: file = filename config = self.config_as_dict() with open(file, "w") as f: json.dump(config, f)