Skip to content
This repository was archived by the owner on May 2, 2023. It is now read-only.

Commit 15792dd

Browse files
committed
fix error sending raw gcode file
1 parent f6a70f7 commit 15792dd

3 files changed

Lines changed: 76 additions & 60 deletions

File tree

SM2GCodeWriter.py

Lines changed: 68 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
# from cura.CuraApplication import CuraApplication
1515
from cura.Snapshot import Snapshot
16+
from cura.CuraApplication import CuraApplication
1617
from cura.Utils.Threading import call_on_qt_thread
1718
# from cura.UI import PrintInformation
1819
from PyQt5.QtCore import QBuffer
@@ -62,16 +63,19 @@ def __init__(self):
6263
super().__init__(add_to_recent_files = False)
6364
self._application = Application.getInstance()
6465

66+
@call_on_qt_thread
6567
def _createSnapshot(self, *args):
66-
# must be called from the main thread because of OpenGL
6768
Logger.log("d", "Creating thumbnail image...")
69+
if not CuraApplication.getInstance().isVisible:
70+
Logger.log("w", "Can't create snapshot when renderer not initialized.")
71+
return None
6872
try:
69-
self._snapshot = Snapshot.snapshot(width=300, height=300).convertToFormat(QImage.Format_Indexed8)
73+
ss = Snapshot.snapshot(width=300, height=300).convertToFormat(QImage.Format_Indexed8)
7074
except Exception:
7175
Logger.logException("w", "Failed to create snapshot image")
72-
self._snapshot = None # Failing to create thumbnail should not fail creation of UFP
76+
return None
77+
return ss
7378

