You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LightWork3D/docs/2D-3D交换协议.md

14 KiB

2D / 3D 交换协议(第一版)

本文档只描述 QET 与 FreeCAD 之间的 JSON 交换格式

不负责描述:

  • 数据库建表
  • 数据库存储约束
  • 旧表兼容策略

这些内容统一放在:

  • 数据库设计.md

1. 协议目标

第一版协议只解决下面这条最小闭环:

  1. QET 能把当前项目中的设备实例和端子实例导出给 FreeCAD
  2. FreeCAD 能根据导出结果创建或更新 3D 设备实例
  3. FreeCAD 能根据导出结果创建或更新 3D 端子对象
  4. FreeCAD 保存后,能把最小回写结果再交还给 QET

当前版本明确采用:

  • 文件交换
  • JSON 格式

当前版本明确不采用:

  • 实时 RPC
  • HTTP API
  • 直接双向数据库同步

2. 交换文件位置建议

建议所有交换文件都放到项目目录下:

<ProjectRoot>/.qet_freecad/
    2d_to_3d.json
    3d_to_2d.json
    scene.FCStd
    logs/

含义:

  • 2d_to_3d.jsonQET 导出给 FreeCAD 的输入快照
  • 3d_to_2d.jsonFreeCAD 回写给 QET 的结果快照
  • scene.FCStd:该项目对应的 FreeCAD 3D 工程

3. 第一版 2d_to_3d.json 设计原则

3.1 最小主键集

第一版最小主键集只认:

  • project_uuid
  • element_uuid
  • terminal_uuid
  • instance_id

3.2 数据来源

2d_to_3d.json 不是数据库整表导出,而是:

从 QET 当前项目状态中整理出的、面向 FreeCAD 使用的最小交换快照。

也就是说:

  • 它可以来自数据库
  • 也可以来自当前内存状态
  • 但最终输出是给 FreeCAD 消费的统一协议格式

3.3 协议可以比数据库稍微丰富

数据库设计要求尽量去冗余。

但 JSON 交换协议可以为了:

  • 降低 FreeCAD 读取复杂度
  • 提升可调试性
  • 避免 FreeCAD 再回查 QET 内部数据库

而适当带上一些“已解析数据”。

这不等于数据库必须保留这些字段。


4. 第一版 2d_to_3d.json 顶层结构

推荐结构:

{
  "schema_version": "1.2",
  "project_uuid": "string",
  "generated_at": "2026-05-18T10:30:00+08:00",
  "source": {
    "app": "QET",
    "version": "string"
  },
  "cabinet": {},
  "devices": [],
  "terminals": [],
  "device_models": [],
  "wires": []
}

说明:

  • schema_version:协议版本,便于后续兼容升级
  • project_uuid:项目主键
  • generated_at:导出时间
  • source:导出来源信息
  • cabinet:当前图纸属性中绑定的机柜信息
  • devices:设备实例绑定
  • terminals:端子实例绑定
  • device_models:设备 3D 模型解析结果
  • wires:导线起点/终点与标注快照

5. cabinet 结构

5.1 作用

当前版本仍然以 图纸 作为交换单位。

但图纸属性本身已经绑定了一个机柜,因此 2d_to_3d.json 顶层会额外带上:

当前图纸绑定的机柜信息

这样 FreeCAD 在保持“按图纸导入设备/端子”的同时,也能知道:

  • 这批设备属于哪个机柜
  • 这个机柜当前绑定了哪个 3D 相对路径

5.2 推荐字段

{
  "location_id": 12,
  "label": "C",
  "name": "电容柜",
  "display_text": "C - 电容柜",
  "associated_fileset": "电容柜文件集",
  "three_d_relative_path": "3D/Cabinets/C.FCStd",
  "resolved_scene_path": "C:/Users/Admin/Documents/MingTuProject/xxx/3D/Cabinets/C.FCStd"
}

5.3 字段说明

字段 中文 必需 说明
location_id 机柜位置ID 当前图纸属性绑定的机柜位置 ID
label 机柜标注 用于 3D 侧快速识别机柜
name 机柜名称 机柜名称
display_text 机柜显示文本 等价于 QET 图纸属性界面中看到的机柜显示文本
associated_fileset 关联文件集 当前机柜位置绑定的文件集信息
three_d_relative_path 3D 相对路径 相对于工程目录保存的 3D 机柜路径
resolved_scene_path 已解析机柜场景路径 QET 已解析出的本地场景文件路径,便于 FreeCAD 直接使用

5.4 说明

  • cabinet 是一个 图纸级上下文对象
  • 它不是设备绑定表或端子绑定表的扩张
  • 它只描述“当前图纸绑定了哪个机柜,以及机柜当前对应哪个 3D 文件”

6. devices 结构

6.1 作用

