50 lines
1.8 KiB
Python
50 lines
1.8 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)
|
|
if parts_match:
|
|
try:
|
|
gcode_info = json.loads(parts_match.group(1))
|
|
names: list[str] = [str(v['name']) for v in gcode_info['objects']]
|
|
counts = Counter(names)
|
|
return "-".join(f"{c}x{n}" if c > 1 else n for n, c in counts.items())
|
|
except:
|
|
pass
|
|
return default
|