Changed USB printing to reflect changes in output device API

CURA-1339
This commit is contained in:
Jaime van Kessel 2016-04-13 15:15:37 +02:00
parent 2b9aa1dbb5
commit 0cd1031ec7
2 changed files with 36 additions and 135 deletions

View file

@ -11,25 +11,20 @@ import functools
import os.path
from UM.Application import Application
from UM.Signal import Signal, SignalEmitter
from UM.Logger import Logger
from UM.OutputDevice.OutputDevice import OutputDevice
from UM.PluginRegistry import PluginRegistry
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
from PyQt5.QtQuick import QQuickView
from PyQt5.QtQml import QQmlComponent, QQmlContext
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
from PyQt5.QtCore import QUrl, pyqtSlot, pyqtSignal
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
def __init__(self, serial_port, parent = None):
QObject.__init__(self, parent)
OutputDevice.__init__(self, serial_port)
SignalEmitter.__init__(self)
#super().__init__(serial_port)
class USBPrinterOutputDevice(PrinterOutputDevice):
def __init__(self, serial_port):
super().__init__(serial_port)
self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
self.setShortDescription(catalog.i18nc("@action:button", "Print with USB"))
self.setDescription(catalog.i18nc("@info:tooltip", "Print with USB"))
@ -46,18 +41,10 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
self._end_stop_thread.daemon = True
self._poll_endstop = -1
# Printer is connected
self._is_connected = False
# Printer is in the process of connecting
self._is_connecting = False
# The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable
# response. If the baudrate is correct, this should make sense, else we get giberish.
self._required_responses_auto_baud = 3
self._progress = 0
self._listen_thread = threading.Thread(target=self._listen)
self._listen_thread.daemon = True
@ -119,40 +106,26 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
self._control_view = None
onError = pyqtSignal()
progressChanged = pyqtSignal()
extruderTemperatureChanged = pyqtSignal()
bedTemperatureChanged = pyqtSignal()
firmwareUpdateComplete = pyqtSignal()
endstopStateChanged = pyqtSignal(str ,bool, arguments = ["key","state"])
@pyqtProperty(float, notify = progressChanged)
def progress(self):
return self._progress
def _setTargetBedTemperature(self, temperature):
Logger.log("d", "Setting bed temperature to %s", temperature)
self._sendCommand("M140 S%s" % temperature)
@pyqtProperty(float, notify = extruderTemperatureChanged)
def extruderTemperature(self):
return self._extruder_temperatures[0]
def _setHeadPosition(self, x, y , z, speed):
self._sendCommand("G0 X%s Y%s Z%s F%s" % (x, y, z, speed))
@pyqtProperty(float, notify = bedTemperatureChanged)
def bedTemperature(self):
return self._bed_temperature
def _setHeadX(self, x, speed):
self._sendCommand("G0 X%s F%s" % (x, speed))
@pyqtProperty(str, notify = onError)
def error(self):
return self._error_state
def _setHeadY(self, y, speed):
self._sendCommand("G0 Y%s F%s" % (y, speed))
# TODO: Might need to add check that extruders can not be changed when it started printing or loading these settings from settings object
def setNumExtuders(self, num):
self._extruder_count = num
self._extruder_temperatures = [0] * self._extruder_count
self._target_extruder_temperatures = [0] * self._extruder_count
## Is the printer actively printing
def isPrinting(self):
if not self._is_connected or self._serial is None:
return False
return self._is_printing
def _setHeadZ(self, z, speed):
self._sendCommand("G0 Y%s F%s" % (z, speed))
@pyqtSlot()
def startPrint(self):
@ -163,7 +136,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
## Start a print based on a g-code.
# \param gcode_list List with gcode (strings).
def printGCode(self, gcode_list):
if self.isPrinting() or not self._is_connected:
if not self._progress or self._connection_state != ConnectionState.CONNECTED:
Logger.log("d", "Printer is busy or not connected, aborting print")
self.writeError.emit(self)
return
@ -198,7 +171,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
def _updateFirmware(self):
self.setProgress(0, 100)
if self._is_connecting or self._is_connected:
if self._connection_state != ConnectionState.CLOSED:
self.close()
hex_file = intelHex.readHex(self._firmware_file_name)
@ -253,14 +226,14 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
self._poll_endstop = False
def _pollEndStop(self):
while self._is_connected and self._poll_endstop:
while self._connection_state == ConnectionState.CONNECTED and self._poll_endstop:
self.sendCommand("M119")
time.sleep(0.5)
## Private connect function run by thread. Can be started by calling connect.
def _connect(self):
Logger.log("d", "Attempting to connect to %s", self._serial_port)
self._is_connecting = True
self.setConnectionState(ConnectionState.CONNECTING)
programmer = stk500v2.Stk500v2()
try:
programmer.connect(self._serial_port) # Connect with the serial, if this succeeds, it's an arduino based usb device.
@ -277,7 +250,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
try:
self._serial = serial.Serial(str(self._serial_port), baud_rate, timeout = 3, writeTimeout = 10000)
except serial.SerialException:
#Logger.log("i", "Could not open port %s" % self._serial_port)
Logger.log("d", "Could not open port %s" % self._serial_port)
continue
else:
if not self.setBaudRate(baud_rate):
@ -291,15 +264,16 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
while timeout_time > time.time():
line = self._readline()
if line is None:
self.setIsConnected(False) # Something went wrong with reading, could be that close was called.
# Something went wrong with reading, could be that close was called.
self.setConnectionState(ConnectionState.CLOSED)
return
if b"T:" in line:
self._serial.timeout = 0.5
sucesfull_responses += 1
if sucesfull_responses >= self._required_responses_auto_baud:
self._serial.timeout = 2 #Reset serial timeout
self.setIsConnected(True)
self._serial.timeout = 2 # Reset serial timeout
self.setConnectionState(ConnectionState.CONNECTED)
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
return
@ -307,7 +281,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
self.close() # Unable to connect, wrap up.
self.setIsConnected(False)
self.setConnectionState(ConnectionState.CLOSED)
## Set the baud rate of the serial. This can cause exceptions, but we simply want to ignore those.
def setBaudRate(self, baud_rate):
@ -317,21 +291,9 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
except Exception as e:
return False
def setIsConnected(self, state):
self._is_connecting = False
if self._is_connected != state:
self._is_connected = state
self.connectionStateChanged.emit(self._serial_port)
if self._is_connected:
self._listen_thread.start() #Start listening
else:
Logger.log("w", "Printer connection state was not changed")
connectionStateChanged = Signal()
## Close the printer connection
def close(self):
Logger.log("d", "Closing the printer connection.")
Logger.log("d", "Closing the USB printer connection.")
if self._connect_thread.isAlive():
try:
self._connect_thread.join()
@ -339,10 +301,10 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
Logger.log("d", "PrinterConnection.close: %s (expected)", e)
pass # This should work, but it does fail sometimes for some reason
self._connect_thread = threading.Thread(target=self._connect)
self._connect_thread = threading.Thread(target = self._connect)
self._connect_thread.daemon = True
self.setIsConnected(False)
self.setConnectionState(ConnectionState.CLOSED)
if self._serial is not None:
try:
self._listen_thread.join()
@ -350,49 +312,10 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
pass
self._serial.close()
self._listen_thread = threading.Thread(target=self._listen)
self._listen_thread = threading.Thread(target = self._listen)
self._listen_thread.daemon = True
self._serial = None
def isConnected(self):
return self._is_connected
@pyqtSlot(int)
def heatupNozzle(self, temperature):
Logger.log("d", "Setting nozzle temperature to %s", temperature)
self._sendCommand("M104 S%s" % temperature)
@pyqtSlot(int)
def heatupBed(self, temperature):
Logger.log("d", "Setting bed temperature to %s", temperature)
self._sendCommand("M140 S%s" % temperature)
@pyqtSlot()
def setMoveToRelative(self):
self._sendCommand("G91")
@pyqtSlot()
def setMoveToAbsolute(self):
self._sendCommand("G90")
@pyqtSlot("long", "long","long")
def moveHead(self, x, y, z):
Logger.log("d","Moving head to %s, %s , %s", x, y, z)
self._sendCommand("G0 X%s Y%s Z%s F3000" % (x, y, z))
@pyqtSlot("long", "long","long")
def moveHeadRelative(self, x, y, z):
self.setMoveToRelative()
self.moveHead(x,y,z)
self.setMoveToAbsolute()
@pyqtSlot()
def homeHead(self):
self._sendCommand("G28")
@pyqtSlot()
def homeBed(self):
self._sendCommand("G28 Z")
## Directly send the command, withouth checking connection state (eg; printing).
# \param cmd string with g-code
@ -433,10 +356,6 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
self._setErrorState("Unexpected error while writing serial port %s " % e)
self.close()
## Ensure that close gets called when object is destroyed
def __del__(self):
self.close()
def createControlInterface(self):
if self._control_view is None:
Logger.log("d", "Creating control interface for printer connection")
@ -456,7 +375,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
## Send a command to printer.
# \param cmd string with g-code
def sendCommand(self, cmd):
if self.isPrinting():
if not self._progress:
self._command_queue.put(cmd)
elif self.isConnected():
self._sendCommand(cmd)
@ -467,24 +386,6 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
self._error_state = error
self.onError.emit()
## Private function to set the temperature of an extruder
# \param index index of the extruder
# \param temperature received temperature
def _setExtruderTemperature(self, index, temperature):
try:
self._extruder_temperatures[index] = temperature
self.extruderTemperatureChanged.emit()
except Exception as e:
Logger.log("d", "PrinterConnection._setExtruderTemperature: ", e)
pass
## Private function to set the temperature of the bed.
# As all printers (as of time of writing) only support a single heated bed,
# these are not indexed as with extruders.
def _setBedTemperature(self, temperature):
self._bed_temperature = temperature
self.bedTemperatureChanged.emit()
def requestWrite(self, node, file_name = None, filter_by_machine = False):
self.showControlInterface()
@ -507,7 +408,7 @@ class USBPrinterOutputDevice(OutputDevice, QObject, SignalEmitter):
Logger.log("i", "Printer connection listen thread started for %s" % self._serial_port)
temperature_request_timeout = time.time()
ok_timeout = time.time()
while self._is_connected:
while self._connected:
line = self._readline()
if line is None: