Skip to content

Commit bb365c6

Browse files
committed
bumped version to 1.1.0
Added support for MacOS and Linux Minor Code refactoring
1 parent 8ddf4e8 commit bb365c6

5 files changed

+66
-75
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,4 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
*.qmlc

QidiPrintOutputDevice.py

+58-66
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from UM.PluginRegistry import PluginRegistry
2222
from UM.OutputDevice.OutputDevice import OutputDevice
2323
from UM.OutputDevice import OutputDeviceError
24+
from UM.Platform import Platform
2425

2526
from UM.i18n import i18nCatalog
2627
from .ChituCodeWriter import ChituCodeWriter
@@ -66,8 +67,7 @@ def __init__(self, name, target_ip):
6667
self.sock = socket(AF_INET, SOCK_DGRAM)
6768
self.sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
6869

69-
self._localTempGcode = Resources.getStoragePath(
70-
Resources.Resources, 'data.gcode')
70+
self._localTempGcode = Resources.getStoragePath(Resources.Resources, 'data.gcode')
7171
self._send_thread = None
7272
self._file_encode = 'utf-8'
7373

@@ -91,27 +91,22 @@ def requestWrite(self, node, fileName=None, *args, **kwargs):
9191
raise OutputDeviceError.DeviceBusyError()
9292

9393
if fileName:
94-
fileName = os.path.splitext(fileName)[0] + '.gcode.tz'
94+
fileName = os.path.splitext(fileName)[0]
9595
else:
96-
fileName = "%s.gcode.tz" % Application.getInstance().getPrintInformation().jobName
96+
fileName = "%s" % Application.getInstance().getPrintInformation().jobName
9797
self.targetSendFileName = fileName
9898

99-
path = os.path.join(os.path.dirname(
100-
os.path.abspath(__file__)), 'UploadFilename.qml')
101-
self._dialog = CuraApplication.getInstance(
102-
).createQmlComponent(path, {"manager": self})
99+
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'UploadFilename.qml')
100+
self._dialog = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
103101
self._dialog.textChanged.connect(self.onFilenameChanged)
104102
self._dialog.accepted.connect(self.onFilenameAccepted)
105103
self._dialog.show()
106-
self._dialog.findChild(QObject, "nameField").setProperty(
107-
'text', self.targetSendFileName)
108-
self._dialog.findChild(QObject, "nameField").select(
109-
0, len(self.targetSendFileName) - 9)
104+
self._dialog.findChild(QObject, "nameField").setProperty('text', self.targetSendFileName)
105+
self._dialog.findChild(QObject, "nameField").select(0, len(self.targetSendFileName))
110106
self._dialog.findChild(QObject, "nameField").setProperty('focus', True)
111107

