mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 07:27:29 -06:00
STAR-322: Extracting models to be able for converting themselves
This commit is contained in:
parent
163226f940
commit
b693b9d98f
20 changed files with 324 additions and 254 deletions
0
__init__.py
Normal file
0
__init__.py
Normal file
|
@ -9,10 +9,13 @@ from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from cura.API import Account
|
from cura.API import Account
|
||||||
from cura.NetworkClient import NetworkClient
|
from cura.NetworkClient import NetworkClient
|
||||||
from plugins.UM3NetworkPrinting.src.Models import BaseModel
|
from ..Models import BaseModel
|
||||||
from plugins.UM3NetworkPrinting.src.Cloud.Models import (
|
from .Models.CloudCluster import CloudCluster
|
||||||
CloudCluster, CloudErrorObject, CloudClusterStatus, CloudJobUploadRequest, CloudPrintResponse, CloudJobResponse
|
from .Models.CloudErrorObject import CloudErrorObject
|
||||||
)
|
from .Models.CloudClusterStatus import CloudClusterStatus
|
||||||
|
from .Models.CloudJobUploadRequest import CloudJobUploadRequest
|
||||||
|
from .Models.CloudPrintResponse import CloudPrintResponse
|
||||||
|
from .Models.CloudJobResponse import CloudJobResponse
|
||||||
|
|
||||||
|
|
||||||
## The cloud API client is responsible for handling the requests and responses from the cloud.
|
## The cloud API client is responsible for handling the requests and responses from the cloud.
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
import os
|
import os
|
||||||
from time import time
|
from time import time
|
||||||
from typing import List, Optional, Dict, Set
|
from typing import Dict, List, Optional, Set
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, QUrl, pyqtProperty, pyqtSlot
|
from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot
|
||||||
|
|
||||||
from UM import i18nCatalog
|
from UM import i18nCatalog
|
||||||
from UM.FileHandler.FileHandler import FileHandler
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
|
@ -12,18 +12,19 @@ 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
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
|
|
||||||
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
|
||||||
|
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
|
||||||
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||||
from plugins.UM3NetworkPrinting.src.Cloud.CloudApiClient import CloudApiClient
|
from ..MeshFormatHandler import MeshFormatHandler
|
||||||
from plugins.UM3NetworkPrinting.src.MeshFormatHandler import MeshFormatHandler
|
from ..UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
from plugins.UM3NetworkPrinting.src.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
from .CloudApiClient import CloudApiClient
|
||||||
from .Models import (
|
from .Models.CloudErrorObject import CloudErrorObject
|
||||||
CloudClusterPrinter, CloudClusterPrintJob, CloudJobUploadRequest, CloudJobResponse, CloudClusterStatus,
|
from .Models.CloudClusterStatus import CloudClusterStatus
|
||||||
CloudClusterPrinterConfigurationMaterial, CloudErrorObject,
|
from .Models.CloudJobUploadRequest import CloudJobUploadRequest
|
||||||
CloudPrintResponse
|
from .Models.CloudPrintResponse import CloudPrintResponse
|
||||||
)
|
from .Models.CloudJobResponse import CloudJobResponse
|
||||||
|
from .Models.CloudClusterPrinter import CloudClusterPrinter
|
||||||
|
from .Models.CloudClusterPrintJob import CloudClusterPrintJob
|
||||||
|
|
||||||
|
|
||||||
## Class that contains all the translations for this module.
|
## Class that contains all the translations for this module.
|
||||||
|
@ -180,80 +181,23 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
remote_printers = {p.uuid: p for p in printers} # type: Dict[str, CloudClusterPrinter]
|
remote_printers = {p.uuid: p for p in printers} # type: Dict[str, CloudClusterPrinter]
|
||||||
current_printers = {p.key: p for p in self._printers} # type: Dict[str, PrinterOutputModel]
|
current_printers = {p.key: p for p in self._printers} # type: Dict[str, PrinterOutputModel]
|
||||||
|
|
||||||
removed_printer_ids = set(current_printers).difference(remote_printers)
|
remote_printer_ids = set(remote_printers) # type: Set[str]
|
||||||
new_printer_ids = set(remote_printers).difference(current_printers)
|
current_printer_ids = set(current_printers) # type: Set[str]
|
||||||
updated_printer_ids = set(current_printers).intersection(remote_printers)
|
|
||||||
|
|
||||||
for printer_guid in removed_printer_ids:
|
for removed_printer_id in current_printer_ids.difference(remote_printer_ids):
|
||||||
self._printers.remove(current_printers[printer_guid])
|
removed_printer = current_printers[removed_printer_id]
|
||||||
|
self._printers.remove(removed_printer)
|
||||||
|
|
||||||
for printer_guid in new_printer_ids:
|
for new_printer_id in remote_printer_ids.difference(current_printer_ids):
|
||||||
self._addPrinter(remote_printers[printer_guid])
|
new_printer = remote_printers[new_printer_id]
|
||||||
|
controller = PrinterOutputController(self)
|
||||||
|
self._printers.append(new_printer.createOutputModel(controller))
|
||||||
|
|
||||||
for printer_guid in updated_printer_ids:
|
for updated_printer_guid in current_printer_ids.intersection(remote_printer_ids):
|
||||||
self._updatePrinter(current_printers[printer_guid], remote_printers[printer_guid])
|
remote_printers[updated_printer_guid].updateOutputModel(current_printers[updated_printer_guid])
|
||||||
|
|
||||||
self.clusterPrintersChanged.emit()
|
self.clusterPrintersChanged.emit()
|
||||||
|
|
||||||
def _addPrinter(self, printer: CloudClusterPrinter) -> None:
|
|
||||||
model = PrinterOutputModel(
|
|
||||||
PrinterOutputController(self), len(printer.configuration), firmware_version = printer.firmware_version
|
|
||||||
)
|
|
||||||
self._printers.append(model)
|
|
||||||
self._updatePrinter(model, printer)
|
|
||||||
|
|
||||||
def _updatePrinter(self, model: PrinterOutputModel, printer: CloudClusterPrinter) -> None:
|
|
||||||
model.updateKey(printer.uuid)
|
|
||||||
model.updateName(printer.friendly_name)
|
|
||||||
model.updateType(printer.machine_variant)
|
|
||||||
model.updateState(printer.status if printer.enabled else "disabled")
|
|
||||||
|
|
||||||
for index in range(0, len(printer.configuration)):
|
|
||||||
try:
|
|
||||||
extruder = model.extruders[index]
|
|
||||||
extruder_data = printer.configuration[index]
|
|
||||||
except IndexError:
|
|
||||||
break
|
|
||||||
|
|
||||||
extruder.updateHotendID(extruder_data.print_core_id)
|
|
||||||
|
|
||||||
if extruder.activeMaterial is None or extruder.activeMaterial.guid != extruder_data.material.guid:
|
|
||||||
material = self._createMaterialOutputModel(extruder_data.material)
|
|
||||||
extruder.updateActiveMaterial(material)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _createMaterialOutputModel(material: CloudClusterPrinterConfigurationMaterial) -> MaterialOutputModel:
|
|
||||||
material_manager = CuraApplication.getInstance().getMaterialManager()
|
|
||||||
material_group_list = material_manager.getMaterialGroupListByGUID(material.guid) or []
|
|
||||||
|
|
||||||
# Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
|
|
||||||
read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
|
|
||||||
non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
|
|
||||||
material_group = None
|
|
||||||
if read_only_material_group_list:
|
|
||||||
read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
|
|
||||||
material_group = read_only_material_group_list[0]
|
|
||||||
elif non_read_only_material_group_list:
|
|
||||||
non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
|
|
||||||
material_group = non_read_only_material_group_list[0]
|
|
||||||
|
|
||||||
if material_group:
|
|
||||||
container = material_group.root_material_node.getContainer()
|
|
||||||
color = container.getMetaDataEntry("color_code")
|
|
||||||
brand = container.getMetaDataEntry("brand")
|
|
||||||
material_type = container.getMetaDataEntry("material")
|
|
||||||
name = container.getName()
|
|
||||||
else:
|
|
||||||
Logger.log("w", "Unable to find material with guid {guid}. Using data as provided by cluster"
|
|
||||||
.format(guid = material.guid))
|
|
||||||
color = material.color
|
|
||||||
brand = material.brand
|
|
||||||
material_type = material.material
|
|
||||||
name = "Empty" if material.material == "empty" else "Unknown"
|
|
||||||
|
|
||||||
return MaterialOutputModel(guid = material.guid, type = material_type, brand = brand, color = color,
|
|
||||||
name = name)
|
|
||||||
|
|
||||||
def _updatePrintJobs(self, jobs: List[CloudClusterPrintJob]) -> None:
|
def _updatePrintJobs(self, jobs: List[CloudClusterPrintJob]) -> None:
|
||||||
remote_jobs = {j.uuid: j for j in jobs} # type: Dict[str, CloudClusterPrintJob]
|
remote_jobs = {j.uuid: j for j in jobs} # type: Dict[str, CloudClusterPrintJob]
|
||||||
current_jobs = {j.key: j for j in self._print_jobs} # type: Dict[str, UM3PrintJobOutputModel]
|
current_jobs = {j.key: j for j in self._print_jobs} # type: Dict[str, UM3PrintJobOutputModel]
|
||||||
|
@ -264,11 +208,11 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
for removed_job_id in current_job_ids.difference(remote_job_ids):
|
for removed_job_id in current_job_ids.difference(remote_job_ids):
|
||||||
self._print_jobs.remove(current_jobs[removed_job_id])
|
self._print_jobs.remove(current_jobs[removed_job_id])
|
||||||
|
|
||||||
for new_job_id in remote_job_ids.difference(current_jobs):
|
for new_job_id in remote_job_ids.difference(current_job_ids):
|
||||||
self._addPrintJob(remote_jobs[new_job_id])
|
self._addPrintJob(remote_jobs[new_job_id])
|
||||||
|
|
||||||
for updated_job_id in current_job_ids.intersection(remote_job_ids):
|
for updated_job_id in current_job_ids.intersection(remote_job_ids):
|
||||||
self._updateUM3PrintJobOutputModel(current_jobs[updated_job_id], remote_jobs[updated_job_id])
|
remote_jobs[updated_job_id].updateOutputModel(current_jobs[updated_job_id])
|
||||||
|
|
||||||
# We only have to update when jobs are added or removed
|
# We only have to update when jobs are added or removed
|
||||||
# updated jobs push their changes via their output model
|
# updated jobs push their changes via their output model
|
||||||
|
@ -282,16 +226,7 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
return Logger.log("w", "Missing printer %s for job %s in %s", job.printer_uuid, job.uuid,
|
return Logger.log("w", "Missing printer %s for job %s in %s", job.printer_uuid, job.uuid,
|
||||||
[p.key for p in self._printers])
|
[p.key for p in self._printers])
|
||||||
|
|
||||||
model = UM3PrintJobOutputModel(printer.getController(), job.uuid, job.name)
|
self._print_jobs.append(job.createOutputModel(printer))
|
||||||
model.updateAssignedPrinter(printer)
|
|
||||||
self._print_jobs.append(model)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _updateUM3PrintJobOutputModel(model: UM3PrintJobOutputModel, job: CloudClusterPrintJob) -> None:
|
|
||||||
model.updateTimeTotal(job.time_total)
|
|
||||||
model.updateTimeElapsed(job.time_elapsed)
|
|
||||||
model.updateOwner(job.owner)
|
|
||||||
model.updateState(job.status)
|
|
||||||
|
|
||||||
def _onPrintJobCreated(self, mesh: bytes, job_response: CloudJobResponse) -> None:
|
def _onPrintJobCreated(self, mesh: bytes, job_response: CloudJobResponse) -> None:
|
||||||
self._api.uploadMesh(job_response, mesh, self._onPrintJobUploaded, self._updateUploadProgress,
|
self._api.uploadMesh(job_response, mesh, self._onPrintJobUploaded, self._updateUploadProgress,
|
||||||
|
|
|
@ -8,9 +8,10 @@ from UM import i18nCatalog
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from plugins.UM3NetworkPrinting.src.Cloud.CloudApiClient import CloudApiClient
|
from .CloudApiClient import CloudApiClient
|
||||||
from .CloudOutputDevice import CloudOutputDevice
|
from .CloudOutputDevice import CloudOutputDevice
|
||||||
from .Models import CloudCluster, CloudErrorObject
|
from .Models.CloudCluster import CloudCluster
|
||||||
|
from .Models.CloudErrorObject import CloudErrorObject
|
||||||
|
|
||||||
|
|
||||||
## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
|
## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
from typing import List, Dict
|
|
||||||
|
|
||||||
from ..Models import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing errors generated by the cloud servers, according to the json-api standard.
|
|
||||||
class CloudErrorObject(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.id = None # type: str
|
|
||||||
self.code = None # type: str
|
|
||||||
self.http_status = None # type: str
|
|
||||||
self.title = None # type: str
|
|
||||||
self.detail = None # type: str
|
|
||||||
self.meta = None # type: Dict[str, any]
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a cloud connected cluster.
|
|
||||||
class CloudCluster(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.cluster_id = None # type: str
|
|
||||||
self.host_guid = None # type: str
|
|
||||||
self.host_name = None # type: str
|
|
||||||
self.host_version = None # type: str
|
|
||||||
self.status = None # type: str
|
|
||||||
self.is_online = None # type: bool
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
if not self.cluster_id:
|
|
||||||
raise ValueError("cluster_id is required on CloudCluster")
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a cloud cluster printer configuration
|
|
||||||
class CloudClusterPrinterConfigurationMaterial(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.guid = None # type: str
|
|
||||||
self.brand = None # type: str
|
|
||||||
self.color = None # type: str
|
|
||||||
self.material = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a cloud cluster printer configuration
|
|
||||||
class CloudClusterPrinterConfiguration(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.extruder_index = None # type: str
|
|
||||||
self.material = None # type: CloudClusterPrinterConfigurationMaterial
|
|
||||||
self.nozzle_diameter = None # type: str
|
|
||||||
self.print_core_id = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
if isinstance(self.material, dict):
|
|
||||||
self.material = CloudClusterPrinterConfigurationMaterial(**self.material)
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a cluster printer
|
|
||||||
class CloudClusterPrinter(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.configuration = [] # type: List[CloudClusterPrinterConfiguration]
|
|
||||||
self.enabled = None # type: str
|
|
||||||
self.firmware_version = None # type: str
|
|
||||||
self.friendly_name = None # type: str
|
|
||||||
self.ip_address = None # type: str
|
|
||||||
self.machine_variant = None # type: str
|
|
||||||
self.status = None # type: str
|
|
||||||
self.unique_name = None # type: str
|
|
||||||
self.uuid = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.configuration = [CloudClusterPrinterConfiguration(**c)
|
|
||||||
if isinstance(c, dict) else c for c in self.configuration]
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a cloud cluster print job constraint
|
|
||||||
class CloudClusterPrintJobConstraint(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.require_printer_name = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
## Class representing a print job
|
|
||||||
class CloudClusterPrintJob(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.assigned_to = None # type: str
|
|
||||||
self.configuration = [] # type: List[CloudClusterPrinterConfiguration]
|
|
||||||
self.constraints = [] # type: List[CloudClusterPrintJobConstraint]
|
|
||||||
self.created_at = None # type: str
|
|
||||||
self.force = None # type: str
|
|
||||||
self.last_seen = None # type: str
|
|
||||||
self.machine_variant = None # type: str
|
|
||||||
self.name = None # type: str
|
|
||||||
self.network_error_count = None # type: int
|
|
||||||
self.owner = None # type: str
|
|
||||||
self.printer_uuid = None # type: str
|
|
||||||
self.started = None # type: str
|
|
||||||
self.status = None # type: str
|
|
||||||
self.time_elapsed = None # type: str
|
|
||||||
self.time_total = None # type: str
|
|
||||||
self.uuid = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.printers = [CloudClusterPrinterConfiguration(**c) if isinstance(c, dict) else c
|
|
||||||
for c in self.configuration]
|
|
||||||
self.printers = [CloudClusterPrintJobConstraint(**p) if isinstance(p, dict) else p
|
|
||||||
for p in self.constraints]
|
|
||||||
|
|
||||||
|
|
||||||
# Model that represents the status of the cluster for the cloud
|
|
||||||
class CloudClusterStatus(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
# a list of the printers
|
|
||||||
self.printers = [] # type: List[CloudClusterPrinter]
|
|
||||||
# a list of the print jobs
|
|
||||||
self.print_jobs = [] # type: List[CloudClusterPrintJob]
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
# converting any dictionaries into models
|
|
||||||
self.printers = [CloudClusterPrinter(**p) if isinstance(p, dict) else p for p in self.printers]
|
|
||||||
self.print_jobs = [CloudClusterPrintJob(**j) if isinstance(j, dict) else j for j in self.print_jobs]
|
|
||||||
|
|
||||||
|
|
||||||
# Model that represents the request to upload a print job to the cloud
|
|
||||||
class CloudJobUploadRequest(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.file_size = None # type: int
|
|
||||||
self.job_name = None # type: str
|
|
||||||
self.content_type = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Model that represents the response received from the cloud after requesting to upload a print job
|
|
||||||
class CloudJobResponse(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.download_url = None # type: str
|
|
||||||
self.job_id = None # type: str
|
|
||||||
self.job_name = None # type: str
|
|
||||||
self.slicing_details = None # type: str
|
|
||||||
self.status = None # type: str
|
|
||||||
self.upload_url = None # type: str
|
|
||||||
self.content_type = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Model that represents the responses received from the cloud after requesting a job to be printed.
|
|
||||||
class CloudPrintResponse(BaseModel):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.cluster_job_id = None # type: str
|
|
||||||
self.job_id = None # type: str
|
|
||||||
self.status = None # type: str
|
|
||||||
super().__init__(**kwargs)
|
|
21
plugins/UM3NetworkPrinting/src/Cloud/Models/CloudCluster.py
Normal file
21
plugins/UM3NetworkPrinting/src/Cloud/Models/CloudCluster.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a cloud connected cluster.
|
||||||
|
class CloudCluster(BaseModel):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.cluster_id = None # type: str
|
||||||
|
self.host_guid = None # type: str
|
||||||
|
self.host_name = None # type: str
|
||||||
|
self.host_version = None # type: str
|
||||||
|
self.status = None # type: str
|
||||||
|
self.is_online = None # type: bool
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
# Validates the model, raising an exception if the model is invalid.
|
||||||
|
def validate(self) -> None:
|
||||||
|
super().validate()
|
||||||
|
if not self.cluster_id:
|
||||||
|
raise ValueError("cluster_id is required on CloudCluster")
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||||
|
from .CloudClusterPrinterConfiguration import CloudClusterPrinterConfiguration
|
||||||
|
from .CloudClusterPrintJobConstraint import CloudClusterPrintJobConstraint
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a print job
|
||||||
|
from plugins.UM3NetworkPrinting.src.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
|
|
||||||
|
|
||||||
|
class CloudClusterPrintJob(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.assigned_to = None # type: str
|
||||||
|
self.configuration = [] # type: List[CloudClusterPrinterConfiguration]
|
||||||
|
self.constraints = [] # type: List[CloudClusterPrintJobConstraint]
|
||||||
|
self.created_at = None # type: str
|
||||||
|
self.force = None # type: str
|
||||||
|
self.last_seen = None # type: str
|
||||||
|
self.machine_variant = None # type: str
|
||||||
|
self.name = None # type: str
|
||||||
|
self.network_error_count = None # type: int
|
||||||
|
self.owner = None # type: str
|
||||||
|
self.printer_uuid = None # type: str
|
||||||
|
self.started = None # type: str
|
||||||
|
self.status = None # type: str
|
||||||
|
self.time_elapsed = None # type: str
|
||||||
|
self.time_total = None # type: str
|
||||||
|
self.uuid = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.printers = [CloudClusterPrinterConfiguration(**c) if isinstance(c, dict) else c
|
||||||
|
for c in self.configuration]
|
||||||
|
self.printers = [CloudClusterPrintJobConstraint(**p) if isinstance(p, dict) else p
|
||||||
|
for p in self.constraints]
|
||||||
|
|
||||||
|
## Creates an UM3 print job output model based on this cloud cluster print job.
|
||||||
|
# \param printer: The output model of the printer
|
||||||
|
def createOutputModel(self, printer: PrinterOutputModel) -> UM3PrintJobOutputModel:
|
||||||
|
model = UM3PrintJobOutputModel(printer.getController(), self.uuid, self.name)
|
||||||
|
model.updateAssignedPrinter(printer)
|
||||||
|
return model
|
||||||
|
|
||||||
|
## Updates an UM3 print job output model based on this cloud cluster print job.
|
||||||
|
# \param model: The model to update.
|
||||||
|
def updateOutputModel(self, model: UM3PrintJobOutputModel) -> None:
|
||||||
|
model.updateTimeTotal(self.time_total)
|
||||||
|
model.updateTimeElapsed(self.time_elapsed)
|
||||||
|
model.updateOwner(self.owner)
|
||||||
|
model.updateState(self.status)
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a cloud cluster print job constraint
|
||||||
|
class CloudClusterPrintJobConstraint(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.require_printer_name = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
|
||||||
|
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||||
|
from .CloudClusterPrinterConfiguration import CloudClusterPrinterConfiguration
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a cluster printer
|
||||||
|
class CloudClusterPrinter(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.configuration = [] # type: List[CloudClusterPrinterConfiguration]
|
||||||
|
self.enabled = None # type: str
|
||||||
|
self.firmware_version = None # type: str
|
||||||
|
self.friendly_name = None # type: str
|
||||||
|
self.ip_address = None # type: str
|
||||||
|
self.machine_variant = None # type: str
|
||||||
|
self.status = None # type: str
|
||||||
|
self.unique_name = None # type: str
|
||||||
|
self.uuid = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.configuration = [CloudClusterPrinterConfiguration(**c)
|
||||||
|
if isinstance(c, dict) else c for c in self.configuration]
|
||||||
|
|
||||||
|
## Creates a new output model.
|
||||||
|
# \param controller - The controller of the model.
|
||||||
|
def createOutputModel(self, controller: PrinterOutputController) -> PrinterOutputModel:
|
||||||
|
model = PrinterOutputModel(controller, len(self.configuration), firmware_version = self.firmware_version)
|
||||||
|
self.updateOutputModel(model)
|
||||||
|
return model
|
||||||
|
|
||||||
|
## Updates the given output model.
|
||||||
|
# \param model - The output model to update.
|
||||||
|
def updateOutputModel(self, model: PrinterOutputModel) -> None:
|
||||||
|
model.updateKey(self.uuid)
|
||||||
|
model.updateName(self.friendly_name)
|
||||||
|
model.updateType(self.machine_variant)
|
||||||
|
model.updateState(self.status if self.enabled else "disabled")
|
||||||
|
|
||||||
|
for configuration, extruder in zip(self.configuration, model.extruders):
|
||||||
|
configuration.updateOutputModel(extruder)
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
|
||||||
|
from .CloudClusterPrinterConfigurationMaterial import CloudClusterPrinterConfigurationMaterial
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a cloud cluster printer configuration
|
||||||
|
class CloudClusterPrinterConfiguration(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.extruder_index = None # type: str
|
||||||
|
self.material = None # type: CloudClusterPrinterConfigurationMaterial
|
||||||
|
self.nozzle_diameter = None # type: str
|
||||||
|
self.print_core_id = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
if isinstance(self.material, dict):
|
||||||
|
self.material = CloudClusterPrinterConfigurationMaterial(**self.material)
|
||||||
|
|
||||||
|
## Updates the given output model.
|
||||||
|
# \param model - The output model to update.
|
||||||
|
def updateOutputModel(self, model: ExtruderOutputModel) -> None:
|
||||||
|
model.updateHotendID(self.print_core_id)
|
||||||
|
|
||||||
|
if model.activeMaterial is None or model.activeMaterial.guid != self.material.guid:
|
||||||
|
material = self.material.createOutputModel()
|
||||||
|
model.updateActiveMaterial(material)
|
|
@ -0,0 +1,46 @@
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing a cloud cluster printer configuration
|
||||||
|
class CloudClusterPrinterConfigurationMaterial(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.guid = None # type: str
|
||||||
|
self.brand = None # type: str
|
||||||
|
self.color = None # type: str
|
||||||
|
self.material = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
## Creates a material output model based on this cloud printer material.
|
||||||
|
def createOutputModel(self) -> MaterialOutputModel:
|
||||||
|
material_manager = CuraApplication.getInstance().getMaterialManager()
|
||||||
|
material_group_list = material_manager.getMaterialGroupListByGUID(self.guid) or []
|
||||||
|
|
||||||
|
# Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
|
||||||
|
read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
|
||||||
|
non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
|
||||||
|
material_group = None
|
||||||
|
if read_only_material_group_list:
|
||||||
|
read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
|
||||||
|
material_group = read_only_material_group_list[0]
|
||||||
|
elif non_read_only_material_group_list:
|
||||||
|
non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
|
||||||
|
material_group = non_read_only_material_group_list[0]
|
||||||
|
|
||||||
|
if material_group:
|
||||||
|
container = material_group.root_material_node.getContainer()
|
||||||
|
color = container.getMetaDataEntry("color_code")
|
||||||
|
brand = container.getMetaDataEntry("brand")
|
||||||
|
material_type = container.getMetaDataEntry("material")
|
||||||
|
name = container.getName()
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Unable to find material with guid {guid}. Using data as provided by cluster"
|
||||||
|
.format(guid = self.guid))
|
||||||
|
color = self.color
|
||||||
|
brand = self.brand
|
||||||
|
material_type = self.material
|
||||||
|
name = "Empty" if self.material == "empty" else "Unknown"
|
||||||
|
|
||||||
|
return MaterialOutputModel(guid = self.guid, type = material_type, brand = brand, color = color, name = name)
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from .CloudClusterPrinter import CloudClusterPrinter
|
||||||
|
from .CloudClusterPrintJob import CloudClusterPrintJob
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# Model that represents the status of the cluster for the cloud
|
||||||
|
class CloudClusterStatus(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
# a list of the printers
|
||||||
|
self.printers = [] # type: List[CloudClusterPrinter]
|
||||||
|
# a list of the print jobs
|
||||||
|
self.print_jobs = [] # type: List[CloudClusterPrintJob]
|
||||||
|
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
# converting any dictionaries into models
|
||||||
|
self.printers = [CloudClusterPrinter(**p) if isinstance(p, dict) else p for p in self.printers]
|
||||||
|
self.print_jobs = [CloudClusterPrintJob(**j) if isinstance(j, dict) else j for j in self.print_jobs]
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
## Class representing errors generated by the cloud servers, according to the json-api standard.
|
||||||
|
class CloudErrorObject(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.id = None # type: str
|
||||||
|
self.code = None # type: str
|
||||||
|
self.http_status = None # type: str
|
||||||
|
self.title = None # type: str
|
||||||
|
self.detail = None # type: str
|
||||||
|
self.meta = None # type: Dict[str, any]
|
||||||
|
super().__init__(**kwargs)
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# Model that represents the response received from the cloud after requesting to upload a print job
|
||||||
|
class CloudJobResponse(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.download_url = None # type: str
|
||||||
|
self.job_id = None # type: str
|
||||||
|
self.job_name = None # type: str
|
||||||
|
self.slicing_details = None # type: str
|
||||||
|
self.status = None # type: str
|
||||||
|
self.upload_url = None # type: str
|
||||||
|
self.content_type = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# Model that represents the request to upload a print job to the cloud
|
||||||
|
class CloudJobUploadRequest(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.file_size = None # type: int
|
||||||
|
self.job_name = None # type: str
|
||||||
|
self.content_type = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from ...Models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# Model that represents the responses received from the cloud after requesting a job to be printed.
|
||||||
|
class CloudPrintResponse(BaseModel):
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
self.cluster_job_id = None # type: str
|
||||||
|
self.job_id = None # type: str
|
||||||
|
self.status = None # type: str
|
||||||
|
super().__init__(**kwargs)
|
2
plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
Normal file
2
plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
|
@ -25,11 +25,11 @@ from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationM
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
|
||||||
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||||
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||||
from plugins.UM3NetworkPrinting.src.MeshFormatHandler import MeshFormatHandler
|
|
||||||
|
|
||||||
from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
|
from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
|
||||||
from .SendMaterialJob import SendMaterialJob
|
|
||||||
from .ConfigurationChangeModel import ConfigurationChangeModel
|
from .ConfigurationChangeModel import ConfigurationChangeModel
|
||||||
|
from .MeshFormatHandler import MeshFormatHandler
|
||||||
|
from .SendMaterialJob import SendMaterialJob
|
||||||
from .UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
from .UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||||
|
|
|
@ -8,6 +8,7 @@ class BaseModel:
|
||||||
self.__dict__.update(kwargs)
|
self.__dict__.update(kwargs)
|
||||||
self.validate()
|
self.validate()
|
||||||
|
|
||||||
|
# Validates the model, raising an exception if the model is invalid.
|
||||||
def validate(self) -> None:
|
def validate(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -34,7 +35,9 @@ class LocalMaterial(BaseModel):
|
||||||
self.version = version # type: int
|
self.version = version # type: int
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
#
|
||||||
def validate(self) -> None:
|
def validate(self) -> None:
|
||||||
|
super().validate()
|
||||||
if not self.GUID:
|
if not self.GUID:
|
||||||
raise ValueError("guid is required on LocalMaterial")
|
raise ValueError("guid is required on LocalMaterial")
|
||||||
if not self.version:
|
if not self.version:
|
||||||
|
|
|
@ -10,7 +10,7 @@ from PyQt5.QtCore import QByteArray
|
||||||
|
|
||||||
from UM.MimeTypeDatabase import MimeType
|
from UM.MimeTypeDatabase import MimeType
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from plugins.UM3NetworkPrinting.src.SendMaterialJob import SendMaterialJob
|
from ..src.SendMaterialJob import SendMaterialJob
|
||||||
|
|
||||||
|
|
||||||
@patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>"))
|
@patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>"))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue