airtable+baserow batch

This commit is contained in:
Nicolas Predella 2026-05-20 22:00:19 +03:00
parent 6def135bbc
commit d4738c62e5

View file

@ -1115,111 +1115,103 @@ class ExecSliceNode_DatabaseSubmit(ExecSliceNode):
def init(self, context):
self._init_exec()
self.add_input("SLICESOCK_Gcode")
self.add_input("SLICESOCK_String", "Filename")
self.add_multi_input("SLICESOCK_Gcode", "Gcode")
def draw_buttons(self, context, layout):
super().draw_buttons(context, layout)
layout.prop(self, "record_id")
def _prepare_submission(self, operator=None) -> tuple[str, str, dict[str, str]]:
import re
import json
gcode: str = resolve_input(self.inputs.get("Gcode"))
if not gcode:
if operator: operator.report({'ERROR'}, "No Gcode to send")
return '', '', {}
filename: str = resolve_input(self.inputs.get("Filename")) or "output.gcode"
if not filename.endswith(".gcode"):
filename += ".gcode"
# Parse Metadata from Gcode
fields = {}
part_name = filename.split(".")[0]
fields["Part ID / Name"] = part_name
# 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", []))
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 gcode, filename, fields
def evaluate(self, operator=None):
from ...infra.networking.bgcode import convert_to_bgcode
from ...infra.networking.gcode_utils import get_gcode_name_from_metadata
import tempfile
import os
from pathlib import Path
gcode, filename, fields = self._prepare_submission(operator)
if not gcode: return 'error'
gcodes: str = self.resolve_multi_input("Gcode")
# Detect binary trigger in gcode comments
is_binary = "; binary_gcode = 1" in gcode
for gc in gcodes:
import re
import json
name_part = filename.split('.')[0]
filename = name_part + ".bgcode" if is_binary else ".gcode"
if not gc:
if operator: operator.report({'ERROR'}, "No Gcode to send")
continue
token_path = getattr(self, self._token_prop_name, "")
token = ""
if token_path:
abs_token_path = bpy.path.abspath(token_path)
if os.path.exists(abs_token_path):
# Parse Metadata from Gcode
fields = {}
part_name = get_gcode_name_from_metadata(gc)
fields["Part ID / Name"] = part_name
# 1. Time per print (decimal hours)
time_match = re.search(r"; estimated printing time \(normal mode\) = (.*)", gc)
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 = (.*)", gc)
if parts_match:
try:
with open(abs_token_path, 'r', encoding='utf-8') as f:
token = f.read().strip()
except Exception as e:
if operator: operator.report({'ERROR'}, f"Failed to read token file: {str(e)}")
return 'error'
info = json.loads(parts_match.group(1))
fields["Parts per print"] = len(info.get("objects", []))
except Exception: pass
if not self._check_config(token):
if operator: operator.report({'ERROR'}, f"{self._db_name} configuration incomplete")
return 'incomplete config'
# 3. Weight per print
weight_match = re.search(r"; total filament used \[g\] = ([\d\.]+)", gc)
if weight_match:
fields["Weight per print"] = int(float(weight_match.group(1)))
temp_dir = tempfile.TemporaryDirectory()
temp_path = Path(temp_dir.name) / filename
# Detect binary trigger in gcode comments
is_binary = "; binary_gcode = 1" in gc
try:
if is_binary:
content = convert_to_bgcode(gcode, name_part, True)
with open(temp_path, "wb") as f:
f.write(content)
else:
with open(temp_path, 'w', encoding='utf-8') as f:
f.write(gcode)
filename = part_name + ".bgcode" if is_binary else ".gcode"
record_id = self._submit_to_db(token, fields, temp_path)
if operator: operator.report({'INFO'}, f"Submitted to {self._db_name} (Record: {record_id})")
return 'ok'
except Exception as e:
if operator: operator.report({'ERROR'}, f"{self._db_name} Error: {str(e)}")
return 'error'
finally:
if temp_path.exists():
temp_path.unlink()
temp_dir.cleanup()
token_path = getattr(self, self._token_prop_name, "")
token = ""
if token_path:
abs_token_path = bpy.path.abspath(token_path)
if os.path.exists(abs_token_path):
try:
with open(abs_token_path, 'r', encoding='utf-8') as f:
token = f.read().strip()
except Exception as e:
if operator: operator.report({'ERROR'}, f"Failed to read token file: {str(e)}")
return 'error'
if not self._check_config(token):
if operator: operator.report({'ERROR'}, f"{self._db_name} configuration incomplete")
return 'incomplete config'
temp_dir = tempfile.TemporaryDirectory()
temp_path = Path(temp_dir.name) / filename
try:
if is_binary:
content = convert_to_bgcode(gc, part_name, True)
with open(temp_path, "wb") as f:
f.write(content)
else:
with open(temp_path, 'w', encoding='utf-8') as f:
f.write(gc)
record_id = self._submit_to_db(token, fields, temp_path)
if operator: operator.report({'INFO'}, f"Submitted to {self._db_name} (Record: {record_id})")
return 'ok'
except Exception as e:
if operator: operator.report({'ERROR'}, f"{self._db_name} Error: {str(e)}")
return 'error'
finally:
if temp_path.exists():
temp_path.unlink()
temp_dir.cleanup()
def _check_config(self, token: str) -> bool:
return False