mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-02 16:54:23 +08:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
9daa78a98f
@ -214,14 +214,14 @@ class CuraApplication(QtApplication):
|
||||
self._cura_scene_controller = None
|
||||
self._machine_error_checker = None
|
||||
|
||||
self._machine_settings_manager = MachineSettingsManager(self)
|
||||
self._machine_settings_manager = MachineSettingsManager(self, parent = self)
|
||||
|
||||
self._discovered_printer_model = DiscoveredPrintersModel(self)
|
||||
self._first_start_machine_actions_model = FirstStartMachineActionsModel(self)
|
||||
self._welcome_pages_model = WelcomePagesModel(self)
|
||||
self._add_printer_pages_model = AddPrinterPagesModel(self)
|
||||
self._whats_new_pages_model = WhatsNewPagesModel(self)
|
||||
self._text_manager = TextManager(self)
|
||||
self._discovered_printer_model = DiscoveredPrintersModel(parent = self)
|
||||
self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
|
||||
self._welcome_pages_model = WelcomePagesModel(self, parent = self)
|
||||
self._add_printer_pages_model = AddPrinterPagesModel(self, parent = self)
|
||||
self._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
|
||||
self._text_manager = TextManager(parent = self)
|
||||
|
||||
self._quality_profile_drop_down_menu_model = None
|
||||
self._custom_quality_profile_drop_down_menu_model = None
|
||||
|
@ -40,4 +40,4 @@ cmake3 \
|
||||
-DBUILD_TESTS=ON \
|
||||
..
|
||||
make
|
||||
ctest3 --verbose --output-on-failure -T Test
|
||||
ctest3 --output-on-failure -T Test
|
||||
|
@ -58,6 +58,14 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
# Therefore we create a private signal used to trigger the printersChanged signal.
|
||||
_clusterPrintersChanged = pyqtSignal()
|
||||
|
||||
# Map of Cura Connect machine_variant field to Cura machine types.
|
||||
# Needed for printer discovery stack creation.
|
||||
_host_machine_variant_to_machine_type_map = {
|
||||
"Ultimaker 3": "ultimaker3",
|
||||
"Ultimaker 3 Extended": "ultimaker3_extended",
|
||||
"Ultimaker S5": "ultimaker_s5"
|
||||
}
|
||||
|
||||
## Creates a new cloud output device
|
||||
# \param api_client: The client that will run the API calls
|
||||
# \param cluster: The device response received from the cloud API.
|
||||
@ -68,10 +76,10 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
# Because the cloud connection does not off all of these, we manually construct this version here.
|
||||
# An example of why this is needed is the selection of the compatible file type when exporting the tool path.
|
||||
properties = {
|
||||
b"address": b"",
|
||||
b"name": cluster.host_name.encode() if cluster.host_name else b"",
|
||||
b"address": cluster.host_internal_ip.encode() if cluster.host_internal_ip else b"",
|
||||
b"name": cluster.friendly_name.encode() if cluster.friendly_name else b"",
|
||||
b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"",
|
||||
b"printer_type": b""
|
||||
b"cluster_size": b"1" # cloud devices are always clusters of at least one
|
||||
}
|
||||
|
||||
super().__init__(device_id = cluster.cluster_id, address = "",
|
||||
@ -96,6 +104,7 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
|
||||
# We keep track of which printer is visible in the monitor page.
|
||||
self._active_printer = None # type: Optional[PrinterOutputModel]
|
||||
self._host_machine_type = ""
|
||||
|
||||
# Properties to populate later on with received cloud data.
|
||||
self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
|
||||
@ -236,6 +245,10 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
previous = {p.key: p for p in self._printers} # type: Dict[str, PrinterOutputModel]
|
||||
received = {p.uuid: p for p in printers} # type: Dict[str, CloudClusterPrinterStatus]
|
||||
|
||||
if len(printers) > 0:
|
||||
# We need the machine type of the host (1st list entry) to allow discovery to work.
|
||||
self._host_machine_type = printers[0].machine_variant
|
||||
|
||||
removed_printers, added_printers, updated_printers = findChanges(previous, received)
|
||||
|
||||
for removed_printer in removed_printers:
|
||||
@ -359,6 +372,19 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
).show()
|
||||
self.writeFinished.emit()
|
||||
|
||||
## Gets the printer type of the cluster host. Falls back to the printer type in the device properties.
|
||||
@pyqtProperty(str, notify=_clusterPrintersChanged)
|
||||
def printerType(self) -> str:
|
||||
if self._printers and self._host_machine_type in self._host_machine_variant_to_machine_type_map:
|
||||
return self._host_machine_variant_to_machine_type_map[self._host_machine_type]
|
||||
return super().printerType
|
||||
|
||||
## Gets the number of printers in the cluster.
|
||||
# We use a minimum of 1 because cloud devices are always a cluster and printer discovery needs it.
|
||||
@pyqtProperty(int, notify = _clusterPrintersChanged)
|
||||
def clusterSize(self) -> int:
|
||||
return max(1, len(self._printers))
|
||||
|
||||
## Gets the remote printers.
|
||||
@pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
|
||||
def printers(self) -> List[PrinterOutputModel]:
|
||||
@ -376,10 +402,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||
self._active_printer = printer
|
||||
self.activePrinterChanged.emit()
|
||||
|
||||
@pyqtProperty(int, notify = _clusterPrintersChanged)
|
||||
def clusterSize(self) -> int:
|
||||
return len(self._printers)
|
||||
|
||||
## Get remote print jobs.
|
||||
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
||||
def printJobs(self) -> List[UM3PrintJobOutputModel]:
|
||||
|
@ -7,7 +7,7 @@ from PyQt5.QtCore import QTimer
|
||||
from UM import i18nCatalog
|
||||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.Signal import Signal, signalemitter
|
||||
from UM.Signal import Signal
|
||||
from cura.API import Account
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
@ -81,25 +81,61 @@ class CloudOutputDeviceManager:
|
||||
Logger.log("d", "Removed: %s, added: %s, updates: %s", len(removed_devices), len(added_clusters), len(updates))
|
||||
|
||||
# Remove output devices that are gone
|
||||
for removed_cluster in removed_devices:
|
||||
if removed_cluster.isConnected():
|
||||
removed_cluster.disconnect()
|
||||
removed_cluster.close()
|
||||
self._output_device_manager.removeOutputDevice(removed_cluster.key)
|
||||
self.removedCloudCluster.emit(removed_cluster)
|
||||
del self._remote_clusters[removed_cluster.key]
|
||||
for device in removed_devices:
|
||||
if device.isConnected():
|
||||
device.disconnect()
|
||||
device.close()
|
||||
self._output_device_manager.removeOutputDevice(device.key)
|
||||
self._application.getDiscoveredPrintersModel().removeDiscoveredPrinter(device.key)
|
||||
self.removedCloudCluster.emit(device)
|
||||
del self._remote_clusters[device.key]
|
||||
|
||||
# Add an output device for each new remote cluster.
|
||||
# We only add when is_online as we don't want the option in the drop down if the cluster is not online.
|
||||
for added_cluster in added_clusters:
|
||||
device = CloudOutputDevice(self._api, added_cluster)
|
||||
self._remote_clusters[added_cluster.cluster_id] = device
|
||||
self.addedCloudCluster.emit(added_cluster)
|
||||
for cluster in added_clusters:
|
||||
device = CloudOutputDevice(self._api, cluster)
|
||||
self._remote_clusters[cluster.cluster_id] = device
|
||||
self._application.getDiscoveredPrintersModel().addDiscoveredPrinter(
|
||||
cluster.cluster_id,
|
||||
device.key,
|
||||
cluster.friendly_name,
|
||||
self._createMachineFromDiscoveredPrinter,
|
||||
device.printerType,
|
||||
device
|
||||
)
|
||||
self.addedCloudCluster.emit(cluster)
|
||||
|
||||
# Update the output devices
|
||||
for device, cluster in updates:
|
||||
device.clusterData = cluster
|
||||
self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter(
|
||||
cluster.cluster_id,
|
||||
cluster.friendly_name,
|
||||
device.printerType,
|
||||
)
|
||||
|
||||
self._connectToActiveMachine()
|
||||
|
||||
def _createMachineFromDiscoveredPrinter(self, key: str) -> None:
|
||||
device = self._remote_clusters[key] # type: CloudOutputDevice
|
||||
if not device:
|
||||
Logger.log("e", "Could not find discovered device with key [%s]", key)
|
||||
return
|
||||
|
||||
group_name = device.clusterData.friendly_name
|
||||
machine_type_id = device.printerType
|
||||
|
||||
Logger.log("i", "Creating machine from cloud device with key = [%s], group name = [%s], printer type = [%s]",
|
||||
key, group_name, machine_type_id)
|
||||
|
||||
# The newly added machine is automatically activated.
|
||||
self._application.getMachineManager().addMachine(machine_type_id, group_name)
|
||||
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
if not 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.
|
||||
def _connectToActiveMachine(self) -> None:
|
||||
|
@ -16,7 +16,8 @@ class CloudClusterResponse(BaseCloudModel):
|
||||
# \param status: The status of the cluster authentication (active or inactive).
|
||||
# \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on.
|
||||
def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str,
|
||||
host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, **kwargs) -> None:
|
||||
host_internal_ip: Optional[str] = None, host_version: Optional[str] = None,
|
||||
friendly_name: Optional[str] = None, **kwargs) -> None:
|
||||
self.cluster_id = cluster_id
|
||||
self.host_guid = host_guid
|
||||
self.host_name = host_name
|
||||
@ -24,6 +25,7 @@ class CloudClusterResponse(BaseCloudModel):
|
||||
self.is_online = is_online
|
||||
self.host_version = host_version
|
||||
self.host_internal_ip = host_internal_ip
|
||||
self.friendly_name = friendly_name
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# Validates the model, raising an exception if the model is invalid.
|
||||
|
@ -22,6 +22,7 @@ class TestCloudOutputDevice(TestCase):
|
||||
HOST_NAME = "ultimakersystem-ccbdd30044ec"
|
||||
HOST_GUID = "e90ae0ac-1257-4403-91ee-a44c9b7e8050"
|
||||
HOST_VERSION = "5.2.0"
|
||||
FRIENDLY_NAME = "My Friendly Printer"
|
||||
|
||||
STATUS_URL = "{}/connect/v1/clusters/{}/status".format(CuraCloudAPIRoot, CLUSTER_ID)
|
||||
PRINT_URL = "{}/connect/v1/clusters/{}/print/{}".format(CuraCloudAPIRoot, CLUSTER_ID, JOB_ID)
|
||||
@ -37,7 +38,8 @@ class TestCloudOutputDevice(TestCase):
|
||||
patched_method.start()
|
||||
|
||||
self.cluster = CloudClusterResponse(self.CLUSTER_ID, self.HOST_GUID, self.HOST_NAME, is_online=True,
|
||||
status="active", host_version=self.HOST_VERSION)
|
||||
status="active", host_version=self.HOST_VERSION,
|
||||
friendly_name=self.FRIENDLY_NAME)
|
||||
|
||||
self.network = NetworkManagerMock()
|
||||
self.account = MagicMock(isLoggedIn=True, accessToken="TestAccessToken")
|
||||
@ -60,7 +62,7 @@ class TestCloudOutputDevice(TestCase):
|
||||
# We test for these in order to make sure the correct file type is selected depending on the firmware version.
|
||||
def test_properties(self):
|
||||
self.assertEqual(self.device.firmwareVersion, self.HOST_VERSION)
|
||||
self.assertEqual(self.device.name, self.HOST_NAME)
|
||||
self.assertEqual(self.device.name, self.FRIENDLY_NAME)
|
||||
|
||||
def test_status(self):
|
||||
self.device._update()
|
||||
|
@ -5853,10 +5853,10 @@
|
||||
"description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.",
|
||||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 0.20,
|
||||
"default_value": 0.5,
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.02",
|
||||
"maximum_value_warning": "2",
|
||||
"minimum_value_warning": "0.01",
|
||||
"maximum_value_warning": "3",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"meshfix_maximum_travel_resolution":
|
||||
@ -5865,8 +5865,8 @@
|
||||
"description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.",
|
||||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 0.5,
|
||||
"value": "meshfix_maximum_resolution * speed_travel / speed_print",
|
||||
"default_value": 1.0,
|
||||
"value": "min(meshfix_maximum_resolution * speed_travel / speed_print, 2 * line_width)",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.05",
|
||||
"maximum_value_warning": "10",
|
||||
@ -5879,10 +5879,10 @@
|
||||
"description": "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller.",
|
||||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 0.005,
|
||||
"default_value": 0.05,
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.003",
|
||||
"maximum_value_warning": "0.1",
|
||||
"minimum_value_warning": "0.01",
|
||||
"maximum_value_warning": "0.3",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"support_skip_some_zags":
|
||||
|
@ -118,7 +118,6 @@
|
||||
"material_bed_temperature": { "maximum_value": "115" },
|
||||
"material_bed_temperature_layer_0": { "maximum_value": "115" },
|
||||
"material_standby_temperature": { "value": "100" },
|
||||
"meshfix_maximum_resolution": { "value": "0.04" },
|
||||
"multiple_mesh_overlap": { "value": "0" },
|
||||
"optimize_wall_printing_order": { "value": "True" },
|
||||
"prime_tower_enable": { "default_value": true },
|
||||
|
@ -156,7 +156,8 @@
|
||||
"wall_0_inset": { "value": "0" },
|
||||
"wall_line_width_x": { "value": "round(line_width * 0.3 / 0.35, 2)" },
|
||||
"wall_thickness": { "value": "1" },
|
||||
"meshfix_maximum_resolution": { "value": "0.04" },
|
||||
"meshfix_maximum_resolution": { "value": "(speed_wall_0 + speed_wall_x) / 60" },
|
||||
"meshfix_maximum_deviation": { "value": "layer_height / 2" },
|
||||
"optimize_wall_printing_order": { "value": "True" },
|
||||
"retraction_combing": { "default_value": "all" },
|
||||
"initial_layer_line_width_factor": { "value": "120" },
|
||||
|
Loading…
x
Reference in New Issue
Block a user