-
Notifications
You must be signed in to change notification settings - Fork 0
/
gcodeGoblin.py
166 lines (147 loc) · 6.59 KB
/
gcodeGoblin.py
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
import sys
import zipfile
import hashlib
import os
import re
def remove_extrusion(line):
if line.startswith('G1 ') or line.startswith('G2 ') or line.startswith('G3 '):
return re.sub(r'\sE[0-9.-]+', '', line)
return line
def extract_gcode_content(zip_filename):
"""Extracts lines from the first .gcode file found in the Metadata/ directory."""
content = None
original_file_name = None
with zipfile.ZipFile(zip_filename, 'r') as zip_file:
for file_info in zip_file.infolist():
if file_info.filename.startswith('Metadata/') and file_info.filename.endswith('.gcode'):
with zip_file.open(file_info.filename) as gcode_file:
content = gcode_file.read().decode().splitlines()
original_file_name = file_info.filename
break
return content, original_file_name
def detect_command(command, line):
"""Checks for command insensitivity."""
line = line.replace(" ", "")
command = command.replace(" ", "")
return line.strip().lower().startswith(command.lower())
def process_lines(lines):
"""Processes lines from the .gcode file."""
buffers = {}
current_buffer = None
output = []
cutting = False
disable_extrusion = False
lineno = 0
for line in lines:
lineno += 1
line = line.strip() # Remove leading/trailing whitespace
if not cutting:
if disable_extrusion:
output.append(remove_extrusion(line))
else:
output.append(line)
# Check for buffer commands with insensitivity
if detect_command('; START_COPY:', line):
# Extract the buffer name
buffer_name = line.split(':')[1].strip()
print(f"Start copy {buffer_name}")
buffers[buffer_name] = [] # Initialize the buffer
output.append(f'; starting to copy into buffer {buffer_name}')
current_buffer = buffer_name
elif detect_command('; STOP_COPY:', line):
output.append(f'; stopping copy into buffer {current_buffer}')
buffer_name = line.split(':')[1].strip()
print(f"Stop copy {buffer_name}")
current_buffer = None # Stop copying lines
elif detect_command('; STOP_EXTRUDE:', line):
print("Disabling extrusion")
disable_extrusion=True
elif detect_command('; START_EXTRUDE:', line):
print("Enabling extrusion")
disable_extrusion=False
elif current_buffer:
# Add line to the current buffer
buffers[current_buffer].append(line)
elif detect_command('; PASTE:', line):
# Extract the buffer name to paste
buffer_name = line.split(':')[1].strip()
print(f"paste buffer {buffer_name}")
if buffer_name in buffers:
output.append(f'; pasting from buffer {buffer_name} into output:')
# Output all lines stored in the buffer
for buffered_line in buffers[buffer_name]:
output.append(buffered_line)
output.append("; END OF PASTE BUFFER")
elif detect_command('; REMOVE_EXTRUSION:', line):
buffer_name = line.split(':')[1].strip()
if buffer_name in buffers:
print(f'Removing extrusion activity from Buffer {buffer_name}')
newBuf = []
for buffered_line in buffers[buffer_name]:
newBuf.append(remove_extrusion(buffered_line))
buffers[buffer_name] = newBuf
elif detect_command('; PRINT_BUFFER', line):
buffer_name = line.split(':')[1].strip()
if buffer_name in buffers:
print(f'; pasting from buffer {buffer_name} into output:')
# Output all lines stored in the buffer
for buffered_line in buffers[buffer_name]:
print(buffered_line)
print(f"; END OF PASTE BUFFER {buffer_name}")
elif detect_command('; START_CUT', line):
output.append("; CUT START")
print("Cut start")
cutting = True
elif detect_command('; STOP_CUT', line):
output.append("; CUT STOPPED")
print("Cut stop")
cutting = False
return output
def calculate_md5(file_content):
"""Calculates the MD5 checksum of the given file content."""
md5 = hashlib.md5()
md5.update(file_content.encode('utf-8'))
return md5.hexdigest()
def process_zip_file(zip_filename):
"""Main function to process the .gcode file in the zip."""
lines, original_file_name = extract_gcode_content(zip_filename)
if lines is not None and original_file_name is not None:
new_content = process_lines(lines)
md5_checksum = calculate_md5('\n'.join(new_content))
# Create a new zip file with .fixed.3mf extension
fixed_zip_filename = zip_filename.replace('.3mf', '.fixed.3mf')
with zipfile.ZipFile(zip_filename, 'r') as original_zip:
with zipfile.ZipFile(fixed_zip_filename, 'w') as fixed_zip:
for file_info in original_zip.infolist():
# Write all files except the original .gcode and .md5
if file_info.filename != original_file_name and not file_info.filename.endswith('.md5'):
fixed_zip.writestr(file_info, original_zip.read(file_info.filename))
# Write the processed .gcode file
fixed_zip.writestr(original_file_name, '\n'.join(new_content).encode('utf-8'))
# Write the new .md5 file
md5_file_name = original_file_name + '.md5'
fixed_zip.writestr(md5_file_name, md5_checksum)
def process_gcode(filename):
with open(filename, 'r') as file:
lines = file.readlines()
new_content = process_lines(lines)
fixed_filename = filename.replace(".gcode", ".fixed.gcode")
with open(fixed_filename, 'w') as out_file:
for line in new_content:
out_file.write(line)
out_file.write("\n")
def print_message():
print("Usage: python script.py <filename>")
print(" <filename> can be a .3mf file or a gcode file")
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) < 2:
print_message()
filename = sys.argv[1]
if filename.endswith(".3mf"):
process_zip_file(filename)
elif filename.endswith(".gcode"):
process_gcode(filename)
else:
print("ERROR: filename is neither .3mf nor .gcode")
print_message()