devices 负责表达:

一个 2D 设备实例,对应哪个 3D 设备实例。

6.2 第一版字段

{
  "element_uuid": "string",
  "instance_id": "string",
  "display_tag": "string"
}

6.3 字段说明

字段 中文 必需 说明
element_uuid 2D设备实例UUID QET 图纸中的设备实例主键
instance_id 3D实例ID FreeCAD 侧设备实例主键
display_tag 2D设备实例标注 JSON 显示辅助字段,优先使用 2D 中设备标注作为 FreeCAD 树标签;为空时再退回 instance_id / element_uuid

6.4 说明

  • 如果第一次进入 3D 时还没有 instance_id,允许先导出空字符串或缺省值
  • FreeCAD 创建 3D 实例后,再在回写阶段补齐
  • display_tag 不进入第一版数据库最小字段集,它只存在于交换 JSON 中,用来让 3D 树视图与 2D 标注更容易对上

7. terminals 结构

7.1 作用

terminals 负责表达:

一个 2D 端子实例,属于哪个 3D 设备实例。

7.2 第一版字段

{
  "terminal_uuid": "string",
  "instance_id": "string",
  "element_uuid": "string"
}

7.3 字段说明

字段 中文 必需 说明
terminal_uuid 2D端子UUID QET 端子实例主键
instance_id 3D实例ID 该端子所属的 3D 设备实例
element_uuid 2D设备实例UUID JSON 导入辅助字段,帮助 FreeCAD 在首次没有 instance_id 时仍能知道端子属于哪个设备

7.4 为什么这里允许带 element_uuid

注意:

  • element_uuid 不是第一版端子绑定表的数据库字段扩张
  • 它只是交换 JSON 中的上下文辅助字段

原因:

  • 当某些设备第一次进入 3D、暂时还没有 instance_id
  • FreeCAD 仍需要知道该端子属于哪个 2D 设备实例

所以这里允许 JSON 比数据库稍微丰富一些。

7.5 为什么第一版不带更多字段

第一版先不强制包含:

  • terminal_key
  • connection_point_key
  • symbol_terminal

8. wires 结构

8.1 作用

wires 负责表达:

当前图纸中每一条逻辑导线,连接了哪两个端子,以及它当前的导线标注。

第一版先只解决:

  • 导线是谁
  • 起点端子是谁
  • 终点端子是谁
  • 当前导线标注是什么

不在这一版里解决:

  • 3D 路径点
  • 3D 线束位姿
  • 导线自动布线路由结果

8.2 第一版字段

{
  "wire_id": "string",
  "net_uuid": "string",
  "group_uuid": "string",
  "wire_mark": "string",
  "wire_mark_is_manual": false,
  "wire_style_id": 0,
  "start_element_uuid": "string",
  "start_terminal_uuid": "string",
  "end_element_uuid": "string",
  "end_terminal_uuid": "string",
  "start_terminal_display": "string",
  "end_terminal_display": "string"
}

8.3 字段说明

字段 中文 必需 说明
wire_id 导线交换ID JSON 交换层稳定标识;按 DirectionInfo 生成,格式为 direction:${net_uuid}:${index}
net_uuid 网络UUID 当前逻辑导线所属网络
group_uuid 网络分组UUID 当前逻辑导线所属网络分组
wire_mark 导线标注 导线当前标注;为空时导出为 无标注导线
wire_mark_is_manual 导线标注是否手工 是否手工修改过导线标注
wire_style_id 导线样式ID start_terminal 所连接导线的样式 ID
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 中的显示编号

8.4 说明

  • wire_mark 来源于当前图纸导线方向信息里的 wireMark

  • 它是导线标注

  • 不是设备实例标注,也不是符号设备标注

  • wire_id 代表一条 DirectionInfo

  • 不再混入几何 Conductor UUID 作为导线主标识

  • wire_style_id 只取 start_terminal 所连接导线的样式

  • 不按整条几何路径聚合多个样式

  • wires 是交换 JSON 的扩展层

  • 不意味着第一版数据库绑定表要新增导线绑定表

  • 第一版 FreeCAD 侧即使暂时不消费 wires

  • 也建议先由 QET 输出出来,方便后续 3D 布线与调试


9. device_models 结构

9.1 作用

device_models 不是绑定表本身,而是:

QET 在导出时,顺手把设备对应 3D 模型资源解析出来,减少 FreeCAD 再回查 QET 内部数据库的复杂度。

9.2 第二步设备导入推荐字段

{
  "element_uuid": "string",
  "device_id": 123,
  "parts_3d": "string",
  "resolved_model_path": "string"
}

8.3 字段说明

