mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 07:27:29 -06:00
Fixes
This commit is contained in:
parent
9e4c71cce3
commit
bfca117bff
6 changed files with 119 additions and 110 deletions
|
@ -9,6 +9,7 @@ from PyQt5.QtGui import QDesktopServices
|
||||||
from UM import i18nCatalog
|
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.FileHandler.WriteFileJob import WriteFileJob
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
@ -16,6 +17,7 @@ from UM.Version import Version
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
||||||
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||||
|
from plugins.UM3NetworkPrinting.src.ExportFileJob import ExportFileJob
|
||||||
|
|
||||||
from .CloudApiClient import CloudApiClient
|
from .CloudApiClient import CloudApiClient
|
||||||
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
||||||
|
@ -93,6 +95,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
self._received_print_jobs = None # type: Optional[List[ClusterPrintJobStatus]]
|
self._received_print_jobs = None # type: Optional[List[ClusterPrintJobStatus]]
|
||||||
|
|
||||||
# Reference to the uploaded print job / mesh
|
# Reference to the uploaded print job / mesh
|
||||||
|
# We do this to prevent re-uploading the same file multiple times.
|
||||||
self._tool_path = None # type: Optional[bytes]
|
self._tool_path = None # type: Optional[bytes]
|
||||||
self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse]
|
self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse]
|
||||||
|
|
||||||
|
@ -129,7 +132,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
## 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.setName(self._id)
|
||||||
|
@ -137,6 +140,32 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
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"))
|
||||||
|
|
||||||
|
## Called when the network data should be updated.
|
||||||
|
def _update(self) -> None:
|
||||||
|
super()._update()
|
||||||
|
if self._last_request_time and time() - self._last_request_time < self.CHECK_CLUSTER_INTERVAL:
|
||||||
|
return # Avoid calling the cloud too often
|
||||||
|
|
||||||
|
Logger.log("d", "Updating: %s - %s >= %s", time(), self._last_request_time, self.CHECK_CLUSTER_INTERVAL)
|
||||||
|
if self._account.isLoggedIn:
|
||||||
|
self.setAuthenticationState(AuthState.Authenticated)
|
||||||
|
self._last_request_time = time()
|
||||||
|
self._api.getClusterStatus(self.key, self._onStatusCallFinished)
|
||||||
|
else:
|
||||||
|
self.setAuthenticationState(AuthState.NotAuthenticated)
|
||||||
|
|
||||||
|
## Method called when HTTP request to status endpoint is finished.
|
||||||
|
# Contains both printers and print jobs statuses in a single response.
|
||||||
|
def _onStatusCallFinished(self, status: CloudClusterStatus) -> None:
|
||||||
|
# Update all data from the cluster.
|
||||||
|
self._last_response_time = time()
|
||||||
|
if self._received_printers != status.printers:
|
||||||
|
self._received_printers = status.printers
|
||||||
|
self._updatePrinters(status.printers)
|
||||||
|
if status.print_jobs != self._received_print_jobs:
|
||||||
|
self._received_print_jobs = status.print_jobs
|
||||||
|
self._updatePrintJobs(status.print_jobs)
|
||||||
|
|
||||||
## Called when Cura requests an output device to receive a (G-code) file.
|
## Called when Cura requests an output device to receive a (G-code) file.
|
||||||
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
||||||
file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
||||||
|
@ -159,54 +188,29 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
# Indicate we have started sending a job.
|
# Indicate we have started sending a job.
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
|
# Export the scene to the correct file type.
|
||||||
if not mesh_format.is_valid:
|
job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
|
||||||
Logger.log("e", "Missing file or mesh writer!")
|
job.finished.connect(self._onPrintJobCreated)
|
||||||
return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
job.start()
|
||||||
|
|
||||||
# TODO: use stream just like the network output device
|
## Handler for when the print job was created locally.
|
||||||
mesh = mesh_format.getBytes(nodes)
|
# It can now be sent over the cloud.
|
||||||
self._tool_path = mesh
|
def _onPrintJobCreated(self, job: WriteFileJob) -> None:
|
||||||
|
self._progress.show()
|
||||||
|
self._tool_path = job.getOutput()
|
||||||
request = CloudPrintJobUploadRequest(
|
request = CloudPrintJobUploadRequest(
|
||||||
job_name=file_name or mesh_format.file_extension,
|
job_name=job.getFileName(),
|
||||||
file_size=len(mesh),
|
file_size=len(self._tool_path),
|
||||||
content_type=mesh_format.mime_type,
|
content_type=job.getMimeType(),
|
||||||
)
|
)
|
||||||
self._api.requestUpload(request, self._onPrintJobCreated)
|
self._api.requestUpload(request, self._uploadPrintJob)
|
||||||
|
|
||||||
## Called when the network data should be updated.
|
|
||||||
def _update(self) -> None:
|
|
||||||
super()._update()
|
|
||||||
if self._last_request_time and time() - self._last_request_time < self.CHECK_CLUSTER_INTERVAL:
|
|
||||||
return # Avoid calling the cloud too often
|
|
||||||
|
|
||||||
Logger.log("d", "Updating: %s - %s >= %s", time(), self._last_request_time, self.CHECK_CLUSTER_INTERVAL)
|
|
||||||
if self._account.isLoggedIn:
|
|
||||||
self.setAuthenticationState(AuthState.Authenticated)
|
|
||||||
self._last_request_time = time()
|
|
||||||
self._api.getClusterStatus(self.key, self._onStatusCallFinished)
|
|
||||||
else:
|
|
||||||
self.setAuthenticationState(AuthState.NotAuthenticated)
|
|
||||||
|
|
||||||
## Method called when HTTP request to status endpoint is finished.
|
|
||||||
# Contains both printers and print jobs statuses in a single response.
|
|
||||||
def _onStatusCallFinished(self, status: CloudClusterStatus) -> None:
|
|
||||||
# Update all data from the cluster.
|
|
||||||
self._last_response_time = time()
|
|
||||||
if self._received_printers != status.printers:
|
|
||||||
self._received_printers = status.printers
|
|
||||||
self._updatePrinters(status.printers)
|
|
||||||
if status.print_jobs != self._received_print_jobs:
|
|
||||||
self._received_print_jobs = status.print_jobs
|
|
||||||
self._updatePrintJobs(status.print_jobs)
|
|
||||||
|
|
||||||
## Uploads the mesh when the print job was registered with the cloud API.
|
## Uploads the mesh when the print job was registered with the cloud API.
|
||||||
# \param job_response: The response received from the cloud API.
|
# \param job_response: The response received from the cloud API.
|
||||||
def _onPrintJobCreated(self, job_response: CloudPrintJobResponse) -> None:
|
def _uploadPrintJob(self, job_response: CloudPrintJobResponse) -> None:
|
||||||
self._progress.show()
|
self._progress.show()
|
||||||
self._uploaded_print_job = job_response
|
self._uploaded_print_job = job_response # store the last uploaded job to prevent re-upload of the same file
|
||||||
tool_path = cast(bytes, self._tool_path)
|
self._api.uploadToolPath(job_response, self._tool_path, self._onPrintJobUploaded, self._progress.update,
|
||||||
self._api.uploadToolPath(job_response, tool_path, self._onPrintJobUploaded, self._progress.update,
|
|
||||||
self._onUploadError)
|
self._onUploadError)
|
||||||
|
|
||||||
## Requests the print to be sent to the printer when we finished uploading the mesh.
|
## Requests the print to be sent to the printer when we finished uploading the mesh.
|
||||||
|
|
|
@ -40,6 +40,7 @@ class CloudOutputDeviceManager:
|
||||||
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
|
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
|
||||||
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
|
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
|
||||||
self._api = CloudApiClient(self._account, self._onApiError)
|
self._api = CloudApiClient(self._account, self._onApiError)
|
||||||
|
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||||
|
|
||||||
# Create a timer to update the remote cluster list
|
# Create a timer to update the remote cluster list
|
||||||
self._update_timer = QTimer()
|
self._update_timer = QTimer()
|
||||||
|
@ -53,17 +54,22 @@ class CloudOutputDeviceManager:
|
||||||
def start(self):
|
def start(self):
|
||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
if not self._account.isLoggedIn:
|
||||||
|
return
|
||||||
|
self._running = True
|
||||||
|
if not self._update_timer.isActive():
|
||||||
|
self._update_timer.start()
|
||||||
self._update_timer.timeout.connect(self._getRemoteClusters)
|
self._update_timer.timeout.connect(self._getRemoteClusters)
|
||||||
self._onLoginStateChanged(is_logged_in=self._account.isLoggedIn)
|
|
||||||
|
|
||||||
## Stops running the cloud output device manager.
|
## Stops running the cloud output device manager.
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if not self._running:
|
if not self._running:
|
||||||
return
|
return
|
||||||
self._account.loginStateChanged.disconnect(self._onLoginStateChanged)
|
self._running = False
|
||||||
|
if self._update_timer.isActive():
|
||||||
|
self._update_timer.stop()
|
||||||
|
self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices.
|
||||||
self._update_timer.timeout.disconnect(self._getRemoteClusters)
|
self._update_timer.timeout.disconnect(self._getRemoteClusters)
|
||||||
self._onLoginStateChanged(is_logged_in=False)
|
|
||||||
|
|
||||||
## Force refreshing connections.
|
## Force refreshing connections.
|
||||||
def refreshConnections(self) -> None:
|
def refreshConnections(self) -> None:
|
||||||
|
@ -72,17 +78,13 @@ class CloudOutputDeviceManager:
|
||||||
## Called when the uses logs in or out
|
## Called when the uses logs in or out
|
||||||
def _onLoginStateChanged(self, is_logged_in: bool) -> None:
|
def _onLoginStateChanged(self, is_logged_in: bool) -> None:
|
||||||
if is_logged_in:
|
if is_logged_in:
|
||||||
if not self._update_timer.isActive():
|
self.start()
|
||||||
self._update_timer.start()
|
|
||||||
self._getRemoteClusters()
|
|
||||||
else:
|
else:
|
||||||
if self._update_timer.isActive():
|
self.stop()
|
||||||
self._update_timer.stop()
|
|
||||||
# Notify that all clusters have disappeared
|
|
||||||
self._onGetRemoteClustersFinished([])
|
|
||||||
|
|
||||||
## Gets all remote clusters from the API.
|
## Gets all remote clusters from the API.
|
||||||
def _getRemoteClusters(self) -> None:
|
def _getRemoteClusters(self) -> None:
|
||||||
|
print("getRemoteClusters")
|
||||||
self._api.getClusters(self._onGetRemoteClustersFinished)
|
self._api.getClusters(self._onGetRemoteClustersFinished)
|
||||||
|
|
||||||
## Callback for when the request for getting the clusters is finished.
|
## Callback for when the request for getting the clusters is finished.
|
||||||
|
@ -113,6 +115,8 @@ class CloudOutputDeviceManager:
|
||||||
keys = self._remote_clusters.keys()
|
keys = self._remote_clusters.keys()
|
||||||
removed_devices = [cluster for cluster in self._remote_clusters.values() if cluster.key not in keys]
|
removed_devices = [cluster for cluster in self._remote_clusters.values() if cluster.key not in keys]
|
||||||
for device in removed_devices:
|
for device in removed_devices:
|
||||||
|
device.disconnect()
|
||||||
|
device.close()
|
||||||
CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(device.key)
|
CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(device.key)
|
||||||
discovery.removeDiscoveredPrinter(device.key)
|
discovery.removeDiscoveredPrinter(device.key)
|
||||||
|
|
||||||
|
@ -127,11 +131,13 @@ class CloudOutputDeviceManager:
|
||||||
return
|
return
|
||||||
|
|
||||||
# The newly added machine is automatically activated.
|
# The newly added machine is automatically activated.
|
||||||
CuraApplication.getInstance().getMachineManager().addMachine(device.printerType,
|
machine_manager = CuraApplication.getInstance().getMachineManager()
|
||||||
device.clusterData.friendly_name)
|
machine_manager.addMachine(device.printerType, device.clusterData.friendly_name)
|
||||||
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
||||||
if active_machine:
|
if not active_machine:
|
||||||
self._connectToOutputDevice(device, active_machine)
|
return
|
||||||
|
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
||||||
|
self._connectToOutputDevice(device, active_machine)
|
||||||
|
|
||||||
## Callback for when the active machine was changed by the user or a new remote cluster was found.
|
## Callback for when the active machine was changed by the user or a new remote cluster was found.
|
||||||
def _connectToActiveMachine(self) -> None:
|
def _connectToActiveMachine(self) -> None:
|
||||||
|
@ -150,28 +156,25 @@ class CloudOutputDeviceManager:
|
||||||
device = self._remote_clusters[stored_cluster_id]
|
device = self._remote_clusters[stored_cluster_id]
|
||||||
self._connectToOutputDevice(device, active_machine)
|
self._connectToOutputDevice(device, active_machine)
|
||||||
Logger.log("d", "Device connected by metadata cluster ID %s", stored_cluster_id)
|
Logger.log("d", "Device connected by metadata cluster ID %s", stored_cluster_id)
|
||||||
else:
|
# else:
|
||||||
self._connectByNetworkKey(active_machine)
|
# self._connectByNetworkKey(active_machine)
|
||||||
|
|
||||||
## Tries to match the local network key to the cloud cluster host name.
|
## Tries to match the local network key to the cloud cluster host name.
|
||||||
def _connectByNetworkKey(self, active_machine: GlobalStack) -> None:
|
def _connectByNetworkKey(self, active_machine: GlobalStack) -> None:
|
||||||
# Check if the active printer has a local network connection and match this key to the remote cluster.
|
|
||||||
local_network_key = active_machine.getMetaDataEntry("um_network_key")
|
local_network_key = active_machine.getMetaDataEntry("um_network_key")
|
||||||
if not local_network_key:
|
if not local_network_key:
|
||||||
return
|
return
|
||||||
|
|
||||||
device = next((c for c in self._remote_clusters.values() if c.matchesNetworkKey(local_network_key)), None)
|
device = next((c for c in self._remote_clusters.values() if c.matchesNetworkKey(local_network_key)), None)
|
||||||
if not device:
|
if not device:
|
||||||
return
|
return
|
||||||
|
|
||||||
Logger.log("i", "Found cluster %s with network key %s", device, local_network_key)
|
Logger.log("i", "Found cluster %s with network key %s", device, local_network_key)
|
||||||
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
||||||
self._connectToOutputDevice(device, active_machine)
|
self._connectToOutputDevice(device, active_machine)
|
||||||
|
|
||||||
## Connects to an output device and makes sure it is registered in the output device manager.
|
## Connects to an output device and makes sure it is registered in the output device manager.
|
||||||
def _connectToOutputDevice(self, device: CloudOutputDevice, active_machine: GlobalStack) -> None:
|
@staticmethod
|
||||||
|
def _connectToOutputDevice(device: CloudOutputDevice, active_machine: GlobalStack) -> None:
|
||||||
device.connect()
|
device.connect()
|
||||||
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
|
||||||
active_machine.addConfiguredConnectionType(device.connectionType.value)
|
active_machine.addConfiguredConnectionType(device.connectionType.value)
|
||||||
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
|
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
|
||||||
|
|
||||||
|
|
39
plugins/UM3NetworkPrinting/src/ExportFileJob.py
Normal file
39
plugins/UM3NetworkPrinting/src/ExportFileJob.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
|
from UM.FileHandler.WriteFileJob import WriteFileJob
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
|
from .MeshFormatHandler import MeshFormatHandler
|
||||||
|
|
||||||
|
|
||||||
|
## Job that exports the build plate to the correct file format for the target cluster.
|
||||||
|
class ExportFileJob(WriteFileJob):
|
||||||
|
|
||||||
|
def __init__(self, file_handler: FileHandler, nodes: List[SceneNode], firmware_version: str) -> None:
|
||||||
|
|
||||||
|
self._mesh_format_handler = MeshFormatHandler(file_handler, firmware_version)
|
||||||
|
if not self._mesh_format_handler.is_valid:
|
||||||
|
Logger.log("e", "Missing file or mesh writer!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Determine the filename.
|
||||||
|
job_name = CuraApplication.getInstance().getPrintInformation().jobName
|
||||||
|
extension = self._mesh_format_handler.preferred_format.get("extension", "")
|
||||||
|
self.setFileName(f"{job_name}.{extension}")
|
||||||
|
|
||||||
|
super().__init__(self._mesh_format_handler.writer, self._mesh_format_handler.createStream(), nodes,
|
||||||
|
self._mesh_format_handler.file_mode)
|
||||||
|
|
||||||
|
## Get the mime type of the selected export file type.
|
||||||
|
def getMimeType(self) -> str:
|
||||||
|
return self._mesh_format_handler.mime_type
|
||||||
|
|
||||||
|
## Get the job result as bytes as that is what we need to upload to the cluster.
|
||||||
|
def getOutput(self) -> bytes:
|
||||||
|
output = self.getStream().getvalue()
|
||||||
|
if isinstance(output, str):
|
||||||
|
output = output.encode("utf-8")
|
||||||
|
return output
|
|
@ -15,6 +15,7 @@ from UM.Scene.SceneNode import SceneNode
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
||||||
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||||
|
from plugins.UM3NetworkPrinting.src.ExportFileJob import ExportFileJob
|
||||||
|
|
||||||
from .ClusterApiClient import ClusterApiClient
|
from .ClusterApiClient import ClusterApiClient
|
||||||
from ..MeshFormatHandler import MeshFormatHandler
|
from ..MeshFormatHandler import MeshFormatHandler
|
||||||
|
@ -46,7 +47,6 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
self._setInterfaceElements()
|
self._setInterfaceElements()
|
||||||
self._active_camera_url = QUrl() # type: QUrl
|
self._active_camera_url = QUrl() # type: QUrl
|
||||||
|
|
||||||
|
|
||||||
## 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
|
||||||
|
@ -146,21 +146,8 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
# Make sure the printer is aware of all new materials as the new print job might contain one.
|
# Make sure the printer is aware of all new materials as the new print job might contain one.
|
||||||
self.sendMaterialProfiles()
|
self.sendMaterialProfiles()
|
||||||
|
|
||||||
# Detect the correct export format depending on printer type and firmware version.
|
# Export the scene to the correct file type.
|
||||||
mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
|
job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
|
||||||
if not mesh_format.is_valid:
|
|
||||||
Logger.log("e", "Missing file or mesh writer!")
|
|
||||||
return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
|
||||||
|
|
||||||
# Determine the filename.
|
|
||||||
job_name = CuraApplication.getInstance().getPrintInformation().jobName
|
|
||||||
extension = mesh_format.preferred_format.get("extension", "")
|
|
||||||
file_name = f"{job_name}.{extension}"
|
|
||||||
|
|
||||||
# Export the file.
|
|
||||||
stream = mesh_format.createStream()
|
|
||||||
job = WriteFileJob(writer=mesh_format.writer, stream=stream, data=nodes, mode=mesh_format.file_mode)
|
|
||||||
job.setFileName(file_name)
|
|
||||||
job.finished.connect(self._onPrintJobCreated)
|
job.finished.connect(self._onPrintJobCreated)
|
||||||
job.start()
|
job.start()
|
||||||
|
|
||||||
|
@ -168,14 +155,10 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
# It can now be sent over the network.
|
# It can now be sent over the network.
|
||||||
def _onPrintJobCreated(self, job: WriteFileJob) -> None:
|
def _onPrintJobCreated(self, job: WriteFileJob) -> None:
|
||||||
self._progress.show()
|
self._progress.show()
|
||||||
# TODO: extract multi-part stuff
|
parts = [
|
||||||
parts = []
|
self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"),
|
||||||
parts.append(self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"))
|
self._createFormPart("name=\"file\"; filename=\"%s\"" % job.getFileName(), job.getOutput())
|
||||||
output = job.getStream().getvalue()
|
]
|
||||||
if isinstance(output, str):
|
|
||||||
# Ensure that our output is bytes
|
|
||||||
output = output.encode("utf-8")
|
|
||||||
parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % job.getFileName(), output))
|
|
||||||
self.postFormWithParts("/cluster-api/v1/print_jobs/", parts, on_finished=self._onPrintUploadCompleted,
|
self.postFormWithParts("/cluster-api/v1/print_jobs/", parts, on_finished=self._onPrintUploadCompleted,
|
||||||
on_progress=self._onPrintJobUploadProgress)
|
on_progress=self._onPrintJobUploadProgress)
|
||||||
|
|
||||||
|
|
|
@ -118,8 +118,6 @@ class NetworkOutputDeviceManager:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _connectToOutputDevice(device: PrinterOutputDevice, active_machine: GlobalStack) -> None:
|
def _connectToOutputDevice(device: PrinterOutputDevice, active_machine: GlobalStack) -> None:
|
||||||
device.connect()
|
device.connect()
|
||||||
active_machine.setMetaDataEntry("um_network_key", device.key)
|
|
||||||
active_machine.setMetaDataEntry("group_name", device.name)
|
|
||||||
active_machine.addConfiguredConnectionType(device.connectionType.value)
|
active_machine.addConfiguredConnectionType(device.connectionType.value)
|
||||||
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
|
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
|
||||||
|
|
||||||
|
@ -199,6 +197,8 @@ class NetworkOutputDeviceManager:
|
||||||
# The newly added machine is automatically activated.
|
# The newly added machine is automatically activated.
|
||||||
CuraApplication.getInstance().getMachineManager().addMachine(device.printerType, device.name)
|
CuraApplication.getInstance().getMachineManager().addMachine(device.printerType, device.name)
|
||||||
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
||||||
|
active_machine.setMetaDataEntry("um_network_key", device.key)
|
||||||
|
active_machine.setMetaDataEntry("group_name", device.name)
|
||||||
if active_machine:
|
if active_machine:
|
||||||
self._connectToOutputDevice(device, active_machine)
|
self._connectToOutputDevice(device, active_machine)
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@ from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
|
||||||
## This plugin handles the discovery and networking for Ultimaker 3D printers that support network and cloud printing.
|
## This plugin handles the discovery and networking for Ultimaker 3D printers that support network and cloud printing.
|
||||||
class UM3OutputDevicePlugin(OutputDevicePlugin):
|
class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
|
|
||||||
# cloudFlowIsPossible = Signal()
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -29,24 +27,6 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
# This ensures no output devices are still connected that do not belong to the new active machine.
|
# This ensures no output devices are still connected that do not belong to the new active machine.
|
||||||
CuraApplication.getInstance().globalContainerStackChanged.connect(self.refreshConnections)
|
CuraApplication.getInstance().globalContainerStackChanged.connect(self.refreshConnections)
|
||||||
|
|
||||||
# TODO: re-write cloud messaging
|
|
||||||
# self._account = self._application.getCuraAPI().account
|
|
||||||
|
|
||||||
# Check if cloud flow is possible when user logs in
|
|
||||||
# self._account.loginStateChanged.connect(self.checkCloudFlowIsPossible)
|
|
||||||
|
|
||||||
# Check if cloud flow is possible when user switches machines
|
|
||||||
# self._application.globalContainerStackChanged.connect(self._onMachineSwitched)
|
|
||||||
|
|
||||||
# Listen for when cloud flow is possible
|
|
||||||
# self.cloudFlowIsPossible.connect(self._onCloudFlowPossible)
|
|
||||||
|
|
||||||
# self._start_cloud_flow_message = None # type: Optional[Message]
|
|
||||||
# self._cloud_flow_complete_message = None # type: Optional[Message]
|
|
||||||
|
|
||||||
# self._cloud_output_device_manager.addedCloudCluster.connect(self._onCloudPrintingConfigured)
|
|
||||||
# self._cloud_output_device_manager.removedCloudCluster.connect(self.checkCloudFlowIsPossible)
|
|
||||||
|
|
||||||
## Start looking for devices in the network and cloud.
|
## Start looking for devices in the network and cloud.
|
||||||
def start(self):
|
def start(self):
|
||||||
self._network_output_device_manager.start()
|
self._network_output_device_manager.start()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue