Skip to content

Commit 69a8ec5

Browse files
committed
bugfix: fix temperature with a floating point.
The start gcode macros in recent versions of Cura format the print temperature as a floating point. Other temperature commands in the gcode don't have such behavior. On Finder (version 1?) with the more recent firmware, this causes the temperature to be the fixed to start at 185C, which appears to be the "default start temperature" or some rounding error when reading the floating point temperature. This commit fixes that by parsing the 'M104 SXXX' commands, and changing the temperature by converting it to integer. This also allows the temperature to be embedded to the .gx file header. I took the opportunity to move the parsing commands into the gx.py script, as a way to potentially easy the proccess to make this a standalone script that can potentially be used by other slicers/software. Fixes #21 Related to #2 and #16
1 parent abd556b commit 69a8ec5

File tree

4 files changed

+101
-34
lines changed

4 files changed

+101
-34
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ plugins/FlashforgeFinderIntegration/printer/defs/finder.def.json:
5858
git submodule init
5959
git submodule update
6060

61-
release: build
61+
test:
62+
find plugins -type f -iname '*_test.py' | xargs -I{} python3 {}
63+
64+
release: build test
6265
if [ x"$(VERSION)" = x"master" ] ; then echo "Unable to release from master. Use make VERSION=X.Y.Z" ; exit 1; fi
6366
git tag v$(VERSION)
6467
git push --tags

plugins/GXWriter/GXWriter.py

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
from UM.i18n import i18nCatalog
1515
catalog = i18nCatalog("cura")
1616

17-
import re
1817
from io import StringIO, BufferedIOBase
1918
from typing import cast, List
20-
from . import gx
19+
from .gx import GX
2120

2221
qt_version = 6
2322
try:
@@ -26,17 +25,6 @@
2625
qt_version = 5
2726
from PyQt5 import QtGui, QtCore
2827

29-
# Helper function that extracts values from gcode to add to the binary header.
30-
def getValue(line, key, default=None):
31-
if key not in line:
32-
return default
33-
else:
34-
subPart = line[line.find(key) + len(key):]
35-
m = re.search('^-?[0-9]+\\.?[0-9]*', subPart)
36-
try:
37-
return float(m.group(0))
38-
except:
39-
return default
4028

4129
# Implements a MeshWriter that creates the xgcode header before the gcode
4230
# content.
@@ -77,30 +65,14 @@ def write(self, stream, nodes: List[SceneNode], mode = MeshWriter.OutputMode.Bin
7765
def modify(self, gcode):
7866
try:
7967
# Initialize GX header variables
80-
g = gx.GX()
81-
g.gcode = gcode.encode('latin-1')
82-
# Parse values from original gcode
83-
self._parse_gcode_info(g, gcode)
84-
self._createSnapshot(g)
85-
return g.encode()
68+
gx = GX.from_gcode(gcode)
69+
# Add snapshot image from Cura
70+
self._createSnapshot(gx)
71+
return gx.encode()
8672
except Exception:
8773
Logger.logException("w", "\n*** Failed to create gx file, defaulting to write regular gcode!!! ***\n")
8874
return gcode.encode('latin-1')
8975

90-
def _parse_gcode_info(self, gx, gcode):
91-
for line in gcode.split("\n"):
92-
if line.startswith(';TIME:'):
93-
gx.print_time = int(getValue(line, ';TIME:', 0))
94-
if line.startswith(';Filament used:'):
95-
f = float(line.split(':')[1].split('m')[0].strip())
96-
f = f*100
97-
gx.filament_usage = int(f)
98-
if line.startswith(';Layer height:'):
99-
f = float(getValue(line, ';Layer height:', 0))
100-
f = f*1000
101-
gx.layer_height = int(f)
102-
Logger.log("i", "Updated values from struct =>", vars(gx))
103-
10476
def _createSnapshot(self, g, *args):
10577
Logger.log("i", "Creating thumbnail image ...")
10678
try:

plugins/GXWriter/gx.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@
66

77
import struct
88
import base64
9+
import re
10+
11+
# Helper function that extracts values from gcode to add to the binary header.
12+
def getValue(line, key, default=None):
13+
if key not in line:
14+
return default
15+
else:
16+
subPart = line[line.find(key) + len(key):]
17+
m = re.search('^-?[0-9]+\\.?[0-9]*', subPart)
18+
try:
19+
return float(m.group(0))
20+
except:
21+
return default
922

1023
class GX(object):
1124
"""
@@ -103,6 +116,36 @@ def _encode(self):
103116
buff+= self.gcode
104117
return buff
105118

119+
@staticmethod
120+
def from_gcode(gcode):
121+
gx = GX()
122+
gx.gcode = gcode.encode('latin-1')
123+
for line in gcode.split("\n"):
124+
if line.startswith(';TIME:'):
125+
gx.print_time = int(getValue(line, ';TIME:', 0))
126+
if line.startswith(';Filament used:'):
127+
f = float(line.split(':')[1].split('m')[0].strip())
128+
f = f*100
129+
gx.filament_usage = int(f)
130+
if line.startswith(';Layer height:'):
131+
f = float(getValue(line, ';Layer height:', 0))
132+
f = f*1000
133+
gx.layer_height = int(f)
134+
if line.startswith('M104 S'):
135+
# Fixes temperature if expressed in float (195.0 -> 195)
136+
args = []
137+
for a in line.split(' '):
138+
if a.startswith('S'):
139+
t = float(a.replace('S', ''))
140+
t = int(t)
141+
a = "S{}".format(t)
142+
if gx.print_temperature <= 0.00:
143+
# Stores the first temperature to the xgcode header
144+
gx.print_temperature = t
145+
args.append(a)
146+
gx.gcode = gx.gcode.replace(line.encode(), ' '.join(args).encode())
147+
return gx
148+
106149
# base64 --wrap=80 testdata/cura.bmp | xclip -sel clip
107150
_SAMPLE_BMP = base64.decodebytes("""
108151
Qk12OAAAAAAAADYAAAAoAAAAUAAAADwAAAABABgAAAAAAEA4AADDDgAAww4AAAAAAAAAAAAAnJycnJyc

plugins/GXWriter/gx_test.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
from gx import GX
3+
4+
test_gcode = """;FLAVOR:Marlin
5+
;TIME:1066
6+
;Filament used: 0.681442m
7+
;Layer height: 0.12
8+
;MINX:-14
9+
;MINY:-14
10+
;MINZ:0.2
11+
;MAXX:14
12+
;MAXY:14
13+
;MAXZ:10.04
14+
;TARGET_MACHINE.NAME:Flashforge Finder
15+
;Generated with Cura_SteamEngine 5.6.0
16+
M82 ;absolute extrusion mode
17+
M140 S0
18+
M104 S195.0 T0
19+
M104 S0 T1
20+
M107
21+
G90
22+
G28
23+
M132 X Y Z A B
24+
G1 Z50.00 F400
25+
G161 X Y F3300
26+
M6 T0
27+
M907 X100 Y100 Z40 A80 B20
28+
M108 T0
29+
G1 Z.20 F400
30+
G92 E0
31+
G92 E0
32+
G1 F1800 E-1.3
33+
;LAYER_COUNT:83
34+
;LAYER:0
35+
M106 S255
36+
G0 F3000 X14 Y9.314 Z0.2"""
37+
38+
class TestGX(unittest.TestCase):
39+
40+
def test_from_gcode(self):
41+
gx = GX.from_gcode(test_gcode)
42+
result = gx.encode().decode('latin1')
43+
print("Resulting gcode: ", result)
44+
self.assertFalse(' S195.0 ' in result)
45+
self.assertTrue(' S195 ' in result)
46+
self.assertTrue('xgcode' in result)
47+
48+
if __name__ == '__main__':
49+
unittest.main()

0 commit comments

Comments
 (0)