Fix USBPrinterOutputDevice to work with the Print Monitor

CURA-1036
This commit is contained in:
fieldOfView 2016-07-01 14:32:40 +02:00
parent c9b2a1d938
commit 6800991fa1
2 changed files with 43 additions and 107 deletions

View file

@ -51,13 +51,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
self._update_firmware_thread.daemon = True
self.firmwareUpdateComplete.connect(self._onFirmwareUpdateComplete)
self._heatup_wait_start_time = time.time()
## Queue for commands that need to be send. Used when command is sent when a print is active.
self._command_queue = queue.Queue()
self._is_printing = False
self._is_paused = False
## Set when print is started in order to check running time.
self._print_start_time = None
@ -80,13 +81,15 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
# In order to keep the connection alive we request the temperature every so often from a different extruder.
# This index is the extruder we requested data from the last time.
self._temperature_requested_extruder_index = 0
self._temperature_requested_extruder_index = 0
self._current_z = 0
self._updating_firmware = False
self._firmware_file_name = None
self._control_view = None
self._error_message = None
onError = pyqtSignal()
@ -120,10 +123,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
def _homeBed(self):
self._sendCommand("G28 Z")
@pyqtSlot()
def startPrint(self):
self.writeStarted.emit(self)
gcode_list = getattr( Application.getInstance().getController().getScene(), "gcode_list")
self._updateJobState("printing")
self.printGCode(gcode_list)
def _moveHead(self, x, y, z, speed):
@ -135,6 +138,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
# \param gcode_list List with gcode (strings).
def printGCode(self, gcode_list):
if self._progress or self._connection_state != ConnectionState.connected:
self._error_message = Message(i18n_catalog.i18nc("@info:status", "Printer is busy or not connected. Unable to start a new job."))
self._error_message.show()
Logger.log("d", "Printer is busy or not connected, aborting print")
self.writeError.emit(self)
return
@ -344,23 +349,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._setErrorState("Unexpected error while writing serial port %s " % e)
self.close()
def createControlInterface(self):
if self._control_view is None:
Logger.log("d", "Creating control interface for printer connection")
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "ControlWindow.qml"))
component = QQmlComponent(Application.getInstance()._engine, path)
self._control_context = QQmlContext(Application.getInstance()._engine.rootContext())
self._control_context.setContextProperty("manager", self)
self._control_view = component.create(self._control_context)
## Show control interface.
# This will create the view if its not already created.
def showControlInterface(self):
if self._control_view is None:
self.createControlInterface()
self._control_view.show()
## Send a command to printer.
## Send a command to printer.
# \param cmd string with g-code
def sendCommand(self, cmd):
if self._progress:
@ -371,11 +360,12 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
## Set the error state with a message.
# \param error String with the error message.
def _setErrorState(self, error):
self._updateJobState("error")
self._error_state = error
self.onError.emit()
def requestWrite(self, node, file_name = None, filter_by_machine = False):
self.showControlInterface()
self.startPrint()
def _setEndstopState(self, endstop_key, value):
if endstop_key == b"x_min":
@ -391,14 +381,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self.endstopStateChanged.emit("z_min", value)
self._z_min_endstop_pressed = value
## Listen thread function.
## Listen thread function.
def _listen(self):
Logger.log("i", "Printer connection listen thread started for %s" % self._serial_port)
temperature_request_timeout = time.time()
ok_timeout = time.time()
while self._connection_state == ConnectionState.connected:
line = self._readline()
if line is None:
if line is None:
break # None is only returned when something went wrong. Stop listening
if time.time() > temperature_request_timeout:
@ -423,7 +413,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._setErrorState(line[6:])
elif b" T:" in line or line.startswith(b"T:"): # Temperature message
try:
try:
self._setHotendTemperature(self._temperature_requested_extruder_index, float(re.search(b"T: *([0-9\.]*)", line).group(1)))
except:
pass
@ -445,6 +435,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
ok_timeout = time.time() + 5
if not self._command_queue.empty():
self._sendCommand(self._command_queue.get())
elif self._is_paused:
line = b"" # Force getting temperature as keep alive
else:
self._sendNextGcodeLine()
elif b"resend" in line.lower() or b"rs" in line: # Because a resend can be asked with "resend" and "rs"
@ -454,13 +446,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
if b"rs" in line:
self._gcode_position = int(line.split()[1])
else: # Request the temperature on comm timeout (every 2 seconds) when we are not printing.)
if line == b"":
if self._num_extruders > 0:
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._num_extruders
self.sendCommand("M105 T%d" % self._temperature_requested_extruder_index)
else:
self.sendCommand("M105")
# Request the temperature on comm timeout (every 2 seconds) when we are not printing.)
if line == b"":
if self._num_extruders > 0:
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._num_extruders
self.sendCommand("M105 T%d" % self._temperature_requested_extruder_index)
else:
self.sendCommand("M105")
Logger.log("i", "Printer connection listen thread stopped for %s" % self._serial_port)
## Send next Gcode in the gcode list
@ -487,10 +480,22 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
checksum = functools.reduce(lambda x,y: x^y, map(ord, "N%d%s" % (self._gcode_position, line)))
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
self._gcode_position += 1
self._gcode_position += 1
self.setProgress((self._gcode_position / len(self._gcode)) * 100)
self.progressChanged.emit()
## Set the state of the print.
# Sent from the print monitor
def _setJobState(self, job_state):
if job_state == "pause":
self._is_paused = True
self._updateJobState("paused")
elif job_state == "print":
self._is_paused = False
self._updateJobState("printing")
elif job_state == "abort":
self.cancelPrint()
## Set the progress of the print.
# It will be normalized (based on max_progress) to range 0 - 100
def setProgress(self, progress, max_progress = 100):
@ -498,16 +503,19 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self.progressChanged.emit()
## Cancel the current print. Printer connection wil continue to listen.
@pyqtSlot()
def cancelPrint(self):
self._gcode_position = 0
self.setProgress(0)
self._gcode = []
# Turn of temperatures
# Turn off temperatures, fan and steppers
self._sendCommand("M140 S0")
self._sendCommand("M104 S0")
self._sendCommand("M107")
self._sendCommand("M84")
self._is_printing = False
self._is_paused = False
self._updateJobState("ready")
## Check if the process did not encounter an error yet.
def hasError(self):