112108
def onFilenameChanged(self):
113-
fileName = self._dialog.findChild(
114-
QObject, "nameField").property('text').strip()
109+
fileName = self._dialog.findChild(QObject, "nameField").property('text').strip()
115110
forbidden_characters = "\"'´`<>()[]?*\,;:&%#$!"
116111
for forbidden_character in forbidden_characters:
117112
if forbidden_character in fileName:
@@ -138,7 +133,6 @@ def _genTempGcodeFile(self):
138133
if not fp:
139134
self._result = SendResult.FILE_NOT_SAVE
140135
else:
141-
#writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("ChituCodeWriter"))
142136
writer = ChituCodeWriter()
143137
success = writer.write(fp, None, MeshWriter.OutputMode.TextMode)
144138
fp.close()
@@ -160,8 +154,7 @@ def sendDatThread(self):
160154
if tryCnt > 3:
161155
self._result = SendResult.CONNECT_TIMEOUT
162156
break
163-
self.sock.sendto(self.encodeCmd(
164-
'M4001\r\n'), (self._targetIP, self.PORT))
157+
self.sock.sendto(self.encodeCmd('M4001\r\n'), (self._targetIP, self.PORT))
165158
message, address = self.sock.recvfrom(self.RECVBUF)
166159
Logger.log('d', message)
167160
break
@@ -175,12 +168,16 @@ def sendDatThread(self):
175168
break
176169
if self._abort:
177170
break
178-
filePath = self._localTempGcode + '.tz'
179-
Logger.log('d', 'compressed file path: ' + filePath)
171+
if os.path.exists(self._localTempGcode + '.tz'):
172+
filePath = self._localTempGcode + '.tz'
173+
self.targetSendFileName = self.targetSendFileName + '.gcode.tz'
174+
else:
175+
filePath = self._localTempGcode
176+
self.targetSendFileName = self.targetSendFileName + '.gcode'
177+
Logger.log('d', 'file path: ' + filePath)
180178
try:
181179
self.sendMax = os.path.getsize(filePath)
182-
Logger.log('d', 'compressed file size: ' +
183-
str(self.sendMax))
180+
Logger.log('d', 'file size: ' + str(self.sendMax))
184181
if self.sendMax == 0:
185182
self._result = SendResult.FILE_EMPTY
186183
break
@@ -197,8 +194,7 @@ def sendDatThread(self):
197194
fp.seek(0, 0)
198195
cmd = 'M28 ' + self.targetSendFileName
199196
Logger.log('d', 'cmd:' + cmd)
200-
self.sock.sendto(self.encodeCmd(
201-
cmd), (self._targetIP, self.PORT))
197+
self.sock.sendto(self.encodeCmd(cmd), (self._targetIP, self.PORT))
202198
message, address = self.sock.recvfrom(self.RECVBUF)
203199
message = message.decode('utf-8', 'replace')
204200
Logger.log('d', 'message: ' + message)
@@ -218,7 +214,7 @@ def sendDatThread(self):
218214
break
219215
data = fp.read(self.BUFSIZE)
220216
if not data:
221-
Logger.log('f', 'reach file end')
217+
Logger.log('d', 'reach file end')
222218
if finishedCnt >= 50 or not lastDataArray:
223219
break
224220
dataArray = lastDataArray
@@ -249,8 +245,7 @@ def sendDatThread(self):
249245
dataArray[datSize + 5] = 131
250246
lastDataArray = dataArray
251247

252-
self.sock.sendto(
253-
dataArray, (self._targetIP, self.PORT))
248+
self.sock.sendto(dataArray, (self._targetIP, self.PORT))
254249
message, address = self.sock.recvfrom(self.RECVBUF)
255250
timeoutCnt = 0
256251
message = message.decode('utf-8', 'replace')
@@ -271,14 +266,12 @@ def sendDatThread(self):
271266
value = value[0].replace('resend ', '')
272267
oldseek = offset = int(value)
273268
fp.seek(offset, 0)
274-
Logger.log(
275-
'd', 'resend offset:' + str(offset))
269+
Logger.log('d', 'resend offset:' + str(offset))
276270
else:
277271
Logger.log('d', 'Error offset:' + message)
278272
except timeout:
279273
if finishedCnt < 4 and timeoutCnt > 150 or finishedCnt > 45:
280-
Logger.log(
281-
'w', 'finishedCnt: ' + str(finishedCnt) + ' timeoutcnt: ' + str(timeoutCnt))
274+
Logger.log('w', 'finishedCnt: ' + str(finishedCnt) + ' timeoutcnt: ' + str(timeoutCnt))
282275
self._result = SendResult.CONNECT_TIMEOUT
283276
break
284277
timeoutCnt += 1
@@ -287,16 +280,18 @@ def sendDatThread(self):
287280
self._abort = True
288281

289282
fp.close()
290-
os.remove(filePath)
283+
if os.path.exists(filePath):
284+
os.remove(filePath)
285+
if os.path.exists(self._localTempGcode):
286+
os.remove(self._localTempGcode)
291287
break
292288

