Optimize G-code processing time by using M73OffsetTemplate for plate number offsets

This commit is contained in:
hyyz17200
2026-05-08 12:02:15 +08:00
parent 7dabdc676a
commit 8126a9c608
4 changed files with 158 additions and 15 deletions
+55
View File
@@ -71,6 +71,61 @@ class GcodePrepareCacheTest(unittest.TestCase):
self.assertEqual(captured_gcode.count("G0 Y250 F3000 ;Patched"), 3)
self.assertNotIn("G0 Y254 F3000", captured_gcode)
def test_repeated_copies_prepare_m73_template_once_per_member(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
source_3mf = root / "source.3mf"
output_3mf = root / "out.3mf"
swap_gcode = root / "swap.gcode"
self.write_archive(source_3mf)
swap_gcode.write_text("; swap\nG1 X5\n", encoding="utf-8")
m73_template_calls = 0
captured_gcode = ""
original_prepare_m73 = builder.prepare_m73_offset_template
def count_m73_template_calls(text: str):
nonlocal m73_template_calls
m73_template_calls += 1
return original_prepare_m73(text)
def capture_gcode(
base_3mf: Path,
output_3mf: Path,
gcode_bytes: bytes,
sources: list[builder.PlateSource],
options: BuildOptions,
) -> str:
nonlocal captured_gcode
captured_gcode = gcode_bytes.decode("utf-8")
return hashlib.md5(gcode_bytes).hexdigest()
options = BuildOptions(
swap_gcode=swap_gcode,
output_3mf=output_3mf,
apply_gcode_patches=False,
show_plate_number=True,
swap_after_final=False,
line_ending="lf",
add_preview_label=False,
)
with (
patch.object(builder, "prepare_m73_offset_template", side_effect=count_m73_template_calls),
patch.object(
builder,
"write_output_3mf",
side_effect=capture_gcode,
),
):
result = builder.build_packed_3mf([PlateJob(source_3mf, 3)], options)
self.assertEqual(result.plate_count, 3)
self.assertEqual(m73_template_calls, 1)
self.assertIn("M73 P0 R6010", captured_gcode)
self.assertIn("M73 P0 R12010", captured_gcode)
self.assertIn("M73 P0 R18010", captured_gcode)
@staticmethod
def write_archive(path: Path) -> None:
slice_info = """<?xml version="1.0" encoding="UTF-8"?>
+42
View File
@@ -0,0 +1,42 @@
from __future__ import annotations
import unittest
from a1_swap_mod_packer.gcode import M73_RE, apply_plate_number_offset, prepare_m73_offset_template
class M73OffsetTemplateTest(unittest.TestCase):
def test_template_matches_previous_regex_replacement_semantics(self) -> None:
gcode = (
"M73 P0 R10\n"
"; M73 P0 R20\n"
" M73 P0 R30\n"
"M73 P50 R5999 ; comment\n"
"G1 X1\n"
"M73 P100 R0\n"
)
def previous_apply(text: str, plate_number: int) -> str:
minute_offset = plate_number * 100 * 60
def replace(match) -> str:
prefix = match.group(1)
remaining_minutes = int(match.group(2)) + minute_offset
suffix = match.group(3)
return f"{prefix}{remaining_minutes}{suffix}"
return M73_RE.sub(replace, text)
template = prepare_m73_offset_template(gcode)
for plate_number in (1, 2, 10):
self.assertEqual(template.apply(plate_number), previous_apply(gcode, plate_number))
self.assertEqual(apply_plate_number_offset(gcode, plate_number), previous_apply(gcode, plate_number))
def test_template_without_m73_matches_returns_original_text(self) -> None:
gcode = "G1 X1\n; M73 P0 R10\n"
template = prepare_m73_offset_template(gcode)
self.assertEqual(template.apply(3), gcode)
if __name__ == "__main__":
unittest.main()