mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-19 04:37:51 -06:00
Refactoring & documentation
CURA-1339
This commit is contained in:
parent
9ee6323177
commit
4b5c118ed2
3 changed files with 28 additions and 270 deletions
|
@ -1,244 +0,0 @@
|
||||||
# Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
|
||||||
|
|
||||||
from UM.Signal import Signal, SignalEmitter
|
|
||||||
from . import USBPrinterOutputDevice
|
|
||||||
from UM.Application import Application
|
|
||||||
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
|
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
|
||||||
|
|
||||||
import threading
|
|
||||||
import platform
|
|
||||||
import glob
|
|
||||||
import time
|
|
||||||
import os.path
|
|
||||||
from UM.Extension import Extension
|
|
||||||
|
|
||||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
|
||||||
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
|
|
||||||
from UM.i18n import i18nCatalog
|
|
||||||
i18n_catalog = i18nCatalog("cura")
|
|
||||||
|
|
||||||
class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|
||||||
def __init__(self, parent = None):
|
|
||||||
QObject.__init__(self, parent)
|
|
||||||
SignalEmitter.__init__(self)
|
|
||||||
OutputDevicePlugin.__init__(self)
|
|
||||||
Extension.__init__(self)
|
|
||||||
self._serial_port_list = []
|
|
||||||
self._printer_connections = {}
|
|
||||||
self._printer_connections_model = None
|
|
||||||
self._update_thread = threading.Thread(target = self._updateThread)
|
|
||||||
self._update_thread.setDaemon(True)
|
|
||||||
|
|
||||||
self._check_updates = True
|
|
||||||
self._firmware_view = None
|
|
||||||
|
|
||||||
## Add menu item to top menu of the application.
|
|
||||||
self.setMenuName(i18n_catalog.i18nc("@title:menu","Firmware"))
|
|
||||||
self.addMenuItem(i18n_catalog.i18nc("@item:inmenu", "Update Firmware"), self.updateAllFirmware)
|
|
||||||
|
|
||||||
Application.getInstance().applicationShuttingDown.connect(self.stop)
|
|
||||||
self.addConnectionSignal.connect(self.addConnection) #Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
|
||||||
|
|
||||||
addConnectionSignal = Signal()
|
|
||||||
printerConnectionStateChanged = pyqtSignal()
|
|
||||||
|
|
||||||
progressChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(float, notify = progressChanged)
|
|
||||||
def progress(self):
|
|
||||||
progress = 0
|
|
||||||
for printer_name, connection in self._printer_connections.items(): # TODO: @UnusedVariable "printer_name"
|
|
||||||
progress += connection.progress
|
|
||||||
|
|
||||||
return progress / len(self._printer_connections)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
self._check_updates = True
|
|
||||||
self._update_thread.start()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self._check_updates = False
|
|
||||||
try:
|
|
||||||
self._update_thread.join()
|
|
||||||
except RuntimeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _updateThread(self):
|
|
||||||
while self._check_updates:
|
|
||||||
result = self.getSerialPortList(only_list_usb = True)
|
|
||||||
self._addRemovePorts(result)
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
## Show firmware interface.
|
|
||||||
# This will create the view if its not already created.
|
|
||||||
def spawnFirmwareInterface(self, serial_port):
|
|
||||||
if self._firmware_view is None:
|
|
||||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml"))
|
|
||||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
|
||||||
|
|
||||||
self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
|
||||||
self._firmware_context.setContextProperty("manager", self)
|
|
||||||
self._firmware_view = component.create(self._firmware_context)
|
|
||||||
|
|
||||||
self._firmware_view.show()
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def updateAllFirmware(self):
|
|
||||||
if not self._printer_connections:
|
|
||||||
Message(i18n_catalog.i18nc("@info","Cannot update firmware, there were no connected printers found.")).show()
|
|
||||||
return
|
|
||||||
|
|
||||||
self.spawnFirmwareInterface("")
|
|
||||||
for printer_connection in self._printer_connections:
|
|
||||||
try:
|
|
||||||
self._printer_connections[printer_connection].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
|
||||||
except FileNotFoundError:
|
|
||||||
self._printer_connections[printer_connection].setProgress(100, 100)
|
|
||||||
Logger.log("w", "No firmware found for printer %s", printer_connection)
|
|
||||||
continue
|
|
||||||
|
|
||||||
@pyqtSlot(str, result = bool)
|
|
||||||
def updateFirmwareBySerial(self, serial_port):
|
|
||||||
if serial_port in self._printer_connections:
|
|
||||||
self.spawnFirmwareInterface(self._printer_connections[serial_port].getSerialPort())
|
|
||||||
try:
|
|
||||||
self._printer_connections[serial_port].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
|
||||||
except FileNotFoundError:
|
|
||||||
self._firmware_view.close()
|
|
||||||
Logger.log("e", "Could not find firmware required for this machine")
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
## Return the singleton instance of the USBPrinterManager
|
|
||||||
@classmethod
|
|
||||||
def getInstance(cls, engine = None, script_engine = None):
|
|
||||||
# Note: Explicit use of class name to prevent issues with inheritance.
|
|
||||||
if USBPrinterManager._instance is None:
|
|
||||||
USBPrinterManager._instance = cls()
|
|
||||||
|
|
||||||
return USBPrinterManager._instance
|
|
||||||
|
|
||||||
def _getDefaultFirmwareName(self):
|
|
||||||
machine_instance = Application.getInstance().getMachineManager().getActiveMachineInstance()
|
|
||||||
machine_type = machine_instance.getMachineDefinition().getId()
|
|
||||||
if platform.system() == "Linux":
|
|
||||||
baudrate = 115200
|
|
||||||
else:
|
|
||||||
baudrate = 250000
|
|
||||||
|
|
||||||
# NOTE: The keyword used here is the id of the machine. You can find the id of your machine in the *.json file, eg.
|
|
||||||
# https://github.com/Ultimaker/Cura/blob/master/resources/machines/ultimaker_original.json#L2
|
|
||||||
# The *.hex files are stored at a seperate repository:
|
|
||||||
# https://github.com/Ultimaker/cura-binary-data/tree/master/cura/resources/firmware
|
|
||||||
machine_without_extras = {"bq_witbox" : "MarlinWitbox.hex",
|
|
||||||
"ultimaker_original" : "MarlinUltimaker-{baudrate}.hex",
|
|
||||||
"ultimaker_original_plus" : "MarlinUltimaker-UMOP-{baudrate}.hex",
|
|
||||||
"ultimaker2" : "MarlinUltimaker2.hex",
|
|
||||||
"ultimaker2_go" : "MarlinUltimaker2go.hex",
|
|
||||||
"ultimaker2plus" : "MarlinUltimaker2plus.hex",
|
|
||||||
"ultimaker2_extended" : "MarlinUltimaker2extended.hex",
|
|
||||||
"ultimaker2_extended_plus" : "MarlinUltimaker2extended-plus.hex",
|
|
||||||
}
|
|
||||||
machine_with_heated_bed = {"ultimaker_original" : "MarlinUltimaker-HBK-{baudrate}.hex",
|
|
||||||
}
|
|
||||||
|
|
||||||
##TODO: Add check for multiple extruders
|
|
||||||
hex_file = None
|
|
||||||
if machine_type in machine_without_extras.keys(): # The machine needs to be defined here!
|
|
||||||
if machine_type in machine_with_heated_bed.keys() and machine_instance.getMachineSettingValue("machine_heated_bed"):
|
|
||||||
Logger.log("d", "Choosing firmware with heated bed enabled for machine %s.", machine_type)
|
|
||||||
hex_file = machine_with_heated_bed[machine_type] # Return firmware with heated bed enabled
|
|
||||||
else:
|
|
||||||
Logger.log("d", "Choosing basic firmware for machine %s.", machine_type)
|
|
||||||
hex_file = machine_without_extras[machine_type] # Return "basic" firmware
|
|
||||||
else:
|
|
||||||
Logger.log("e", "There is no firmware for machine %s.", machine_type)
|
|
||||||
|
|
||||||
if hex_file:
|
|
||||||
return hex_file.format(baudrate=baudrate)
|
|
||||||
else:
|
|
||||||
Logger.log("e", "Could not find any firmware for machine %s.", machine_type)
|
|
||||||
raise FileNotFoundError()
|
|
||||||
|
|
||||||
def _addRemovePorts(self, serial_ports):
|
|
||||||
# First, find and add all new or changed keys
|
|
||||||
for serial_port in list(serial_ports):
|
|
||||||
if serial_port not in self._serial_port_list:
|
|
||||||
self.addConnectionSignal.emit(serial_port) #Hack to ensure its created in main thread
|
|
||||||
continue
|
|
||||||
self._serial_port_list = list(serial_ports)
|
|
||||||
|
|
||||||
connections_to_remove = []
|
|
||||||
for port, connection in self._printer_connections.items():
|
|
||||||
if port not in self._serial_port_list:
|
|
||||||
connection.close()
|
|
||||||
connections_to_remove.append(port)
|
|
||||||
|
|
||||||
for port in connections_to_remove:
|
|
||||||
del self._printer_connections[port]
|
|
||||||
|
|
||||||
|
|
||||||
## Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
|
||||||
def addConnection(self, serial_port):
|
|
||||||
connection = USBPrinterOutputDevice.USBPrinterOutputDevice(serial_port)
|
|
||||||
connection.connect()
|
|
||||||
connection.connectionStateChanged.connect(self._onPrinterConnectionStateChanged)
|
|
||||||
connection.progressChanged.connect(self.progressChanged)
|
|
||||||
self._printer_connections[serial_port] = connection
|
|
||||||
|
|
||||||
def _onPrinterConnectionStateChanged(self, serial_port):
|
|
||||||
try:
|
|
||||||
if self._printer_connections[serial_port].connectionState == ConnectionState.CONNECTED:
|
|
||||||
self.getOutputDeviceManager().addOutputDevice(self._printer_connections[serial_port])
|
|
||||||
else:
|
|
||||||
self.getOutputDeviceManager().removeOutputDevice(serial_port)
|
|
||||||
self.printerConnectionStateChanged.emit()
|
|
||||||
except KeyError:
|
|
||||||
pass # no output device by this device_id found in connection list.
|
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty(QObject , notify = printerConnectionStateChanged)
|
|
||||||
def connectedPrinterList(self):
|
|
||||||
self._printer_connections_model = ListModel()
|
|
||||||
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].connectionState == ConnectionState.CONNECTED:
|
|
||||||
self._printer_connections_model.appendItem({"name":connection, "printer": self._printer_connections[connection]})
|
|
||||||
return self._printer_connections_model
|
|
||||||
|
|
||||||
## Create a list of serial ports on the system.
|
|
||||||
# \param only_list_usb If true, only usb ports are listed
|
|
||||||
def getSerialPortList(self, only_list_usb = False):
|
|
||||||
base_list = []
|
|
||||||
if platform.system() == "Windows":
|
|
||||||
import winreg
|
|
||||||
try:
|
|
||||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
|
|
||||||
i = 0
|
|
||||||
while True:
|
|
||||||
values = winreg.EnumValue(key, i)
|
|
||||||
if not only_list_usb or "USBSER" in values[0]:
|
|
||||||
base_list += [values[1]]
|
|
||||||
i += 1
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if only_list_usb:
|
|
||||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.usb*")
|
|
||||||
base_list = filter(lambda s: "Bluetooth" not in s, base_list) # Filter because mac sometimes puts them in the list
|
|
||||||
else:
|
|
||||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*")
|
|
||||||
return list(base_list)
|
|
||||||
|
|
||||||
_instance = None
|
|
|
@ -72,6 +72,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
# Current Z stage location
|
# Current Z stage location
|
||||||
self._current_z = 0
|
self._current_z = 0
|
||||||
|
|
||||||
|
# Check if endstops are ever pressed (used for first run)
|
||||||
self._x_min_endstop_pressed = False
|
self._x_min_endstop_pressed = False
|
||||||
self._y_min_endstop_pressed = False
|
self._y_min_endstop_pressed = False
|
||||||
self._z_min_endstop_pressed = False
|
self._z_min_endstop_pressed = False
|
||||||
|
@ -140,14 +141,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
for layer in gcode_list:
|
for layer in gcode_list:
|
||||||
self._gcode.extend(layer.split("\n"))
|
self._gcode.extend(layer.split("\n"))
|
||||||
|
|
||||||
#Reset line number. If this is not done, first line is sometimes ignored
|
# Reset line number. If this is not done, first line is sometimes ignored
|
||||||
self._gcode.insert(0, "M110")
|
self._gcode.insert(0, "M110")
|
||||||
self._gcode_position = 0
|
self._gcode_position = 0
|
||||||
self._print_start_time_100 = None
|
self._print_start_time_100 = None
|
||||||
self._is_printing = True
|
self._is_printing = True
|
||||||
self._print_start_time = time.time()
|
self._print_start_time = time.time()
|
||||||
|
|
||||||
for i in range(0, 4): #Push first 4 entries before accepting other inputs
|
for i in range(0, 4): # Push first 4 entries before accepting other inputs
|
||||||
self._sendNextGcodeLine()
|
self._sendNextGcodeLine()
|
||||||
|
|
||||||
self.writeFinished.emit(self)
|
self.writeFinished.emit(self)
|
||||||
|
@ -162,7 +163,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
if not self._updating_firmware and not self._connect_thread.isAlive():
|
if not self._updating_firmware and not self._connect_thread.isAlive():
|
||||||
self._connect_thread.start()
|
self._connect_thread.start()
|
||||||
|
|
||||||
## Private fuction (threaded) that actually uploads the firmware.
|
## Private function (threaded) that actually uploads the firmware.
|
||||||
def _updateFirmware(self):
|
def _updateFirmware(self):
|
||||||
self.setProgress(0, 100)
|
self.setProgress(0, 100)
|
||||||
|
|
||||||
|
@ -182,7 +183,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
time.sleep(1) # Give programmer some time to connect. Might need more in some cases, but this worked in all tested cases.
|
# Give programmer some time to connect. Might need more in some cases, but this worked in all tested cases.
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
if not programmer.isConnected():
|
if not programmer.isConnected():
|
||||||
Logger.log("e", "Unable to connect with serial. Could not update firmware")
|
Logger.log("e", "Unable to connect with serial. Could not update firmware")
|
||||||
|
@ -238,7 +240,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
|
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
|
||||||
|
|
||||||
# If the programmer connected, we know its an atmega based version. Not all that useful, but it does give some debugging information.
|
# If the programmer connected, we know its an atmega based version.
|
||||||
|
# Not all that useful, but it does give some debugging information.
|
||||||
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
||||||
Logger.log("d","Attempting to connect to printer with serial %s on baud rate %s", self._serial_port, baud_rate)
|
Logger.log("d","Attempting to connect to printer with serial %s on baud rate %s", self._serial_port, baud_rate)
|
||||||
if self._serial is None:
|
if self._serial is None:
|
||||||
|
@ -259,7 +262,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
while timeout_time > time.time():
|
while timeout_time > time.time():
|
||||||
line = self._readline()
|
line = self._readline()
|
||||||
if line is None:
|
if line is None:
|
||||||
# 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)
|
self.setConnectionState(ConnectionState.CLOSED)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -273,10 +276,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
|
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
|
||||||
|
|
||||||
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
|
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
|
||||||
self.close() # Unable to connect, wrap up.
|
self.close() # Unable to connect, wrap up.
|
||||||
self.setConnectionState(ConnectionState.CLOSED)
|
self.setConnectionState(ConnectionState.CLOSED)
|
||||||
|
|
||||||
## Set the baud rate of the serial. This can cause exceptions, but we simply want to ignore those.
|
## Set the baud rate of the serial. This can cause exceptions, but we simply want to ignore those.
|
||||||
|
@ -312,7 +315,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._listen_thread.daemon = True
|
self._listen_thread.daemon = True
|
||||||
self._serial = None
|
self._serial = None
|
||||||
|
|
||||||
|
|
||||||
## Directly send the command, withouth checking connection state (eg; printing).
|
## Directly send the command, withouth checking connection state (eg; printing).
|
||||||
# \param cmd string with g-code
|
# \param cmd string with g-code
|
||||||
def _sendCommand(self, cmd):
|
def _sendCommand(self, cmd):
|
||||||
|
@ -395,7 +397,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
while self._connection_state == ConnectionState.CONNECTED:
|
while self._connection_state == ConnectionState.CONNECTED:
|
||||||
line = self._readline()
|
line = self._readline()
|
||||||
if line is None:
|
if line is None:
|
||||||
break # None is only returned when something went wrong. Stop listening
|
break # None is only returned when something went wrong. Stop listening
|
||||||
|
|
||||||
if time.time() > temperature_request_timeout:
|
if time.time() > temperature_request_timeout:
|
||||||
if self._num_extruders > 0:
|
if self._num_extruders > 0:
|
||||||
|
@ -408,8 +410,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
if line.startswith(b"Error:"):
|
if line.startswith(b"Error:"):
|
||||||
# Oh YEAH, consistency.
|
# Oh YEAH, consistency.
|
||||||
# Marlin reports a MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
# Marlin reports a MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
||||||
# But a bed temp error is reported as "Error: Temperature heated bed switched off. MAXTEMP triggered !!"
|
# But a bed temp error is reported as "Error: Temperature heated bed switched off. MAXTEMP triggered !!"
|
||||||
# So we can have an extra newline in the most common case. Awesome work people.
|
# So we can have an extra newline in the most common case. Awesome work people.
|
||||||
if re.match(b"Error:[0-9]\n", line):
|
if re.match(b"Error:[0-9]\n", line):
|
||||||
line = line.rstrip() + self._readline()
|
line = line.rstrip() + self._readline()
|
||||||
|
|
||||||
|
@ -418,12 +420,12 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
if not self.hasError():
|
if not self.hasError():
|
||||||
self._setErrorState(line[6:])
|
self._setErrorState(line[6:])
|
||||||
|
|
||||||
elif b" T:" in line or line.startswith(b"T:"): #Temperature message
|
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)))
|
self._setHotendTemperature(self._temperature_requested_extruder_index, float(re.search(b"T: *([0-9\.]*)", line).group(1)))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if b"B:" in line: # Check if it's a bed temperature
|
if b"B:" in line: # Check if it's a bed temperature
|
||||||
try:
|
try:
|
||||||
self._setBedTemperature(float(re.search(b"B: *([0-9\.]*)", line).group(1)))
|
self._setBedTemperature(float(re.search(b"B: *([0-9\.]*)", line).group(1)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -435,7 +437,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
|
|
||||||
if self._is_printing:
|
if self._is_printing:
|
||||||
if line == b"" and time.time() > ok_timeout:
|
if line == b"" and time.time() > ok_timeout:
|
||||||
line = b"ok" # Force a timeout (basicly, send next command)
|
line = b"ok" # Force a timeout (basically, send next command)
|
||||||
|
|
||||||
if b"ok" in line:
|
if b"ok" in line:
|
||||||
ok_timeout = time.time() + 5
|
ok_timeout = time.time() + 5
|
||||||
|
@ -443,14 +445,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._sendCommand(self._command_queue.get())
|
self._sendCommand(self._command_queue.get())
|
||||||
else:
|
else:
|
||||||
self._sendNextGcodeLine()
|
self._sendNextGcodeLine()
|
||||||
elif b"resend" in line.lower() or b"rs" in line: # Because a resend can be asked with "resend" and "rs"
|
elif b"resend" in line.lower() or b"rs" in line: # Because a resend can be asked with "resend" and "rs"
|
||||||
try:
|
try:
|
||||||
self._gcode_position = int(line.replace(b"N:",b" ").replace(b"N",b" ").replace(b":",b" ").split()[-1])
|
self._gcode_position = int(line.replace(b"N:",b" ").replace(b"N",b" ").replace(b":",b" ").split()[-1])
|
||||||
except:
|
except:
|
||||||
if b"rs" in line:
|
if b"rs" in line:
|
||||||
self._gcode_position = int(line.split()[1])
|
self._gcode_position = int(line.split()[1])
|
||||||
|
|
||||||
else: # Request the temperature on comm timeout (every 2 seconds) when we are not printing.)
|
else: # Request the temperature on comm timeout (every 2 seconds) when we are not printing.)
|
||||||
if line == b"":
|
if line == b"":
|
||||||
if self._num_extruders > 0:
|
if self._num_extruders > 0:
|
||||||
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._num_extruders
|
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._num_extruders
|
||||||
|
@ -472,7 +474,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
try:
|
try:
|
||||||
if line == "M0" or line == "M1":
|
if line == "M0" or line == "M1":
|
||||||
line = "M105" #Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
line = "M105" # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
||||||
if ("G0" in line or "G1" in line) and "Z" in line:
|
if ("G0" in line or "G1" in line) and "Z" in line:
|
||||||
z = float(re.search("Z([0-9\.]*)", line).group(1))
|
z = float(re.search("Z([0-9\.]*)", line).group(1))
|
||||||
if self._current_z != z:
|
if self._current_z != z:
|
||||||
|
@ -484,13 +486,13 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
|
|
||||||
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
|
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.setProgress((self._gcode_position / len(self._gcode)) * 100)
|
||||||
self.progressChanged.emit()
|
self.progressChanged.emit()
|
||||||
|
|
||||||
## Set the progress of the print.
|
## Set the progress of the print.
|
||||||
# It will be normalized (based on max_progress) to range 0 - 100
|
# It will be normalized (based on max_progress) to range 0 - 100
|
||||||
def setProgress(self, progress, max_progress = 100):
|
def setProgress(self, progress, max_progress = 100):
|
||||||
self._progress = (progress / max_progress) * 100 #Convert to scale of 0-100
|
self._progress = (progress / max_progress) * 100 # Convert to scale of 0-100
|
||||||
self.progressChanged.emit()
|
self.progressChanged.emit()
|
||||||
|
|
||||||
## Cancel the current print. Printer connection wil continue to listen.
|
## Cancel the current print. Printer connection wil continue to listen.
|
||||||
|
@ -507,7 +509,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
|
|
||||||
## Check if the process did not encounter an error yet.
|
## Check if the process did not encounter an error yet.
|
||||||
def hasError(self):
|
def hasError(self):
|
||||||
return self._error_state != None
|
return self._error_state is not None
|
||||||
|
|
||||||
## private read line used by printer connection to listen for data on serial port.
|
## private read line used by printer connection to listen for data on serial port.
|
||||||
def _readline(self):
|
def _readline(self):
|
||||||
|
@ -516,7 +518,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
try:
|
try:
|
||||||
ret = self._serial.readline()
|
ret = self._serial.readline()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.log("e","Unexpected error while reading serial port. %s" %e)
|
Logger.log("e", "Unexpected error while reading serial port. %s" % e)
|
||||||
self._setErrorState("Printer has been disconnected")
|
self._setErrorState("Printer has been disconnected")
|
||||||
self.close()
|
self.close()
|
||||||
return None
|
return None
|
||||||
|
@ -530,7 +532,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
|
|
||||||
def _onFirmwareUpdateComplete(self):
|
def _onFirmwareUpdateComplete(self):
|
||||||
self._update_firmware_thread.join()
|
self._update_firmware_thread.join()
|
||||||
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
self._update_firmware_thread = threading.Thread(target = self._updateFirmware)
|
||||||
self._update_firmware_thread.daemon = True
|
self._update_firmware_thread.daemon = True
|
||||||
|
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright (c) 2015 Ultimaker B.V.
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from . import USBPrinterManager
|
from . import USBPrinterOutputDeviceManager
|
||||||
from PyQt5.QtQml import qmlRegisterType, qmlRegisterSingletonType
|
from PyQt5.QtQml import qmlRegisterType, qmlRegisterSingletonType
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
@ -19,5 +19,5 @@ def getMetaData():
|
||||||
}
|
}
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
qmlRegisterSingletonType(USBPrinterManager.USBPrinterManager, "UM", 1, 0, "USBPrinterManager", USBPrinterManager.USBPrinterManager.getInstance)
|
qmlRegisterSingletonType(USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager, "UM", 1, 0, "USBPrinterManager", USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance)
|
||||||
return {"extension":USBPrinterManager.USBPrinterManager.getInstance(),"output_device": USBPrinterManager.USBPrinterManager.getInstance() }
|
return {"extension":USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance(), "output_device": USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance()}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue