Browse Source

Changed USB printing to reflect changes in output device API

CURA-1339
Jaime van Kessel 9 years ago
parent
commit
0cd1031ec7
2 changed files with 36 additions and 135 deletions
  1. 3 3
      plugins/USBPrinting/USBPrinterManager.py
  2. 33 132
      plugins/USBPrinting/USBPrinterOutputDevice.py

+ 3 - 3
plugins/USBPrinting/USBPrinterManager.py

@@ -8,6 +8,7 @@ from UM.Resources import Resources
 from UM.Logger import Logger
 from UM.PluginRegistry import PluginRegistry
 from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
+from cura.PrinterOutputDevice import ConnectionState
 from UM.Qt.ListModel import ListModel
 from UM.Message import Message
 
@@ -20,7 +21,6 @@ import time
 import os.path
 from UM.Extension import Extension
 
-from PyQt5.QtQuick import QQuickView
 from PyQt5.QtQml import QQmlComponent, QQmlContext
 from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
 from UM.i18n import i18nCatalog
@@ -197,7 +197,7 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
         self._printer_connections[serial_port] = connection
 
     def _onPrinterConnectionStateChanged(self, serial_port):
-        if self._printer_connections[serial_port].isConnected():
+        if self._printer_connections[serial_port].connectionState == ConnectionState.CLOSED:
             self.getOutputDeviceManager().addOutputDevice(self._printer_connections[serial_port])
         else:
             self.getOutputDeviceManager().removeOutputDevice(serial_port)
@@ -209,7 +209,7 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
         self._printer_connections_model.addRoleName(Qt.UserRole + 1,"name")
         self._printer_connections_model.addRoleName(Qt.UserRole + 2, "printer")
         for connection in self._printer_connections:
-            if self._printer_connections[connection].isConnected():
+            if self._printer_connections[connection].isConnected:
                 self._printer_connections_model.appendItem({"name":connection, "printer": self._printer_connections[connection]})
         return self._printer_connections_model
 

+ 33 - 132
plugins/USBPrinting/USBPrinterOutputDevice.py

@@ -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: