Skip to content

Commit c6a5f41

Browse files
committed
feat: Add header block to G-code for BrickLayers debug info
Adds a header section to the beginning of the G-code file containing useful metadata about the BrickLayers post-processing. This can help with debugging and reproducibility. The header can be disabled with the `-noHeader` option. Example of a generated header: ;================================ ;== BrickLayers Post-Processed ;== Script Version: v0.2.1-6-g2044cde ;== Python Interpreter: CPython ;== Python Version: 3.9.21 ;== OS: Darwin 23.6.0 ;== Input Source: Command Line ;== Starting at Layer: 3 ;== Ignored Layers: [] ;== Extrusion Multiplier: 1.05 ;================================
1 parent b7be66a commit c6a5f41

File tree

1 file changed

+89
-17
lines changed

1 file changed

+89
-17
lines changed

bricklayers.py

Lines changed: 89 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,9 @@ def __init__(self, extrusion_global_multiplier: float = 1.05, start_at_layer: in
963963
self.last_internalperimeter_state = None # Experiment...
964964
self.last_internalperimeter_xy_line = None # Experiment...
965965
self.last_noninternalperimeter_state = None # Experiment...
966-
self.last_noninternalperimeter_xy_line = None # Experiment...
966+
self.last_noninternalperimeter_xy_line = None # Used to re-conciliate the moved lines to their new surroundings
967+
self.header_info = {} # Any text to be included at the beginning of the exported file
968+
self.enable_header = False # If turned false, won't output the Bricklayers header information to the file
967969

968970
def set_progress_callback(self, callback: Callable[[dict], None]):
969971
"""Sets the progress callback function."""
@@ -1001,7 +1003,37 @@ def new_line_from_multiplier(myline, extrusion_multiplier):
10011003
myline.gcode = command + "\n"
10021004
return myline # keeps the states, just change the actual gcode string
10031005

1006+
def set_header_info(self, dict):
1007+
self.header_info = dict
10041008

1009+
def gen_header_lines(self, gcodeline_wrap = True) -> list:
1010+
"""
1011+
Args:
1012+
gcodeline_wrap (bool):
1013+
- True returns a list of GCodeLine objects.
1014+
- False returns a list of plain string lines.
1015+
"""
1016+
t = []
1017+
pf = ";=="
1018+
bar = "=============================="
1019+
1020+
t.append(bar)
1021+
t.append(" BrickLayers Post-Processed")
1022+
# Loop through key/values to build header
1023+
for key, value in self.header_info.items():
1024+
t.append(f" {key}: {value}")
1025+
t.append(bar)
1026+
t.append("")
1027+
1028+
# Prefix each line with pf and add line breaks
1029+
output = []
1030+
for line in t:
1031+
txt = f"{pf}{line}\n" if line else f"\n"
1032+
if gcodeline_wrap:
1033+
output.append(GCodeLine.from_gcode(txt))
1034+
else:
1035+
output.append(txt)
1036+
return output
10051037

10061038
def travel_to(self, target_state, simulator, feature, loop = None, start_state = None, z = None):
10071039
from_gcode = GCodeLine.from_gcode # faster lookup
@@ -1656,6 +1688,10 @@ def process_gcode(self, gcode_stream):
16561688
knife_activated = False
16571689
layer_changed_during_internal_perimeter = False
16581690

1691+
# includes the BrickLayer Header Information to the GCode
1692+
if self.enable_header:
1693+
buffer_lines.extend(self.gen_header_lines())
1694+
16591695
# Process the G-code
16601696
#READING ONE LINE AT A TIME FROM A GENERATOR (the input)
16611697
for line_number, line in enumerate(gcode_stream, start=1):
@@ -2201,6 +2237,10 @@ def expand_ranges(ranges):
22012237
"1: Just Filenames\n"
22022238
"2: Progress (default)\n"
22032239
"3: Progress all lines, a bit slower\n\n")
2240+
parser.add_argument("-noHeader", action="store_true",
2241+
help="\nSkip adding BrickLayers header to your G-code\n"
2242+
"Recommended only for automation\n"
2243+
"(header is helpful for debugging)\n\n")
22042244

22052245
args = parser.parse_args()
22062246

@@ -2298,6 +2338,50 @@ def gcode_opener(path, flags):
22982338
if verbosity == 1:
22992339
print(input_file)
23002340

2341+
2342+
# Setting up the BrickProcessor:
2343+
processor = BrickLayersProcessor(
2344+
extrusion_global_multiplier=args_dict["extrusionmultiplier"],
2345+
start_at_layer=args_dict["startatlayer"],
2346+
layers_to_ignore=final_ignored_layers,
2347+
verbosity=verbosity
2348+
)
2349+
processor.experimental_arcflick = False
2350+
processor.set_progress_callback(update_progress) # Full-fledged terminal progress indicator
2351+
#processor.set_progress_callback(update_progress_print) # Super simple progress-indicator example
2352+
2353+
2354+
# Detect interpreter
2355+
python_imp = platform.python_implementation()
2356+
python_ver = platform.python_version()
2357+
os_info = f"{platform.system()} {platform.release()}"
2358+
IS_CPYTHON = python_imp == "CPython"
2359+
IS_PYPY = python_imp == "PyPy"
2360+
2361+
# !! HEADER PRIVACY CONCERNS !!
2362+
#
2363+
# Certain information is very useful for debugging
2364+
# but could accidentally expose sensitive user data:
2365+
#
2366+
# - Interpreter Path: Can reveal usernames or computer-specific info
2367+
# - Script Arguments: Might contain file paths or other sensitive details
2368+
# - Input/Output Filenames: May identify personal projects or users
2369+
#
2370+
# DO NOT add sensitive information to the header.
2371+
# Keep the following list minimal, generic, and privacy-safe:
2372+
header_info = {
2373+
"Script Version" : __version__,
2374+
"Python Interpreter" : python_imp,
2375+
"Python Version" : python_ver,
2376+
"OS" : os_info,
2377+
"Input Source" : "Slicer" if is_uploading else "Command Line",
2378+
"Starting at Layer" : args_dict["startatlayer"],
2379+
"Ignored Layers" : final_ignored_layers,
2380+
"Extrusion Multiplier" : args_dict["extrusionmultiplier"]
2381+
}
2382+
processor.set_header_info(header_info)
2383+
processor.enable_header = not args_dict["noheader"]
2384+
23012385
if verbosity > 1:
23022386
import io
23032387
if os.name == "nt":
@@ -2318,28 +2402,16 @@ def gcode_opener(path, flags):
23182402
print(" Layers to Ignore: ", final_ignored_layers)
23192403
print(" Enabled: ", args_dict["enabled"])
23202404
print(" Verbosity: ", args_dict["verbosity"])
2405+
print(" Include Header: ", "No" if args_dict["noheader"] else "Yes")
2406+
print(" Python Interpreter: ", python_imp)
2407+
print(" Python Version: ", python_ver)
2408+
print(" OS: ", os_info)
23212409
print("\n")
23222410

23232411
logger.debug(input_file)
23242412
logger.debug(final_output_file)
23252413
input_file_size = os.path.getsize(input_file)
23262414

2327-
# Setting up the BrickProcessor:
2328-
processor = BrickLayersProcessor(
2329-
extrusion_global_multiplier=args_dict["extrusionmultiplier"],
2330-
start_at_layer=args_dict["startatlayer"],
2331-
layers_to_ignore=final_ignored_layers,
2332-
verbosity=verbosity
2333-
)
2334-
processor.experimental_arcflick = False
2335-
processor.set_progress_callback(update_progress) # Full-fledged terminal progress indicator
2336-
#processor.set_progress_callback(update_progress_print) # Super simple progress-indicator example
2337-
2338-
2339-
# Detect interpreter
2340-
IS_CPYTHON = platform.python_implementation() == "CPython"
2341-
IS_PYPY = platform.python_implementation() == "PyPy"
2342-
23432415
if verbosity > 0:
23442416
# Setup optional memory tracking
23452417
if IS_CPYTHON:

0 commit comments

Comments
 (0)