59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
import re
|
|
import json
|
|
from collections import Counter
|
|
from typing import Any
|
|
|
|
def parse_gcode_metadata(gcode: str) -> dict[str, Any]:
|
|
"""Extracts metadata fields from G-code comments."""
|
|
fields = {}
|
|
|
|
# 1. Time per print (decimal hours)
|
|
time_match = re.search(r"; estimated printing time \(normal mode\) = (.*)", gcode)
|
|
if time_match:
|
|
time_str = time_match.group(1)
|
|
h = re.search(r"(\d+)h", time_str)
|
|
m = re.search(r"(\d+)m", time_str)
|
|
s = re.search(r"(\d+)s", time_str)
|
|
total_hours = 0.0
|
|
if h: total_hours += float(h.group(1))
|
|
if m: total_hours += float(m.group(1)) / 60.0
|
|
if s: total_hours += float(s.group(1)) / 3600.0
|
|
fields["Time per print"] = round(total_hours, 2)
|
|
|
|
# 2. Parts per print
|
|
parts_match = re.search(r"; objects_info = (.*)", gcode)
|
|
if parts_match:
|
|
try:
|
|
info = json.loads(parts_match.group(1))
|
|
fields["Parts per print"] = len(info.get("objects", []))
|
|
fields["objects_info"] = info
|
|
except Exception: pass
|
|
|
|
# 3. Weight per print
|
|
weight_match = re.search(r"; total filament used \[g\] = ([\d\.]+)", gcode)
|
|
if weight_match:
|
|
fields["Weight per print"] = int(float(weight_match.group(1)))
|
|
|
|
return fields
|
|
|
|
def get_gcode_name_from_metadata(gcode: str, default: str = "output") -> str:
|
|
"""Generates a descriptive name for the G-code based on its objects_info metadata."""
|
|
parts_match = re.search(r"; objects_info = (.*)", gcode)
|
|
|
|
filament_match = re.search(r"; filament_type = (.*)", gcode)
|
|
filament = filament_match[1] if filament_match else ''
|
|
|
|
printer_match = re.search(r"; printer_model = (.*)", gcode)
|
|
printer = printer_match[1] if printer_match else ''
|
|
|
|
if parts_match:
|
|
try:
|
|
gcode_info = json.loads(parts_match.group(1))
|
|
names: list[str] = [str(v['name'].split(" id:")[0]) for v in gcode_info['objects']]
|
|
counts = Counter(names)
|
|
object_names = "-".join(f"{c}x{n}" if c > 1 else n for n, c in counts.items())
|
|
parts = [object_names, filament, printer]
|
|
return "-".join([str(p) for p in parts if p])
|
|
except:
|
|
pass
|
|
return default
|