metadata: add support for object postprocessing

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2021-11-24 04:56:42 -05:00 committed by Eric Callahan
parent f00263b782
commit 6bd46a4433
1 changed files with 75 additions and 4 deletions

View File

@ -30,6 +30,13 @@ from typing import (
if TYPE_CHECKING:
pass
HAS_OBJECT_PROCESSING = True
try:
from preprocess_cancellation import preprocessor
except ImportError:
HAS_OBJECT_PROCESSING = False
UFP_MODEL_PATH = "/3D/model.gcode"
UFP_THUMB_PATH = "/Metadata/thumbnail.png"
@ -114,9 +121,29 @@ class BaseSlicer(object):
else:
return None
def _check_has_objects(self,
data: str,
pattern: Optional[str] = None
) -> bool:
match = re.search(r"\nDEFINE_OBJECT NAME=", data)
if match is not None:
# Objects alread processed
return False
# Always check M486
patterns = [r"\nM486"]
if pattern is not None:
patterns.append(pattern)
for regex in patterns:
if re.search(regex, data) is not None:
return True
return False
def check_identity(self, data: str) -> Optional[Dict[str, str]]:
return None
def has_objects(self) -> bool:
return self._check_has_objects(self.header_data)
def parse_gcode_start_byte(self) -> Optional[int]:
m = re.search(r"\n[MG]\d+\s.*\n", self.header_data)
if m is None:
@ -191,6 +218,10 @@ class PrusaSlicer(BaseSlicer):
}
return None
def has_objects(self) -> bool:
return self._check_has_objects(
self.header_data, r"\n; printing object")
def parse_first_layer_height(self) -> Optional[float]:
# Check percentage
pct = _regex_find_first(
@ -348,6 +379,10 @@ class Cura(PrusaSlicer):
}
return None
def has_objects(self) -> bool:
return self._check_has_objects(
self.header_data, r"\n;MESH:")
def parse_first_layer_height(self) -> Optional[float]:
return _regex_find_first(r";MINZ:(\d+\.?\d*)", self.header_data)
@ -547,6 +582,10 @@ class IdeaMaker(PrusaSlicer):
}
return None
def has_objects(self) -> bool:
return self._check_has_objects(
self.header_data, r"\n;PRINTING:")
def parse_first_layer_height(self) -> Optional[float]:
layer_info = _regex_find_floats(
r";LAYER:0\s*.*\s*;HEIGHT.*", self.header_data)
@ -676,7 +715,20 @@ SUPPORTED_DATA = [
'thumbnails', 'first_layer_bed_temp', 'first_layer_extr_temp',
'gcode_start_byte', 'gcode_end_byte']
def extract_metadata(file_path: str) -> Dict[str, Any]:
def process_objects(file_path: str) -> None:
fname = os.path.basename(file_path)
log_to_stderr(f"Performing Object Processing on file: {fname}")
with tempfile.TemporaryDirectory() as tmp_dir_name:
tmp_file = os.path.join(tmp_dir_name, fname)
with open(file_path, 'r') as in_file:
with open(tmp_file, 'w') as out_file:
preprocessor(in_file, out_file)
shutil.move(tmp_file, file_path)
def extract_metadata(file_path: str,
check_objects: bool
) -> Dict[str, Any]:
metadata: Dict[str, Any] = {}
slicers = [s(file_path) for s in SUPPORTED_SLICERS]
header_data = footer_data = ""
@ -706,11 +758,18 @@ def extract_metadata(file_path: str) -> Dict[str, Any]:
else:
footer_data = header_data
slicer.set_data(header_data, footer_data, size)
need_proc = check_objects and slicer.has_objects()
for key in SUPPORTED_DATA:
func = getattr(slicer, "parse_" + key)
result = func()
if result is not None:
metadata[key] = result
if need_proc:
process_objects(file_path)
# After processing the file has changed, update size and
# modified fields
metadata['size'] = os.path.getsize(file_path)
metadata['modified'] = os.path.getmtime(file_path)
return metadata
def extract_ufp(ufp_path: str, dest_path: str) -> None:
@ -743,7 +802,11 @@ def extract_ufp(ufp_path: str, dest_path: str) -> None:
except Exception:
log_to_stderr(f"Error removing ufp file: {ufp_path}")
def main(path: str, filename: str, ufp: Optional[str]) -> None:
def main(path: str,
filename: str,
ufp: Optional[str],
check_objects: bool
) -> None:
file_path = os.path.join(path, filename)
if ufp is not None:
extract_ufp(ufp, file_path)
@ -752,7 +815,7 @@ def main(path: str, filename: str, ufp: Optional[str]) -> None:
log_to_stderr(f"File Not Found: {file_path}")
sys.exit(-1)
try:
metadata = extract_metadata(file_path)
metadata = extract_metadata(file_path, check_objects)
except Exception:
log_to_stderr(traceback.format_exc())
sys.exit(-1)
@ -783,5 +846,13 @@ if __name__ == "__main__":
"-u", "--ufp", metavar="<ufp file>", default=None,
help="optional path of ufp file to extract"
)
parser.add_argument(
"-o", "--check-objects", dest='check_objects', action='store_true',
help="process gcode file for exclude opbject functionality")
args = parser.parse_args()
main(args.path, args.filename, args.ufp)
if not HAS_OBJECT_PROCESSING:
log_to_stderr("Module 'preprocess-cancellation' failed to load")
check_objects = args.check_objects and HAS_OBJECT_PROCESSING
enabled_msg = "enabled" if check_objects else "disabled"
log_to_stderr(f"Object Processing is {enabled_msg}")
main(args.path, args.filename, args.ufp, check_objects)