字段 中文 必需 说明
element_uuid 2D设备实例UUID devices 关联
device_id 设备类型ID QET 设备主数据 ID
parts_3d 3D模型资源URI 原始资源引用,来自 device_3d_asset.uridevice_attribute.parts_3d
resolved_model_path 已解析模型路径 QET 已经解析好的本地模型文件路径FreeCAD 第二步直接用它导入 STEP / FCStd

8.4 为什么 resolved_model_path 是第二步关键字段

第二步开始FreeCAD 不再只做 JSON 校验,而要真正导入设备模型。

如果没有 resolved_model_pathFreeCAD 就必须自己理解和回查:

  1. element_uuid
  2. device_id
  3. device_3d_asset
  4. device_attribute.parts_3d
  5. 本地路径解析规则

这会让 FreeCAD 过度耦合 QET 内部数据库结构。

所以第二步推荐由 QET 在导出时直接给出:

  • resolved_model_path

让 FreeCAD 只负责消费结果。

8.5 .FCStd 设备资产支持

A 方案下,.FCStd 是正式可复用设备资产格式。QET 导出时不需要解析 .FCStd 内部内容,只需要把设备资产路径解析成 resolved_model_path 交给 FreeCAD。

示例:

{
  "element_uuid": "elem-1001",
  "device_id": 123,
  "parts_3d": "models/mccb/MCCB_1P.FCStd",
  "resolved_model_path": "C:/Users/Admin/Documents/MingTuProject/models/mccb/MCCB_1P.FCStd"
}

FreeCAD 根据 resolved_model_path 的扩展名导入 .FCStd,并在导入后的设备组内优先扫描 Role="Terminal" 的 LCS 作为模板端子槽位。

如果 QET 侧已经在 device_3d_asset.format 中保存了资源格式,可以在后续协议中追加可选字段:

{
  "format": "fcstd"
}

第一版 FreeCAD 不应强依赖该字段,避免旧版本 JSON 缺少 format 时无法导入。

8.6 为什么这里允许同时带 parts_3d

注意:

  • 数据库设计里我们已经决定不在绑定表冗余保存 asset_uri
  • 交换协议里允许带 parts_3d

原因是:

  • JSON 是导出快照
  • 不是绑定数据库本身
  • 这样 FreeCAD 读取时更简单

也就是说:

数据库去冗余
JSON 可适度带已解析结果


8. 第一版 2d_to_3d.json 完整样例

{
  "schema_version": "1.0",
  "project_uuid": "proj-001",
  "generated_at": "2026-05-18T10:30:00+08:00",
  "source": {
    "app": "QET",
    "version": "1.0"
  },
  "devices": [
    {
      "element_uuid": "elem-1001",
      "instance_id": "fc-inst-0001"
    }
  ],
  "terminals": [
    {
      "terminal_uuid": "term-2001",
      "instance_id": "fc-inst-0001",
      "element_uuid": "elem-1001"
    },
    {
      "terminal_uuid": "term-2002",
      "instance_id": "fc-inst-0001",
      "element_uuid": "elem-1001"
    }
  ],
  "device_models": [
    {
      "element_uuid": "elem-1001",
      "device_id": 123,
      "parts_3d": "models/mccb/model.step",
      "resolved_model_path": "C:/Users/Admin/Documents/MingTuProject/models/mccb/model.step"
    }
  ]
}

9. 第一版 3d_to_2d.json 建议

第一版回写建议同样保持最小化。

推荐结构:

{
  "schema_version": "1.0",
  "project_uuid": "string",
  "generated_at": "2026-05-18T11:00:00+08:00",
  "instances": [],
  "terminals": []
}

9.1 instances

{
  "element_uuid": "string",
  "instance_id": "string"
}

9.2 terminals

{
  "terminal_uuid": "string",
  "instance_id": "string"
}

9.3 说明

第一版不回写:

  • 3D 位姿
  • 装配层级
  • 几何路径
  • 线槽信息

这些仍以 FreeCAD 文档为准。


10. 第一版推荐交互流程

  1. 用户在 QET 中点击 3D视图
  2. QET 生成 2d_to_3d.json
  3. QET 打开 FreeCAD并打开 scene.FCStd
  4. FreeCAD 读取 2d_to_3d.json
  5. FreeCAD 创建或更新:
    • 3D 设备实例
    • 3D 端子对象
  6. 用户在 FreeCAD 中完成装配和接线
  7. 用户保存 FreeCAD 工程
  8. FreeCAD 生成 3d_to_2d.json
  9. QET 在后续时机读取 3d_to_2d.json

11. 当前推荐结论

第一版协议建议明确分层:

  • 数据库设计:尽量去冗余
  • JSON 协议:允许带少量已解析结果,方便 FreeCAD 使用

一句话总结:

第一版先把 2d_to_3d.json 做成“面向 FreeCAD 的最小项目快照”,而不是数据库整表镜像。