293289
if not self._abort and self._result == SendResult.SEND_RUNNING:
294290
self.sock.settimeout(2)
295291
tryCnt = 0
296292
while True:
297293
try:
298-
self.sock.sendto(self.encodeCmd(
299-
'M29'), (self._targetIP, self.PORT))
294+
self.sock.sendto(self.encodeCmd('M29'), (self._targetIP, self.PORT))
300295
message, address = self.sock.recvfrom(self.RECVBUF)
301296
message = message.decode('utf-8', 'replace')
302297
Logger.log('d', 'M29 rcv:' + message)
@@ -328,8 +323,7 @@ def dataCompressThread(self):
328323
break
329324
self.sock.settimeout(2)
330325
Logger.log('d', self._targetIP)
331-
self.sock.sendto(self.encodeCmd('M4001'),
332-
(self._targetIP, self.PORT))
326+
self.sock.sendto(self.encodeCmd('M4001'), (self._targetIP, self.PORT))
333327
message, address = self.sock.recvfrom(self.BUFSIZE)
334328
pattern = re.compile(self.datamask)
335329
msg = message.decode('utf-8', 'ignore')
@@ -364,15 +358,25 @@ def dataCompressThread(self):
364358
s_z_max = _[3]
365359
elif id == 'U':
366360
self._file_encode = value.replace("'", '')
367-
exePath = os.path.join(os.path.dirname(
368-
os.path.abspath(__file__)), 'VC_compress_gcode.exe')
369-
cmd = '"' + exePath + '"' + ' "' + self._localTempGcode + '" ' + x_mm_per_step + ' ' + y_mm_per_step + ' ' + z_mm_per_step + ' ' + \
370-
e_mm_per_step + ' "' + \
371-
os.path.dirname(self._localTempGcode) + '" ' + s_x_max + \
372-
' ' + s_y_max + ' ' + s_z_max + ' ' + s_machine_type
373-
Logger.log('d', cmd)
374-
ret = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
375-
Logger.log('d', ret.stdout.read().decode('utf-8', 'ignore'))
361+
try:
362+
if Platform.isWindows():
363+
exePath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'VC_compress_gcode.exe')
364+
elif Platform.isOSX():
365+
exePath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'VC_compress_gcode_MAC')
366+
if not os.path.exists(exePath):
367+
exePath = './VC_compress_gcode_MAC'
368+
else:
369+
Logger.log('e', "Could not apply gcode compression")
370+
break
371+
cmd = '"' + exePath + '"' + ' "' + self._localTempGcode + '" ' + x_mm_per_step + ' ' + y_mm_per_step + ' ' + z_mm_per_step + ' ' + \
372+
e_mm_per_step + ' "' + \
373+
os.path.dirname(self._localTempGcode) + '" ' + s_x_max + \
374+
' ' + s_y_max + ' ' + s_z_max + ' ' + s_machine_type
375+
Logger.log('d', cmd)
376+
ret = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
377+
Logger.log('d', ret.stdout.read().decode('utf-8', 'ignore'))
378+
except:
379+
Logger.log('e', "Could not apply gcode compression")
376380
break
377381
except timeout:
378382
tryCnt += 1
@@ -410,12 +414,9 @@ def startSendingThread(self):
410414
return
411415

412416
if self._result == SendResult.SEND_DONE:
413-
self._message = Message(catalog.i18nc(
414-
"@info:status", "Do you wish to print now?"), title=catalog.i18nc("@label", "SUCCESS"))
415-
self._message.addAction("YES", catalog.i18nc(
416-
"@action:button", "YES"), None, "")
417-
self._message.addAction("NO", catalog.i18nc(
418-
"@action:button", "NO"), None, "")
417+
self._message = Message(catalog.i18nc("@info:status", "Do you wish to print now?"), title=catalog.i18nc("@label", "SUCCESS"))
418+
self._message.addAction("YES", catalog.i18nc("@action:button", "YES"), None, "")
419+
self._message.addAction("NO", catalog.i18nc("@action:button", "NO"), None, "")
419420
self._message.actionTriggered.connect(self._onActionTriggered)
420421
self._message.show()
421422
self.writeSuccess.emit(self)
@@ -430,8 +431,7 @@ def startSendingThread(self):
430431
self.writeError.emit(self)
431432
result_msg = self._errorMsg
432433
if 'create file' in self._errorMsg:
433-
m = Message(catalog.i18nc(
434-
'@info:status', ' Write error,please check that the SD card /U disk has been inserted'), lifetime=0)
434+
m = Message(catalog.i18nc('@info:status', ' Write error, please check that the SD card /U disk has been inserted'), lifetime=0)
435435
m.show()
436436
elif self._result == SendResult.FILE_EMPTY:
437437
self.writeError.emit(self)
@@ -446,29 +446,22 @@ def startSendingThread(self):
446446
self.writeError.emit(self)
447447
result_msg = "Cannot start print"
448448

