完善QET交换协议与设备导入提示

dev
zhanghao 6 days ago
parent 03cc72b0c4
commit a2f7c6dda4

@ -101,7 +101,7 @@
```json ```json
{ {
"schema_version": "1.1", "schema_version": "1.2",
"project_uuid": "string", "project_uuid": "string",
"generated_at": "2026-05-18T10:30:00+08:00", "generated_at": "2026-05-18T10:30:00+08:00",
"source": { "source": {
@ -111,7 +111,8 @@
"cabinet": {}, "cabinet": {},
"devices": [], "devices": [],
"terminals": [], "terminals": [],
"device_models": [] "device_models": [],
"wires": []
} }
``` ```
@ -125,6 +126,7 @@
- `devices`:设备实例绑定 - `devices`:设备实例绑定
- `terminals`:端子实例绑定 - `terminals`:端子实例绑定
- `device_models`:设备 3D 模型解析结果 - `device_models`:设备 3D 模型解析结果
- `wires`:导线起点/终点与标注快照
--- ---
@ -258,26 +260,89 @@
- `terminal_key` - `terminal_key`
- `connection_point_key` - `connection_point_key`
- `symbol_terminal` - `symbol_terminal`
- `wire_label`
- `net_id`
原因: ---
## 8. `wires` 结构
### 8.1 作用
`wires` 负责表达:
> 当前图纸中每一条逻辑导线,连接了哪两个端子,以及它当前的导线标注。
第一版先只解决:
- 导线是谁
- 起点端子是谁
- 终点端子是谁
- 当前导线标注是什么
不在这一版里解决:
- 3D 路径点
- 3D 线束位姿
- 导线自动布线路由结果
- 这些字段当前都不是 FreeCAD 第一版创建端子对象的硬前提 ### 8.2 第一版字段
- 端子语义可以通过 `terminal_uuid` 回查 QET
- 先把绑定关系打通,比先堆字段更重要 ```json
{
"wire_id": "string",
"net_uuid": "string",
"group_uuid": "string",
"wire_mark": "string",
"wire_mark_is_manual": false,
"start_element_uuid": "string",
"start_terminal_uuid": "string",
"end_element_uuid": "string",
"end_terminal_uuid": "string",
"start_terminal_display": "string",
"end_terminal_display": "string",
"conductor_uuids": []
}
```
### 8.3 字段说明
| 字段 | 中文 | 必需 | 说明 |
| --- | --- | --- | --- |
| `wire_id` | 导线交换ID | 是 | JSON 交换层稳定标识;优先使用单根导线 UUID退回 `net_uuid + index` |
| `net_uuid` | 网络UUID | 否 | 当前逻辑导线所属网络 |
| `group_uuid` | 网络分组UUID | 否 | 当前逻辑导线所属网络分组 |
| `wire_mark` | 导线标注 | 否 | 导线当前标注;为空时导出为 `无标注导线` |
| `wire_mark_is_manual` | 导线标注是否手工 | 否 | 是否手工修改过导线标注 |
| `start_element_uuid` | 起点设备UUID | 是 | 起点端子所属 2D 设备实例 |
| `start_terminal_uuid` | 起点端子UUID | 是 | 起点 2D 端子实例 |
| `end_element_uuid` | 终点设备UUID | 是 | 终点端子所属 2D 设备实例 |
| `end_terminal_uuid` | 终点端子UUID | 是 | 终点 2D 端子实例 |
| `start_terminal_display` | 起点端子显示号 | 否 | 起点端子在 QET 中的显示编号 |
| `end_terminal_display` | 终点端子显示号 | 否 | 终点端子在 QET 中的显示编号 |
| `conductor_uuids` | 几何导线UUID列表 | 否 | 当前逻辑导线对应的 2D 几何导线 UUID 列表 |
### 8.4 说明
- `wire_mark` 来源于当前图纸导线方向信息里的 `wireMark`
- 它是**导线标注**
- 不是设备实例标注,也不是符号设备标注
- `wires` 是交换 JSON 的扩展层
- 不意味着第一版数据库绑定表要新增导线绑定表
- 第一版 FreeCAD 侧即使暂时不消费 `wires`
- 也建议先由 QET 输出出来,方便后续 3D 布线与调试
--- ---
## 8. `device_models` 结构 ## 9. `device_models` 结构
### 8.1 作用 ### 9.1 作用
`device_models` 不是绑定表本身,而是: `device_models` 不是绑定表本身,而是:
> QET 在导出时,顺手把设备对应 3D 模型资源解析出来,减少 FreeCAD 再回查 QET 内部数据库的复杂度。 > QET 在导出时,顺手把设备对应 3D 模型资源解析出来,减少 FreeCAD 再回查 QET 内部数据库的复杂度。
### 8.2 第二步设备导入推荐字段 ### 9.2 第二步设备导入推荐字段
```json ```json
{ {

@ -214,6 +214,18 @@ def _device_label_text(display_tag, instance_id, element_uuid):
return "QET Device" return "QET Device"
def _device_warning_subject(display_tag, element_uuid):
label = (display_tag or "").strip()
element_uuid = (element_uuid or "").strip()
if label and element_uuid:
return "设备 {0} ({1})".format(label, element_uuid)
if label:
return "设备 {0}".format(label)
if element_uuid:
return "设备 {0}".format(element_uuid)
return "设备"
def _ensure_device_group(doc, root_group, element_uuid, instance_id, model_path, display_tag, layout_index): def _ensure_device_group(doc, root_group, element_uuid, instance_id, model_path, display_tag, layout_index):
created_now = False created_now = False
device_group = _find_device_group(doc, element_uuid) device_group = _find_device_group(doc, element_uuid)
@ -438,21 +450,29 @@ def import_devices_from_payload(payload, scene_path=""):
if not resolved_model_path: if not resolved_model_path:
report["skipped_missing_model"] += 1 report["skipped_missing_model"] += 1
report["warnings"].append( report["warnings"].append(
"设备 {0} 缺少 resolved_model_path已跳过。".format(element_uuid) "{0} 缺少 resolved_model_path已跳过。".format(
_device_warning_subject(display_tag, element_uuid)
)
) )
continue continue
if not os.path.isfile(resolved_model_path): if not os.path.isfile(resolved_model_path):
report["skipped_missing_file"] += 1 report["skipped_missing_file"] += 1
report["warnings"].append( report["warnings"].append(
"设备 {0} 的模型文件不存在:{1}".format(element_uuid, resolved_model_path) "{0} 的模型文件不存在:{1}".format(
_device_warning_subject(display_tag, element_uuid),
resolved_model_path,
)
) )
continue continue
if not _supported_for_import(resolved_model_path): if not _supported_for_import(resolved_model_path):
report["skipped_unsupported_format"] += 1 report["skipped_unsupported_format"] += 1
report["warnings"].append( report["warnings"].append(
"设备 {0} 的模型格式暂不支持:{1}".format(element_uuid, resolved_model_path) "{0} 的模型格式暂不支持:{1}".format(
_device_warning_subject(display_tag, element_uuid),
resolved_model_path,
)
) )
continue continue
@ -481,7 +501,10 @@ def import_devices_from_payload(payload, scene_path=""):
except Exception as exc: except Exception as exc:
report["skipped_import_error"] += 1 report["skipped_import_error"] += 1
report["warnings"].append( report["warnings"].append(
"设备 {0} 导入失败:{1}".format(element_uuid, exc) "{0} 导入失败:{1}".format(
_device_warning_subject(display_tag, element_uuid),
exc,
)
) )
_append_debug_log( _append_debug_log(
"DeviceImport import failed for element_uuid={0}: {1}".format( "DeviceImport import failed for element_uuid={0}: {1}".format(

Loading…
Cancel
Save