Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PrinterOutputModel.py « Models « PrinterOutput « cura - github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 37135bf663aea9c47c7360d900b2e13f48c399a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.

from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot, QUrl
from typing import List, Dict, Optional, TYPE_CHECKING
from UM.Math.Vector import Vector
from cura.PrinterOutput.Peripheral import Peripheral
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
from UM.Logger import Logger

if TYPE_CHECKING:
    from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
    from cura.PrinterOutput.PrinterOutputController import PrinterOutputController


class PrinterOutputModel(QObject):
    bedTemperatureChanged = pyqtSignal()
    targetBedTemperatureChanged = pyqtSignal()
    isPreheatingChanged = pyqtSignal()
    stateChanged = pyqtSignal()
    activePrintJobChanged = pyqtSignal()
    nameChanged = pyqtSignal()
    headPositionChanged = pyqtSignal()
    keyChanged = pyqtSignal()
    typeChanged = pyqtSignal()
    buildplateChanged = pyqtSignal()
    cameraUrlChanged = pyqtSignal()
    configurationChanged = pyqtSignal()
    canUpdateFirmwareChanged = pyqtSignal()

    def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
        super().__init__(parent)
        self._bed_temperature = -1  # type: float  # Use -1 for no heated bed.
        self._target_bed_temperature = 0 # type: float
        self._name = ""
        self._key = ""  # Unique identifier
        self._unique_name = ""  # Unique name (used in Connect)
        self._controller = output_controller
        self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
        self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
        self._active_printer_configuration = PrinterConfigurationModel()  # Indicates the current configuration setup in this printer
        self._head_position = Vector(0, 0, 0)
        self._active_print_job = None  # type: Optional[PrintJobOutputModel]
        self._firmware_version = firmware_version
        self._printer_state = "unknown"
        self._is_preheating = False
        self._printer_type = ""
        self._buildplate = ""
        self._peripherals = []  # type: List[Peripheral]

        self._active_printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
                                                                     self._extruders]
        self._active_printer_configuration.configurationChanged.connect(self.configurationChanged)
        self._available_printer_configurations = []  # type: List[PrinterConfigurationModel]

        self._camera_url = QUrl()  # type: QUrl

    @pyqtProperty(str, constant = True)
    def firmwareVersion(self) -> str:
        return self._firmware_version

    def setCameraUrl(self, camera_url: "QUrl") -> None:
        if self._camera_url != camera_url:
            self._camera_url = camera_url
            self.cameraUrlChanged.emit()

    @pyqtProperty(QUrl, fset = setCameraUrl, notify = cameraUrlChanged)
    def cameraUrl(self) -> "QUrl":
        return self._camera_url

    def updateIsPreheating(self, pre_heating: bool) -> None:
        if self._is_preheating != pre_heating:
            self._is_preheating = pre_heating
            self.isPreheatingChanged.emit()

    @pyqtProperty(bool, notify=isPreheatingChanged)
    def isPreheating(self) -> bool:
        return self._is_preheating

    @pyqtProperty(str, notify = typeChanged)
    def type(self) -> str:
        return self._printer_type

    def updateType(self, printer_type: str) -> None:
        if self._printer_type != printer_type:
            self._printer_type = printer_type
            self._active_printer_configuration.printerType = self._printer_type
            self.typeChanged.emit()
            self.configurationChanged.emit()

    @pyqtProperty(str, notify = buildplateChanged)
    def buildplate(self) -> str:
        return self._buildplate

    def updateBuildplate(self, buildplate: str) -> None:
        if self._buildplate != buildplate:
            self._buildplate = buildplate
            self._active_printer_configuration.buildplateConfiguration = self._buildplate
            self.buildplateChanged.emit()
            self.configurationChanged.emit()

    @pyqtProperty(str, notify=keyChanged)
    def key(self) -> str:
        return self._key

    def updateKey(self, key: str) -> None:
        if self._key != key:
            self._key = key
            self.keyChanged.emit()

    @pyqtSlot()
    def homeHead(self) -> None:
        self._controller.homeHead(self)

    @pyqtSlot()
    def homeBed(self) -> None:
        self._controller.homeBed(self)

    @pyqtSlot(str)
    def sendRawCommand(self, command: str) -> None:
        self._controller.sendRawCommand(self, command)

    @pyqtProperty("QVariantList", constant = True)
    def extruders(self) -> List["ExtruderOutputModel"]:
        return self._extruders

    @pyqtProperty(QVariant, notify = headPositionChanged)
    def headPosition(self) -> Dict[str, float]:
        return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}

    def updateHeadPosition(self, x: float, y: float, z: float) -> None:
        if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:
            self._head_position = Vector(x, y, z)
            self.headPositionChanged.emit()

    @pyqtProperty(float, float, float)
    @pyqtProperty(float, float, float, float)
    def setHeadPosition(self, x: float, y: float, z: float, speed: float = 3000) -> None:
        self.updateHeadPosition(x, y, z)
        self._controller.setHeadPosition(self, x, y, z, speed)

    @pyqtProperty(float)
    @pyqtProperty(float, float)
    def setHeadX(self, x: float, speed: float = 3000) -> None:
        self.updateHeadPosition(x, self._head_position.y, self._head_position.z)
        self._controller.setHeadPosition(self, x, self._head_position.y, self._head_position.z, speed)

    @pyqtProperty(float)
    @pyqtProperty(float, float)
    def setHeadY(self, y: float, speed: float = 3000) -> None:
        self.updateHeadPosition(self._head_position.x, y, self._head_position.z)
        self._controller.setHeadPosition(self, self._head_position.x, y, self._head_position.z, speed)

    @pyqtProperty(float)
    @pyqtProperty(float, float)
    def setHeadZ(self, z: float, speed:float = 3000) -> None:
        self.updateHeadPosition(self._head_position.x, self._head_position.y, z)
        self._controller.setHeadPosition(self, self._head_position.x, self._head_position.y, z, speed)

    @pyqtSlot(float, float, float)
    @pyqtSlot(float, float, float, float)
    def moveHead(self, x: float = 0, y: float = 0, z: float = 0, speed: float = 3000) -> None:
        self._controller.moveHead(self, x, y, z, speed)

    ##  Pre-heats the heated bed of the printer.
    #
    #   \param temperature The temperature to heat the bed to, in degrees
    #   Celsius.
    #   \param duration How long the bed should stay warm, in seconds.
    @pyqtSlot(float, float)
    def preheatBed(self, temperature: float, duration: float) -> None:
        self._controller.preheatBed(self, temperature, duration)

    @pyqtSlot()
    def cancelPreheatBed(self) -> None:
        self._controller.cancelPreheatBed(self)

    def getController(self) -> "PrinterOutputController":
        return self._controller

    @pyqtProperty(str, notify = nameChanged)
    def name(self) -> str:
        return self._name

    def setName(self, name: str) -> None:
        self.updateName(name)

    def updateName(self, name: str) -> None:
        if self._name != name:
            self._name = name
            self.nameChanged.emit()

    @pyqtProperty(str, notify = nameChanged)
    def uniqueName(self) -> str:
        return self._unique_name

    def updateUniqueName(self, unique_name: str) -> None:
        if self._unique_name != unique_name:
            self._unique_name = unique_name
            self.nameChanged.emit()

    ##  Update the bed temperature. This only changes it locally.
    def updateBedTemperature(self, temperature: float) -> None:
        if self._bed_temperature != temperature:
            self._bed_temperature = temperature
            self.bedTemperatureChanged.emit()

    def updateTargetBedTemperature(self, temperature: float) -> None:
        if self._target_bed_temperature != temperature:
            self._target_bed_temperature = temperature
            self.targetBedTemperatureChanged.emit()

    ##  Set the target bed temperature. This ensures that it's actually sent to the remote.
    @pyqtSlot(float)
    def setTargetBedTemperature(self, temperature: float) -> None:
        self._controller.setTargetBedTemperature(self, temperature)
        self.updateTargetBedTemperature(temperature)

    def updateActivePrintJob(self, print_job: Optional["PrintJobOutputModel"]) -> None:
        if self._active_print_job != print_job:
            old_print_job = self._active_print_job

            if print_job is not None:
                print_job.updateAssignedPrinter(self)
            self._active_print_job = print_job

            if old_print_job is not None:
                old_print_job.updateAssignedPrinter(None)
            self.activePrintJobChanged.emit()

    def updateState(self, printer_state: str) -> None:
        if self._printer_state != printer_state:
            self._printer_state = printer_state
            self.stateChanged.emit()

    @pyqtProperty(QObject, notify = activePrintJobChanged)
    def activePrintJob(self) -> Optional["PrintJobOutputModel"]:
        return self._active_print_job

    @pyqtProperty(str, notify = stateChanged)
    def state(self) -> str:
        return self._printer_state

    @pyqtProperty(float, notify = bedTemperatureChanged)
    def bedTemperature(self) -> float:
        return self._bed_temperature

    @pyqtProperty(float, notify = targetBedTemperatureChanged)
    def targetBedTemperature(self) -> float:
        return self._target_bed_temperature

    # Does the printer support pre-heating the bed at all
    @pyqtProperty(bool, constant = True)
    def canPreHeatBed(self) -> bool:
        if self._controller:
            return self._controller.can_pre_heat_bed
        return False

    # Does the printer support pre-heating the bed at all
    @pyqtProperty(bool, constant = True)
    def canPreHeatHotends(self) -> bool:
        if self._controller:
            return self._controller.can_pre_heat_hotends
        return False

    # Does the printer support sending raw G-code at all
    @pyqtProperty(bool, constant = True)
    def canSendRawGcode(self) -> bool:
        if self._controller:
            return self._controller.can_send_raw_gcode
        return False

    # Does the printer support pause at all
    @pyqtProperty(bool, constant = True)
    def canPause(self) -> bool:
        if self._controller:
            return self._controller.can_pause
        return False

    # Does the printer support abort at all
    @pyqtProperty(bool, constant = True)
    def canAbort(self) -> bool:
        if self._controller:
            return self._controller.can_abort
        return False

    # Does the printer support manual control at all
    @pyqtProperty(bool, constant = True)
    def canControlManually(self) -> bool:
        if self._controller:
            return self._controller.can_control_manually
        return False

    # Does the printer support upgrading firmware
    @pyqtProperty(bool, notify = canUpdateFirmwareChanged)
    def canUpdateFirmware(self) -> bool:
        if self._controller:
            return self._controller.can_update_firmware
        return False

    # Stub to connect UM.Signal to pyqtSignal
    def _onControllerCanUpdateFirmwareChanged(self) -> None:
        self.canUpdateFirmwareChanged.emit()

    # Returns the active configuration (material, variant and buildplate) of the current printer
    @pyqtProperty(QObject, notify = configurationChanged)
    def printerConfiguration(self) -> Optional[PrinterConfigurationModel]:
        if self._active_printer_configuration.isValid():
            return self._active_printer_configuration
        return None

    peripheralsChanged = pyqtSignal()

    @pyqtProperty(str, notify = peripheralsChanged)
    def peripherals(self) -> str:
        return ", ".join([peripheral.name for peripheral in self._peripherals])

    def addPeripheral(self, peripheral: Peripheral) -> None:
        self._peripherals.append(peripheral)
        self.peripheralsChanged.emit()

    def removePeripheral(self, peripheral: Peripheral) -> None:
        self._peripherals.remove(peripheral)
        self.peripheralsChanged.emit()

    availableConfigurationsChanged = pyqtSignal()

    # The availableConfigurations are configuration options that a printer can switch to, but doesn't currently have
    # active (eg; Automatic tool changes, material loaders, etc).
    @pyqtProperty("QVariantList", notify = availableConfigurationsChanged)
    def availableConfigurations(self) -> List[PrinterConfigurationModel]:
        return self._available_printer_configurations

    def addAvailableConfiguration(self, new_configuration: PrinterConfigurationModel) -> None:
        if new_configuration not in self._available_printer_configurations:
            self._available_printer_configurations.append(new_configuration)
            self.availableConfigurationsChanged.emit()

    def removeAvailableConfiguration(self, config_to_remove: PrinterConfigurationModel) -> None:
        try:
            self._available_printer_configurations.remove(config_to_remove)
        except ValueError:
            Logger.log("w", "Unable to remove configuration that isn't in the list of available configurations")
        else:
            self.availableConfigurationsChanged.emit()

    def setAvailableConfigurations(self, new_configurations: List[PrinterConfigurationModel]) -> None:
        self._available_printer_configurations = new_configurations
        self.availableConfigurationsChanged.emit()