Revert "feature/手动布线结果回写-zwl-0521"

This reverts commit 588a1727b9.
dev
Zhaowenlong 4 days ago
parent e4b7a95355
commit ad3e17234a

@ -598,5 +598,4 @@ ManualWiring.py
- 2026-05-20修复 `TemplateAuthoring.py``FreeCADCmd.exe` 命令行模式下导入时误注册 GUI 命令的问题;已在运行目录验证创建 `P1` 模板端子、保存 `.FCStd`、重新打开后端子语义仍可识别。
- 2026-05-20确定方案 2 开发目标:新增“设备模板端子制作”任务面板,让 CAD 工作人员通过输入端子名、选择模型位置、点击按钮完成添加端子、校验端子和保存 FCStd不再依赖 Python 控制台。
- 2026-05-20新增 `TemplateAuthoringPanel.py`,提供“设备模板端子制作”任务面板和 `QET_Template_OpenAuthoringPanel` 命令;面板支持输入端子名、添加端子、校验端子、保存 FCStd并已同步到运行目录验证模块可导入。
- 2026-05-21新增手动布线结果回写能力`3d_to_2d.json` 现在会输出 `manual_wires`,包含起止端子 UUID、起止设备实例 ID、路线类型和 3D 路径点;已用单元测试验证,待 QET 侧决定是否消费该可选字段。
```

@ -79,44 +79,6 @@ def _iter_terminal_objects(device_group):
return TerminalObjects.collect_terminal_objects(terminal_container)
def _iter_wire_objects(device_group):
wire_container = TerminalObjects.find_child_group_by_kind(
device_group,
TerminalObjects.WIRE_GROUP_KIND,
)
if wire_container is None:
return []
result = []
def walk(obj):
if obj is None:
return
for child in list(getattr(obj, "Group", []) or []):
if _is_manual_wire_object(child):
result.append(child)
continue
try:
if child.isDerivedFrom("App::DocumentObjectGroup"):
walk(child)
except Exception:
pass
walk(wire_container)
return result
def _is_manual_wire_object(obj):
if obj is None:
return False
properties = getattr(obj, "PropertiesList", [])
if "QetStartTerminalUuid" not in properties:
return False
if "QetEndTerminalUuid" not in properties:
return False
return (getattr(obj, "RouteType", "") or "").strip() == "Manual"
def _scene_path_from_doc(doc, scene_path=""):
candidate = (scene_path or "").strip()
if candidate:
@ -196,70 +158,6 @@ def _collect_terminal_bindings(doc):
return bindings
def _point_from_vector(vector):
return {
"x": float(getattr(vector, "x", 0.0)),
"y": float(getattr(vector, "y", 0.0)),
"z": float(getattr(vector, "z", 0.0)),
}
def _wire_shape_points(wire_obj):
shape = getattr(wire_obj, "Shape", None)
if shape is None:
return []
if isinstance(shape, (list, tuple)):
return [_point_from_vector(point) for point in shape]
vertices = getattr(shape, "Vertexes", None)
if vertices:
points = []
for vertex in vertices:
point = getattr(vertex, "Point", None)
if point is not None:
points.append(_point_from_vector(point))
return points
return []
def _collect_manual_wires(doc):
wires = []
seen = set()
for device_group in _iter_device_groups(doc):
for wire_obj in _iter_wire_objects(device_group):
start_terminal_uuid = getattr(wire_obj, "QetStartTerminalUuid", "").strip()
end_terminal_uuid = getattr(wire_obj, "QetEndTerminalUuid", "").strip()
start_instance_id = getattr(wire_obj, "QetStartInstanceId", "").strip()
end_instance_id = getattr(wire_obj, "QetEndInstanceId", "").strip()
route_type = (getattr(wire_obj, "RouteType", "") or "").strip() or "Manual"
if not start_terminal_uuid or not end_terminal_uuid:
continue
key = (
start_terminal_uuid,
end_terminal_uuid,
start_instance_id,
end_instance_id,
getattr(wire_obj, "Name", ""),
)
if key in seen:
continue
seen.add(key)
wires.append(
{
"start_terminal_uuid": start_terminal_uuid,
"end_terminal_uuid": end_terminal_uuid,
"start_instance_id": start_instance_id,
"end_instance_id": end_instance_id,
"route_type": route_type,
"points": _wire_shape_points(wire_obj),
}
)
return wires
def _project_uuid_from_doc(doc, payload=None):
root = _root_group(doc)
if root is not None:
@ -294,7 +192,6 @@ def write_back_document(doc=None, scene_path="", payload=None):
"generated_at": _format_timestamp(),
"instances": _collect_instance_bindings(doc),
"terminals": _collect_terminal_bindings(doc),
"manual_wires": _collect_manual_wires(doc),
"output_path": output_path,
}
@ -308,7 +205,6 @@ def write_back_document(doc=None, scene_path="", payload=None):
"generated_at": report["generated_at"],
"instances": report["instances"],
"terminals": report["terminals"],
"manual_wires": report["manual_wires"],
},
ensure_ascii=False,
indent=2,
@ -317,10 +213,9 @@ def write_back_document(doc=None, scene_path="", payload=None):
)
_append_debug_log(
"write_back_document completed: instances={0}, terminals={1}, manual_wires={2}, path={3}".format(
"write_back_document completed: instances={0}, terminals={1}, path={2}".format(
len(report["instances"]),
len(report["terminals"]),
len(report["manual_wires"]),
output_path,
)
)
@ -392,10 +287,9 @@ class CommandWriteBack:
report = write_back_document(App.ActiveDocument)
try:
App.Console.PrintMessage(
"[FreeCADExchange] Write-back completed: {0} instances, {1} terminals, {2} manual wires\n".format(
"[FreeCADExchange] Write-back completed: {0} instances, {1} terminals\n".format(
len(report["instances"]),
len(report["terminals"]),
len(report["manual_wires"]),
)
)
except Exception:

@ -1,158 +0,0 @@
import importlib
import json
import sys
import tempfile
import types
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
MODULE_DIR = REPO_ROOT / "src" / "Mod" / "FreeCADExchange"
if str(MODULE_DIR) not in sys.path:
sys.path.insert(0, str(MODULE_DIR))
def _install_fake_freecad():
class Vector:
def __init__(self, x=0.0, y=0.0, z=0.0):
self.x = float(x)
self.y = float(y)
self.z = float(z)
fake_freecad = types.ModuleType("FreeCAD")
fake_freecad.Vector = Vector
fake_freecad.ActiveDocument = None
fake_freecad.Console = types.SimpleNamespace(
PrintMessage=lambda *args, **kwargs: None,
PrintWarning=lambda *args, **kwargs: None,
PrintError=lambda *args, **kwargs: None,
)
fake_freecad.addDocumentObserver = lambda observer: None
sys.modules["FreeCAD"] = fake_freecad
fake_freecadgui = types.ModuleType("FreeCADGui")
fake_freecadgui.addCommand = lambda *args, **kwargs: None
sys.modules["FreeCADGui"] = fake_freecadgui
fake_importgui = types.ModuleType("ImportGui")
fake_importgui.insert = lambda *args, **kwargs: None
sys.modules["ImportGui"] = fake_importgui
fake_device_preview = types.ModuleType("DevicePreview")
fake_device_preview.find_main_exchange_document = lambda preferred_name="": None
sys.modules["DevicePreview"] = fake_device_preview
class FakeObject:
def __init__(self, name, type_id="App::DocumentObjectGroup"):
self.Name = name
self.Label = name
self.TypeId = type_id
self.PropertiesList = []
self.Group = []
self.InList = []
def isDerivedFrom(self, type_name):
if self.TypeId == type_name:
return True
if type_name == "App::DocumentObjectGroup":
return self.TypeId in {"App::DocumentObjectGroup", "App::Part"}
return False
def addProperty(self, prop_type, prop_name, group_name, description):
if prop_name not in self.PropertiesList:
self.PropertiesList.append(prop_name)
def addObject(self, child):
if child not in self.Group:
self.Group.append(child)
if self not in child.InList:
child.InList.append(self)
class FakeDocument:
def __init__(self):
self.Name = "QETScene"
self.FileName = ""
self.Objects = []
def addObject(self, type_name, name):
obj = FakeObject(name, type_name)
self.Objects.append(obj)
return obj
def getObject(self, name):
for obj in self.Objects:
if obj.Name == name:
return obj
return None
def _reload_writeback():
for name in ["DeviceImport", "TerminalObjects", "ExchangeWriteBack"]:
sys.modules.pop(name, None)
return importlib.import_module("ExchangeWriteBack"), importlib.import_module("TerminalObjects")
class ExchangeWriteBackManualWireTest(unittest.TestCase):
def test_write_back_includes_manual_wires_with_route_points(self):
_install_fake_freecad()
exchange_writeback, terminal_objects = _reload_writeback()
app = sys.modules["FreeCAD"]
doc = FakeDocument()
root = terminal_objects.ensure_root_group(doc, "project-1")
device = doc.addObject("App::Part", "QETDevice_device_1")
root.addObject(device)
terminal_objects.ensure_string_property(device, "QetElementUuid", "QET Exchange", "", "device-1")
terminal_objects.ensure_string_property(device, "QetInstanceId", "QET Exchange", "", "instance-1")
wire_group = terminal_objects.ensure_wire_group(
doc,
device,
project_uuid="project-1",
instance_id="instance-1",
)
wire = doc.addObject("Part::Feature", "QETWire_terminal_1_terminal_2")
wire_group.addObject(wire)
terminal_objects.ensure_string_property(wire, "QetProjectUuid", "QET Exchange", "", "project-1")
terminal_objects.ensure_string_property(wire, "QetStartTerminalUuid", "QET Exchange", "", "terminal-1")
terminal_objects.ensure_string_property(wire, "QetEndTerminalUuid", "QET Exchange", "", "terminal-2")
terminal_objects.ensure_string_property(wire, "QetStartInstanceId", "QET Exchange", "", "instance-1")
terminal_objects.ensure_string_property(wire, "QetEndInstanceId", "QET Exchange", "", "instance-2")
terminal_objects.ensure_string_property(wire, "RouteType", "QET Exchange", "", "Manual")
wire.Shape = (
app.Vector(1, 2, 3),
app.Vector(4, 5, 6),
)
with tempfile.TemporaryDirectory() as temp_dir:
scene_path = str(Path(temp_dir) / "scene.FCStd")
report = exchange_writeback.write_back_document(
doc,
scene_path=scene_path,
payload={"project_uuid": "project-1"},
)
payload = json.loads(Path(report["output_path"]).read_text(encoding="utf-8"))
self.assertEqual(1, len(report["manual_wires"]))
self.assertEqual(1, len(payload["manual_wires"]))
self.assertEqual(
{
"start_terminal_uuid": "terminal-1",
"end_terminal_uuid": "terminal-2",
"start_instance_id": "instance-1",
"end_instance_id": "instance-2",
"route_type": "Manual",
"points": [
{"x": 1.0, "y": 2.0, "z": 3.0},
{"x": 4.0, "y": 5.0, "z": 6.0},
],
},
payload["manual_wires"][0],
)
if __name__ == "__main__":
unittest.main()
Loading…
Cancel
Save