74-
@call_on_qt_thread
7579
def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode):
7680
"""Writes the g-code for the entire scene to a stream.
7781
@@ -98,87 +102,93 @@ def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode):
98102
gcode_dict = getattr(scene, "gcode_dict")
99103
gcode_list = gcode_dict.get(active_build_plate, None)
100104

101-
# Get some vars (I cannot find the correct value)
102105
printTemp = None
103106
bedTemp = None
104107
for x in gcode_list:
105108
if ("M190" in x or "M140" in x ) and bedTemp is None:
106-
for y in re.findall(r"(M140|M190) S(\d+)", x):
107-
#Logger.log("d","Bed:" + y[1])
109+
for y in re.findall(r"(M190|M140) S(\d+)", x):
108110
bedTemp = y[1]
109-
break
111+
break;
110112
if ("M109" in x or "M104" in x ) and printTemp is None:
111113
for y in re.findall(r"(M109|M104) S(\d+)", x):
112-
#Logger.log("d","Extruder:" + y[1])
113114
printTemp = y[1]
114-
break
115-
if printTemp is not None and bedTemp is not None:
116-
break
115+
break;
116+
if not (printTemp is None or bedTemp is None):
117+
break;
118+
117119
print_info = Application.getInstance().getPrintInformation()
118120
feature_times = print_info.getFeaturePrintTimes()
119121
estiTime = 0 #in Seconds
120122
for x in feature_times:
121-
#Logger.log("d",x+":"+str(int(feature_times[x])) + " Seconds")
122123
estiTime += int(feature_times[x])
124+
123125
# Generate snapshot
124-
self._createSnapshot()
125-
if self._snapshot:
126-
Logger.log("d","Snapshot created.")
126+
base64_bytes = b""
127+
ss = self._createSnapshot()
128+
if ss:
127129
thumbnail_buffer = QBuffer()
128130
thumbnail_buffer.open(QBuffer.ReadWrite)
129-
thumbnail_image = self._snapshot
130-
thumbnail_image.save(thumbnail_buffer, "PNG")
131+
ss.save(thumbnail_buffer, "PNG")
131132
base64_bytes = base64.b64encode(thumbnail_buffer.data())
132133
thumbnail_buffer.close()
133-
else:
134-
base64_bytes = b""
134+
135135
# Start header
136-
stream.write(";Header Start\n\n")
137136
gcode_buffer = ""
138137
header_buffer = False
139-
model_line_count = 0
138+
model_line_count = 22
140139
if gcode_list is not None:
141140
has_settings = False
142-
for gcode in gcode_list:
143-
if gcode[:len(self._setting_keyword)] == self._setting_keyword:
144-
has_settings = True
145-
# Move FLAVOR/TIME/... block to top
146-
if "FLAVOR" not in gcode:
147-
model_line_count += len(gcode.splitlines()) # Add lines to model_line_count for header
148-
gcode_buffer += gcode + "\n" # Add extra newline for each layer, for readability of gcode
141+
is_gcode_file = False
142+
for line, gcode in enumerate(gcode_list):
143+
if line is 0 and len(re.findall(r"\n", gcode)) is 1:
144+
is_gcode_file = True
145+
146+
if is_gcode_file:
147+
gcode_buffer += gcode
148+
149149
else:
150-
# Split header lines and write to buffer
151-
header_buffer = gcode.splitlines(keepends=True)
152-
# Combine everything
153-
stream.write(header_buffer[0]) # FLAVOR
154-
stream.write(header_buffer[1]) # TIME
155-
stream.write(header_buffer[2]) # Filament used
156-
stream.write(header_buffer[3]) # Layer height
157-
stream.write("\n\n;header_type: 3dp\n")
158-
if base64_bytes:
159-
stream.write(";thumbnail: data:image/png;base64,")
160-
stream.write(base64_bytes.decode("ascii"))
161-
stream.write("\n")
162-
stream.write(";file_total_lines: %s\n" % model_line_count)
163-
stream.write(";estimated_time(s): %s\n" % estiTime)
164-
stream.write(";nozzle_temperature(°C): %s\n" % printTemp)
165-
stream.write(";build_plate_temperature(°C): %s\n" % bedTemp)
166-
stream.write(header_buffer[7].replace("MAXX:","max_x(mm): ")) # max_x
167-
stream.write(header_buffer[8].replace("MAXY:","max_y(mm): ")) # max_y
168-
stream.write(header_buffer[9].replace("MAXZ:","max_z(mm): ")) # max_z
169-
stream.write(header_buffer[4].replace("MINX:","min_x(mm): ")) # min_x
170-
stream.write(header_buffer[5].replace("MINY:","min_y(mm): ")) # min_y
171-
stream.write(header_buffer[6].replace("MINZ:","min_z(mm): ")) # min_z
172-
stream.write("\n;Header End\n\n")
173-
# Add some useful comments, conform Luban generated code, and/or what I deem usefull
174-
gcode_buffer = re.sub(r"(M190 S\d+)",r"\1 ;Wait for Bed Temperature", gcode_buffer)
175-
gcode_buffer = re.sub(r"(M109 S\d+)",r"\1 ;Wait for Hotend Temperature", gcode_buffer)
176-
gcode_buffer = re.sub(r"(G92 E0)",r"\1 ;Reset the extruder's origin/length", gcode_buffer)
150+
if gcode[:len(self._setting_keyword)] == self._setting_keyword:
151+
has_settings = True
152+
if ";FLAVOR:" not in gcode:
153+
model_line_count += len(gcode.splitlines()) + 1
154+
gcode_buffer += gcode + "\n"
155+
else:
156+
# Split header lines and write to buffer
157+
header_buffer = gcode.splitlines(keepends=True)
158+
159+
if not is_gcode_file:
160+
if not has_settings:
161+
settings = self._serialiseSettings(Application.getInstance().getGlobalContainerStack())
162+
model_line_count += len(settings.splitlines())
163+
# Combine everything
164+
stream.write(";Header Start\n\n")
165+
stream.write(header_buffer[0]) # FLAVOR
166+
stream.write(header_buffer[1]) # TIME
167+
stream.write(header_buffer[2]) # Filament used
168+
stream.write(header_buffer[3]) # Layer height
169+
stream.write("\n;header_type: 3dp\n")
170+
if base64_bytes:
171+
stream.write(";thumbnail: data:image/png;base64,")
172+
stream.write(base64_bytes.decode("ascii"))
173+
stream.write("\n")
174+
stream.write(";file_total_lines: %s\n" % model_line_count)
175+
stream.write(";estimated_time(s): %s\n" % estiTime)
176+
stream.write(";nozzle_temperature(°C): %s\n" % printTemp)
177+
stream.write(";build_plate_temperature(°C): %s\n" % bedTemp)
178+
stream.write(header_buffer[7].replace("MAXX:","max_x(mm): ")) # max_x
179+
stream.write(header_buffer[8].replace("MAXY:","max_y(mm): ")) # max_y
180+
stream.write(header_buffer[9].replace("MAXZ:","max_z(mm): ")) # max_z
181+
stream.write(header_buffer[4].replace("MINX:","min_x(mm): ")) # min_x
182+
stream.write(header_buffer[5].replace("MINY:","min_y(mm): ")) # min_y
183+
stream.write(header_buffer[6].replace("MINZ:","min_z(mm): ")) # min_z
184+
stream.write("\n;Header End\n\n")
185+
177186
stream.write(gcode_buffer)
187+
178188
# Serialise the current container stack and put it at the end of the file.
179-
if not has_settings:
180-
settings = self._serialiseSettings(Application.getInstance().getGlobalContainerStack())
189+
if not has_settings and not is_gcode_file:
181190
stream.write(settings)
191+
182192
return True
183193

184194
self.setInformation(catalog.i18nc("@warning:status", "Please prepare G-code before exporting."))

SM2OutputDeviceManager.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ def connect(self) -> str:
186186
Message(title="Error", text=str(e), dismissable=True).show()
187187
return self._auth_token
188188

189+
def disconnect(self):
190+
requests.post("http://" + self._address + self._api_prefix + "/disconnect",
191+
data={"token": self._auth_token})
192+
Logger.log("d", "/disconnect")
193+
189194
def check_status(self):
190195
try:
191196
conn = requests.get("http://" + self._address + self._api_prefix + "/status", params={"token": self._auth_token})
@@ -243,6 +248,7 @@ def _startUpload(self):
243248

244249
def _onUploadCompleted(self, reply):
245250
self._progress.hide()
251+
self.disconnect()
246252
if not reply.error():
247253
Message(
248254
title="Sent to {}".format(self._id),

plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"name": "Snapmaker 2.0 Connection",
33
"author": "https://github.com/macdylan",
4-
"version": "4.0.0",
4+
"version": "4.1.0",
55
"api": 6,
6-
"supported_sdk_versions": ["6.0.0", "6.1.0", "6.2.0", "6.3.0", "7.0.0", "7.1.0", "7.2.0", "7.3.0", "7.4.0", "7.5.0"],
6+
"supported_sdk_versions": ["6.0.0", "6.1.0", "6.2.0", "6.3.0", "7.0.0", "7.1.0", "7.2.0", "7.3.0", "7.4.0", "7.5.0", "7.6.0", "7.7.0"],
77
"description": "Output Device plugin for Snapmaker 2.0"
88
}

0 commit comments

Comments
 (0)