diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py index e33834ffce..951b7138f1 100644 --- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py +++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py @@ -1,4 +1,6 @@ from UM.Application import Application +from UM.Logger import Logger + from cura.PrinterOutputDevice import PrinterOutputDevice from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply @@ -30,6 +32,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice): def _createEmptyRequest(self, target): url = QUrl("http://" + self._address + self._api_prefix + target) + print(url) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") request.setHeader(QNetworkRequest.UserAgentHeader, self._user_agent) @@ -66,9 +69,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice): self._last_response_time = time() try: self._onFinishedCallbacks[reply.url().toString() + str(reply.operation())](reply) - except Exception as e: - print("Something went wrong with callback", e) - pass + except Exception: + Logger.logException("w", "something went wrong with callback") @pyqtSlot(str, result=str) def getProperty(self, key): diff --git a/cura/PrinterOutput/PrintJobOutputModel.py b/cura/PrinterOutput/PrintJobOutputModel.py index 1e0d82f1b0..407bffcbfe 100644 --- a/cura/PrinterOutput/PrintJobOutputModel.py +++ b/cura/PrinterOutput/PrintJobOutputModel.py @@ -11,6 +11,7 @@ class PrintJobOutputModel(QObject): stateChanged = pyqtSignal() timeTotalChanged = pyqtSignal() timeElapsedChanged = pyqtSignal() + nameChanged = pyqtSignal() def __init__(self, output_controller: "PrinterOutputController", parent=None): super().__init__(parent) @@ -18,6 +19,16 @@ class PrintJobOutputModel(QObject): self._state = "" self._time_total = 0 self._time_elapsed = 0 + self._name = "" + + @pyqtProperty(str, notify = nameChanged) + def name(self): + return self._name + + def updateName(self, name: str): + if self._name != name: + self._name = name + self.nameChanged.emit() @pyqtProperty(int, notify = timeTotalChanged) def timeTotal(self): diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py index 00644980b4..7c10944cfd 100644 --- a/cura/PrinterOutput/PrinterOutputModel.py +++ b/cura/PrinterOutput/PrinterOutputModel.py @@ -5,11 +5,11 @@ from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot from UM.Logger import Logger from typing import Optional, List from UM.Math.Vector import Vector +from cura.PrinterOutput.ExtruderOuputModel import ExtruderOutputModel MYPY = False if MYPY: from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel - from cura.PrinterOutput.ExtruderOuputModel import ExtruderOutputModel from cura.PrinterOutput.PrinterOutputController import PrinterOutputController @@ -21,17 +21,19 @@ class PrinterOutputModel(QObject): nameChanged = pyqtSignal() headPositionChanged = pyqtSignal() - def __init__(self, output_controller: "PrinterOutputController", extruders: List["ExtruderOutputModel"], parent=None): + def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None): super().__init__(parent) self._bed_temperature = 0 self._target_bed_temperature = 0 self._name = "" self._controller = output_controller - self._extruders = extruders + self._extruders = [ExtruderOutputModel(printer=self)] * number_of_extruders self._head_position = Vector(0, 0, 0) self._active_print_job = None # type: Optional[PrintJobOutputModel] + self._printer_state = "unknown" + # Features of the printer; self._can_pause = True self._can_abort = True @@ -135,6 +137,11 @@ class PrinterOutputModel(QObject): self._active_print_job = print_job self.activePrintJobChanged.emit() + def updatePrinterState(self, printer_state): + if self._printer_state != printer_state: + self._printer_state = printer_state + self.printerStateChanged.emit() + @pyqtProperty(QObject, notify = activePrintJobChanged) def activePrintJob(self): return self._active_print_job diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py index 86211bddb4..b4e7bdf1af 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py @@ -1,9 +1,86 @@ from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice +from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel +from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel + +from UM.Logger import Logger + +from PyQt5.QtNetwork import QNetworkRequest + + +import json class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): def __init__(self, device_id, address: str, properties, parent = None): super().__init__(device_id = device_id, address = address, properties = properties, parent = parent) + self._api_prefix = "/api/v1/" + self._number_of_extruders = 2 def _update(self): - super()._update() \ No newline at end of file + super()._update() + self._get("printer", onFinished=self._onGetPrinterDataFinished) + self._get("print_job", onFinished=self._onGetPrintJobFinished) + + def _onGetPrintJobFinished(self, reply): + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + + if not self._printers: + return # Ignore the data for now, we don't have info about a printer yet. + printer = self._printers[0] + + if status_code == 200: + try: + result = json.loads(bytes(reply.readAll()).decode("utf-8")) + except json.decoder.JSONDecodeError: + Logger.log("w", "Received an invalid print job state message: Not valid JSON.") + return + if printer.activePrintJob is None: + print_job = PrintJobOutputModel(output_controller=None) + printer.updateActivePrintJob(print_job) + else: + print_job = printer.activePrintJob + print_job.updateState(result["state"]) + print_job.updateTimeElapsed(result["time_elapsed"]) + print_job.updateTimeTotal(result["time_total"]) + print_job.updateName(result["name"]) + elif status_code == 404: + # No job found, so delete the active print job (if any!) + printer.updateActivePrintJob(None) + else: + Logger.log("w", + "Got status code {status_code} while trying to get printer data".format(status_code=status_code)) + + def _onGetPrinterDataFinished(self, reply): + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + if status_code == 200: + try: + result = json.loads(bytes(reply.readAll()).decode("utf-8")) + except json.decoder.JSONDecodeError: + Logger.log("w", "Received an invalid printer state message: Not valid JSON.") + return + + if not self._printers: + self._printers = [PrinterOutputModel(output_controller=None, number_of_extruders=self._number_of_extruders)] + + # LegacyUM3 always has a single printer. + printer = self._printers[0] + printer.updateBedTemperature(result["bed"]["temperature"]["current"]) + printer.updateTargetBedTemperature(result["bed"]["temperature"]["target"]) + printer.updatePrinterState(result["status"]) + + for index in range(0, self._number_of_extruders): + temperatures = result["heads"][0]["extruders"][index]["hotend"]["temperature"] + printer.extruders[index].updateTargetHotendTemperature(temperatures["target"]) + printer.extruders[index].updateHotendTemperature(temperatures["current"]) + + # TODO: Set active material + + try: + hotend_id = result["heads"][0]["extruders"][index]["hotend"]["id"] + except KeyError: + hotend_id = "" + printer.extruders[index].updateHotendID(hotend_id) + + else: + Logger.log("w", + "Got status code {status_code} while trying to get printer data".format(status_code = status_code))