449-
self._message = Message(catalog.i18nc(
450-
"@info:status", result_msg), title=catalog.i18nc("@label", "FAILURE"))
449+
self._message = Message(catalog.i18nc("@info:status", result_msg), title=catalog.i18nc("@label", "FAILURE"))
451450
self._message.show()
452451
self._stage = OutputStage.ready
453452
Logger.log('e', result_msg)
454453

455454
def onFilenameAccepted(self):
456-
self.targetSendFileName = self._dialog.findChild(
457-
QObject, "nameField").property('text').strip()
458-
if not self.targetSendFileName.endswith('.gcode.tz') and '.' not in self.targetSendFileName:
459-
self.targetSendFileName += '.gcode.tz'
460-
Logger.log("d", self._name + " | Filename set to: " +
461-
self.targetSendFileName)
455+
self.targetSendFileName = self._dialog.findChild(QObject, "nameField").property('text').strip()
456+
Logger.log("d", self._name + " | Filename set to: " + self.targetSendFileName)
462457
self._dialog.deleteLater()
463458

464459
self._message = Message(
465-
catalog.i18nc("@info:status",
466-
"Uploading to {}").format(self._name),
460+
catalog.i18nc("@info:status", "Uploading to {}").format(self._name),
467461
title=catalog.i18nc("@label", self._PluginName),
468462
progress=-1, lifetime=0, dismissable=False, use_inactivity_timer=False
469463
)
470-
self._message.addAction("ABORT", catalog.i18nc(
471-
"@action:button", "Cancel"), None, "")
464+
self._message.addAction("ABORT", catalog.i18nc("@action:button", "Cancel"), None, "")
472465
self._message.actionTriggered.connect(self._onActionTriggered)
473466
self._message.show()
474467

@@ -492,8 +485,7 @@ def _onActionTriggered(self, message, action):
492485
try:
493486
cmd = 'M6030 ":' + self.targetSendFileName + '" I1'
494487
Logger.log('i', 'Start print: ' + cmd)
495-
self.sock.sendto(self.encodeCmd(
496-
cmd), (self._targetIP, self.PORT))
488+
self.sock.sendto(self.encodeCmd(cmd), (self._targetIP, self.PORT))
497489
message, address = self.sock.recvfrom(self.RECVBUF)
498490
message = message.decode('utf-8', 'replace')
499491
if 'Error' in message:

README.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22

33
Plugin for Cura 4.7 that allows printing on QIDI 3D printers over network
44

5+
![Screenshot of the print button](/screenshots/print-button.png)
6+
57
## Manual Installation
68

79
with Cura not running, unpack the zip file from the
810
[release](https://github.com/alkaes/QidiPrint/releases/latest) to this
911
specific folder:
1012

11-
`C:\Users\<username>\AppData\Roaming\cura\4.7\plugins\QidiPrint`
12-
13-
Be careful, the unzipper often tacks on the name of the zip as a folder at the
14-
bottom and you don't want it nested. You want the files to show up in that
15-
folder.
1613

17-
Make sure that the plugin folder name is a listed above and it does not have
18-
any trailing version numbers (`-1.0.0`) or similar.
14+
* Windows: `%USERPROFILE%\AppData\Roaming\cura\4.7\plugins\`
15+
* MacOS: `~/Library/Application Support/Cura/4.7/plugins/`
16+
* Linux: `/home/<username>/.local/share/cura/4.7/plugins/`
1917

2018
## Configuration
2119

@@ -46,6 +44,6 @@ should be the big blue button with you printer name on it!
4644

4745
This project is using code from:
4846
* https://github.com/Kriechi/Cura-DuetRRFPlugin
49-
* https://github.com/Spanni26/ChituCodeWriter
47+
* ChituCodeWriter.py is taken from https://github.com/Spanni26/ChituCodeWriter
5048

5149

VC_compress_gcode_MAC

44.9 KB
Binary file not shown.

plugin.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"name": "QidiPrint",
33
"author": "Aleksey Sokolov",
44
"description": "Upload and Print to Qidi printers",
5-
"version": "1.0.0",
5+
"version": "1.1.0",
66
"supported_sdk_versions": ["7.2.0", "7.3.0"]
77
}

0 commit comments

Comments
 (0)