mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-30 10:05:42 +08:00
Merge pull request #6155 from Ultimaker/CS-234_network_plugin_improvements
CS-234: Network plugin improvements
This commit is contained in:
commit
d123fcc132
@ -10,7 +10,6 @@ from UM import i18nCatalog
|
|||||||
from UM.Backend.Backend import BackendState
|
from UM.Backend.Backend import BackendState
|
||||||
from UM.FileHandler.FileHandler import FileHandler
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Version import Version
|
from UM.Version import Version
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
@ -20,6 +19,9 @@ from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
|||||||
from .CloudApiClient import CloudApiClient
|
from .CloudApiClient import CloudApiClient
|
||||||
from ..ExportFileJob import ExportFileJob
|
from ..ExportFileJob import ExportFileJob
|
||||||
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
||||||
|
from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage
|
||||||
|
from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage
|
||||||
|
from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage
|
||||||
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
||||||
from ..Models.Http.CloudClusterStatus import CloudClusterStatus
|
from ..Models.Http.CloudClusterStatus import CloudClusterStatus
|
||||||
from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
|
from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
|
||||||
@ -134,7 +136,6 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
## Set all the interface elements and texts for this output device.
|
## Set all the interface elements and texts for this output device.
|
||||||
def _setInterfaceElements(self) -> None:
|
def _setInterfaceElements(self) -> None:
|
||||||
self.setPriority(2) # Make sure we end up below the local networking and above 'save to file'.
|
self.setPriority(2) # Make sure we end up below the local networking and above 'save to file'.
|
||||||
self.setName(self._id)
|
|
||||||
self.setShortDescription(I18N_CATALOG.i18nc("@action:button", "Print via Cloud"))
|
self.setShortDescription(I18N_CATALOG.i18nc("@action:button", "Print via Cloud"))
|
||||||
self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print via Cloud"))
|
self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print via Cloud"))
|
||||||
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
|
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
|
||||||
@ -169,20 +170,18 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
|
|
||||||
# Show an error message if we're already sending a job.
|
# Show an error message if we're already sending a job.
|
||||||
if self._progress.visible:
|
if self._progress.visible:
|
||||||
return Message(
|
PrintJobUploadBlockedMessage().show()
|
||||||
text=I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
|
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Print error"),
|
|
||||||
lifetime=10
|
|
||||||
).show()
|
|
||||||
|
|
||||||
if self._uploaded_print_job:
|
|
||||||
# The mesh didn't change, let's not upload it again
|
|
||||||
self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Indicate we have started sending a job.
|
# Indicate we have started sending a job.
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
|
# The mesh didn't change, let's not upload it to the cloud again.
|
||||||
|
# Note that self.writeFinished is called in _onPrintUploadCompleted as well.
|
||||||
|
if self._uploaded_print_job:
|
||||||
|
self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted)
|
||||||
|
return
|
||||||
|
|
||||||
# Export the scene to the correct file type.
|
# Export the scene to the correct file type.
|
||||||
job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
|
job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
|
||||||
job.finished.connect(self._onPrintJobCreated)
|
job.finished.connect(self._onPrintJobCreated)
|
||||||
@ -216,29 +215,21 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
print_job = cast(CloudPrintJobResponse, self._uploaded_print_job)
|
print_job = cast(CloudPrintJobResponse, self._uploaded_print_job)
|
||||||
self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted)
|
self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted)
|
||||||
|
|
||||||
|
## Shows a message when the upload has succeeded
|
||||||
|
# \param response: The response from the cloud API.
|
||||||
|
def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
|
||||||
|
self._progress.hide()
|
||||||
|
PrintJobUploadSuccessMessage().show()
|
||||||
|
self.writeFinished.emit()
|
||||||
|
|
||||||
## Displays the given message if uploading the mesh has failed
|
## Displays the given message if uploading the mesh has failed
|
||||||
# \param message: The message to display.
|
# \param message: The message to display.
|
||||||
def _onUploadError(self, message: str = None) -> None:
|
def _onUploadError(self, message: str = None) -> None:
|
||||||
self._progress.hide()
|
self._progress.hide()
|
||||||
self._uploaded_print_job = None
|
self._uploaded_print_job = None
|
||||||
Message(
|
PrintJobUploadErrorMessage(message).show()
|
||||||
text=message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
|
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Cloud error"),
|
|
||||||
lifetime=10
|
|
||||||
).show()
|
|
||||||
self.writeError.emit()
|
self.writeError.emit()
|
||||||
|
|
||||||
## Shows a message when the upload has succeeded
|
|
||||||
# \param response: The response from the cloud API.
|
|
||||||
def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
|
|
||||||
self._progress.hide()
|
|
||||||
Message(
|
|
||||||
text=I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Data Sent"),
|
|
||||||
lifetime=5
|
|
||||||
).show()
|
|
||||||
self.writeFinished.emit()
|
|
||||||
|
|
||||||
## Whether the printer that this output device represents supports print job actions via the cloud.
|
## Whether the printer that this output device represents supports print job actions via the cloud.
|
||||||
@pyqtProperty(bool, notify=_clusterPrintersChanged)
|
@pyqtProperty(bool, notify=_clusterPrintersChanged)
|
||||||
def supportsPrintJobActions(self) -> bool:
|
def supportsPrintJobActions(self) -> bool:
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
# Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from UM import i18nCatalog
|
||||||
|
from UM.Message import Message
|
||||||
|
|
||||||
|
|
||||||
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
## Message shown when uploading a print job to a cluster is blocked because another upload is already in progress.
|
||||||
|
class PrintJobUploadBlockedMessage(Message):
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(
|
||||||
|
text = I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
|
||||||
|
title = I18N_CATALOG.i18nc("@info:title", "Print error"),
|
||||||
|
lifetime = 10
|
||||||
|
)
|
@ -0,0 +1,18 @@
|
|||||||
|
# Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from UM import i18nCatalog
|
||||||
|
from UM.Message import Message
|
||||||
|
|
||||||
|
|
||||||
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
## Message shown when uploading a print job to a cluster failed.
|
||||||
|
class PrintJobUploadErrorMessage(Message):
|
||||||
|
|
||||||
|
def __init__(self, message: str = None) -> None:
|
||||||
|
super().__init__(
|
||||||
|
text = message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
|
||||||
|
title = I18N_CATALOG.i18nc("@info:title", "Network error"),
|
||||||
|
lifetime = 10
|
||||||
|
)
|
@ -0,0 +1,18 @@
|
|||||||
|
# Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from UM import i18nCatalog
|
||||||
|
from UM.Message import Message
|
||||||
|
|
||||||
|
|
||||||
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
## Message shown when uploading a print job to a cluster succeeded.
|
||||||
|
class PrintJobUploadSuccessMessage(Message):
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(
|
||||||
|
text = I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
||||||
|
title = I18N_CATALOG.i18nc("@info:title", "Data Sent"),
|
||||||
|
lifetime = 5
|
||||||
|
)
|
0
plugins/UM3NetworkPrinting/src/Messages/__init__.py
Normal file
0
plugins/UM3NetworkPrinting/src/Messages/__init__.py
Normal file
@ -39,7 +39,7 @@ class ClusterApiClient:
|
|||||||
## Get printer system information.
|
## Get printer system information.
|
||||||
# \param on_finished: The callback in case the response is successful.
|
# \param on_finished: The callback in case the response is successful.
|
||||||
def getSystem(self, on_finished: Callable) -> None:
|
def getSystem(self, on_finished: Callable) -> None:
|
||||||
url = "{}/system/".format(self.PRINTER_API_PREFIX)
|
url = "{}/system".format(self.PRINTER_API_PREFIX)
|
||||||
reply = self._manager.get(self._createEmptyRequest(url))
|
reply = self._manager.get(self._createEmptyRequest(url))
|
||||||
self._addCallback(reply, on_finished, PrinterSystemStatus)
|
self._addCallback(reply, on_finished, PrinterSystemStatus)
|
||||||
|
|
||||||
@ -59,17 +59,17 @@ class ClusterApiClient:
|
|||||||
|
|
||||||
## Move a print job to the top of the queue.
|
## Move a print job to the top of the queue.
|
||||||
def movePrintJobToTop(self, print_job_uuid: str) -> None:
|
def movePrintJobToTop(self, print_job_uuid: str) -> None:
|
||||||
url = "{}/print_jobs/{}/action/move".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
url = "{}/print_jobs/{}/action/move/".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
||||||
self._manager.post(self._createEmptyRequest(url), json.dumps({"to_position": 0, "list": "queued"}).encode())
|
self._manager.post(self._createEmptyRequest(url), json.dumps({"to_position": 0, "list": "queued"}).encode())
|
||||||
|
|
||||||
## Delete a print job from the queue.
|
## Delete a print job from the queue.
|
||||||
def deletePrintJob(self, print_job_uuid: str) -> None:
|
def deletePrintJob(self, print_job_uuid: str) -> None:
|
||||||
url = "{}/print_jobs/{}".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
url = "{}/print_jobs/{}/".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
||||||
self._manager.deleteResource(self._createEmptyRequest(url))
|
self._manager.deleteResource(self._createEmptyRequest(url))
|
||||||
|
|
||||||
## Set the state of a print job.
|
## Set the state of a print job.
|
||||||
def setPrintJobState(self, print_job_uuid: str, state: str) -> None:
|
def setPrintJobState(self, print_job_uuid: str, state: str) -> None:
|
||||||
url = "{}/print_jobs/{}/action".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
url = "{}/print_jobs/{}/action/".format(self.CLUSTER_API_PREFIX, print_job_uuid)
|
||||||
# We rewrite 'resume' to 'print' here because we are using the old print job action endpoints.
|
# We rewrite 'resume' to 'print' here because we are using the old print job action endpoints.
|
||||||
action = "print" if state == "resume" else state
|
action = "print" if state == "resume" else state
|
||||||
self._manager.put(self._createEmptyRequest(url), json.dumps({"action": action}).encode())
|
self._manager.put(self._createEmptyRequest(url), json.dumps({"action": action}).encode())
|
||||||
@ -111,14 +111,17 @@ class ClusterApiClient:
|
|||||||
on_finished: Union[Callable[[ClusterApiClientModel], Any],
|
on_finished: Union[Callable[[ClusterApiClientModel], Any],
|
||||||
Callable[[List[ClusterApiClientModel]], Any]],
|
Callable[[List[ClusterApiClientModel]], Any]],
|
||||||
model_class: Type[ClusterApiClientModel]) -> None:
|
model_class: Type[ClusterApiClientModel]) -> None:
|
||||||
if isinstance(response, list):
|
try:
|
||||||
results = [model_class(**c) for c in response] # type: List[ClusterApiClientModel]
|
if isinstance(response, list):
|
||||||
on_finished_list = cast(Callable[[List[ClusterApiClientModel]], Any], on_finished)
|
results = [model_class(**c) for c in response] # type: List[ClusterApiClientModel]
|
||||||
on_finished_list(results)
|
on_finished_list = cast(Callable[[List[ClusterApiClientModel]], Any], on_finished)
|
||||||
else:
|
on_finished_list(results)
|
||||||
result = model_class(**response) # type: ClusterApiClientModel
|
else:
|
||||||
on_finished_item = cast(Callable[[ClusterApiClientModel], Any], on_finished)
|
result = model_class(**response) # type: ClusterApiClientModel
|
||||||
on_finished_item(result)
|
on_finished_item = cast(Callable[[ClusterApiClientModel], Any], on_finished)
|
||||||
|
on_finished_item(result)
|
||||||
|
except JSONDecodeError:
|
||||||
|
Logger.log("e", "Could not parse response from network: %s", str(response))
|
||||||
|
|
||||||
## Creates a callback function so that it includes the parsing of the response into the correct model.
|
## Creates a callback function so that it includes the parsing of the response into the correct model.
|
||||||
# The callback is added to the 'finished' signal of the reply.
|
# The callback is added to the 'finished' signal of the reply.
|
||||||
|
@ -7,7 +7,6 @@ from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty
|
|||||||
from PyQt5.QtNetwork import QNetworkReply
|
from PyQt5.QtNetwork import QNetworkReply
|
||||||
|
|
||||||
from UM.FileHandler.FileHandler import FileHandler
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
from UM.Message import Message
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
||||||
@ -17,6 +16,9 @@ from .ClusterApiClient import ClusterApiClient
|
|||||||
from ..ExportFileJob import ExportFileJob
|
from ..ExportFileJob import ExportFileJob
|
||||||
from ..SendMaterialJob import SendMaterialJob
|
from ..SendMaterialJob import SendMaterialJob
|
||||||
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
||||||
|
from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage
|
||||||
|
from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage
|
||||||
|
from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage
|
||||||
|
|
||||||
|
|
||||||
I18N_CATALOG = i18nCatalog("cura")
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
@ -46,7 +48,6 @@ class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
## Set all the interface elements and texts for this output device.
|
## Set all the interface elements and texts for this output device.
|
||||||
def _setInterfaceElements(self) -> None:
|
def _setInterfaceElements(self) -> None:
|
||||||
self.setPriority(3) # Make sure the output device gets selected above local file output
|
self.setPriority(3) # Make sure the output device gets selected above local file output
|
||||||
self.setName(self._id)
|
|
||||||
self.setShortDescription(I18N_CATALOG.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
|
self.setShortDescription(I18N_CATALOG.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
|
||||||
self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print over network"))
|
self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print over network"))
|
||||||
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected over the network"))
|
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected over the network"))
|
||||||
@ -111,11 +112,8 @@ class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
|
|
||||||
# Show an error message if we're already sending a job.
|
# Show an error message if we're already sending a job.
|
||||||
if self._progress.visible:
|
if self._progress.visible:
|
||||||
return Message(
|
PrintJobUploadBlockedMessage().show()
|
||||||
text=I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
|
return
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Print error"),
|
|
||||||
lifetime=10
|
|
||||||
).show()
|
|
||||||
|
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
@ -147,22 +145,14 @@ class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
## Handler for when the print job was fully uploaded to the cluster.
|
## Handler for when the print job was fully uploaded to the cluster.
|
||||||
def _onPrintUploadCompleted(self, _: QNetworkReply) -> None:
|
def _onPrintUploadCompleted(self, _: QNetworkReply) -> None:
|
||||||
self._progress.hide()
|
self._progress.hide()
|
||||||
Message(
|
PrintJobUploadSuccessMessage().show()
|
||||||
text=I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Data Sent"),
|
|
||||||
lifetime=5
|
|
||||||
).show()
|
|
||||||
self.writeFinished.emit()
|
self.writeFinished.emit()
|
||||||
|
|
||||||
## Displays the given message if uploading the mesh has failed
|
## Displays the given message if uploading the mesh has failed
|
||||||
# \param message: The message to display.
|
# \param message: The message to display.
|
||||||
def _onUploadError(self, message: str = None) -> None:
|
def _onUploadError(self, message: str = None) -> None:
|
||||||
self._progress.hide()
|
self._progress.hide()
|
||||||
Message(
|
PrintJobUploadErrorMessage(message).show()
|
||||||
text=message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
|
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Network error"),
|
|
||||||
lifetime=10
|
|
||||||
).show()
|
|
||||||
self.writeError.emit()
|
self.writeError.emit()
|
||||||
|
|
||||||
## Download all the images from the cluster and load their data in the print job models.
|
## Download all the images from the cluster and load their data in the print job models.
|
||||||
|
@ -14,7 +14,7 @@ from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
|||||||
|
|
||||||
from .Utils import formatTimeCompleted, formatDateCompleted
|
from .Utils import formatTimeCompleted, formatDateCompleted
|
||||||
from .ClusterOutputController import ClusterOutputController
|
from .ClusterOutputController import ClusterOutputController
|
||||||
from .PrintJobUploadProgressMessage import PrintJobUploadProgressMessage
|
from plugins.UM3NetworkPrinting.src.Messages.PrintJobUploadProgressMessage import PrintJobUploadProgressMessage
|
||||||
from .Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
from .Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
from .Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
|
from .Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
|
||||||
from .Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
|
from .Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
|
||||||
@ -45,6 +45,9 @@ class UltimakerNetworkedPrinterOutputDevice(NetworkedPrinterOutputDevice):
|
|||||||
|
|
||||||
# Trigger the printersChanged signal when the private signal is triggered.
|
# Trigger the printersChanged signal when the private signal is triggered.
|
||||||
self.printersChanged.connect(self._clusterPrintersChanged)
|
self.printersChanged.connect(self._clusterPrintersChanged)
|
||||||
|
|
||||||
|
# Set the display name from the properties
|
||||||
|
self.setName(self.getProperty("name"))
|
||||||
|
|
||||||
# Keeps track of all printers in the cluster.
|
# Keeps track of all printers in the cluster.
|
||||||
self._printers = [] # type: List[PrinterOutputModel]
|
self._printers = [] # type: List[PrinterOutputModel]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user