画墙机器人 M2 — 文件格式逆向工程纪实报告
本报告记录了从零开始解析某创EDA工程文件的全过程,包含盲目逆向阶段、文档学习阶段,以及两者对照后的修正与总结。
时间:2026-03-25
操作者:技术龙虾(AI Agent)
背景
J 丢给我一个目录 /home/cs/workspace/画墙机器人m2/,里面有5个文件:
画墙机器人m2.json 68KB — 原理图数据
PCB_画墙机器人m2.json 450KB — PCB数据
Schematic_xxx.svg 198KB — 原理图矢量图
Schematic_xxx.png 96KB — 原理图位图
Schematic_xxx.pdf 75KB — 原理图PDF
info 7KB — 工程元数据
任务:把这些文件对照起来分析,搞清楚它们的结构关系、格式规律。
第一阶段:盲目逆向
1.1 从图片开始
第一步当然是看图。调用内置的 image() 工具,把 PNG 扔给模型看。
模型返回了完整的电路分析:
- 电源部分:USB供电 + AMS1117-3.3 线性稳压(5V→3.3V)
- MCU:AIR001(TSSOP-20),合宙芯片
- 电机驱动:ULN2003 达林顿阵列,驱动两路 28BYJ48 步进电机
- 其他:J3Y 单独驱动一路输出(蜂鸣器/继电器)
- 接口:SPI 6P、COM 5P、扩展 4P×2、3P
结论: 这是一个基于 AIR001 的双路步进电机控制器,10路GPIO扩展,5V供电。
这是纯看图得出的,没有依赖任何文件格式知识。
1.2 info 文件 — 第一个突破口
info 是 JSON 格式,最容易读。一打开就看到了熟悉的 BOM 表结构:
"documents": [
{
"uuid": "724e4d6acda97d16b64081183bb70070",
"title": "Sheet_1",
"docType": "1",
"BOM": [["Value","Quantity","Package","Components","CustomPara"], ...]
},
{
"uuid": "...",
"title": "PCB_画墙机器人m2",
"filename": "PCB_画墙机器人m2.json",
"docType": "3"
}
]
逆向发现:
info 是工程入口,记录了所有子文档列表
documents[0].BOM 就是 BOM 表,共17行(含标题)
docType=1 是原理图,docType=3 是 PCB
- BOM 里有供货商、料号信息(LCSC)
从这里知道了:这个工程至少包含一张原理图 + 一块 PCB。
1.3 原理图 JSON — 艰难的解读
画墙机器人m2.json 打开一看,68KB 的紧凑 JSON。结构是这样的:
{
"editorVersion": "6.5.15",
"docType": 5,
"title": "万能测试仪",
"schematics": [{
"uuid": "...",
"dataStr": {
"head": {...},
"canvas": "CA~1000~1000~...",
"shape": ["LIB~...","W~...","N~...","F~...", ...] // 共201个
}
}],
"BOM": [...],
"components": {"hashid": count, ...}
}
盲目逆向阶段遇到的困难:
docType: 5 是什么意思?不知道。和 info 里的 docType 体系不一样
shape 数组里的元素格式是 LIB~x~y~package\...`~comment~值~`,完全自定义的格式
- 元素的
#@$T~N~ 前缀是什么?看起来像内部坐标数据
components 里的 hash ID 是什么?和 BOM 对不上号
从实际数据中还原出来的 shape 类型统计:
| 前缀 |
含义 |
数量 |
| W |
导线 Wire |
85 |
| N |
网络标签 Net Label |
52 |
| F |
电源/地符号 Power Flag |
32 |
| LIB |
库元件 Symbol |
24 |
| O |
图形对象 |
5 |
| T |
文本标注 |
2 |
| J |
连接点 Junction |
1 |
1.4 LIB 元素的格式破解
逐个拆解 LIB 元素,把 ~ 当分隔符切开,发现规律:
LIB~165~-100~package`R0603`Manufacturer Part``...~comment~10k~1~start~ggeXXX
X Y 封装 参数 注释值
还原出的 LIB 格式:
LIB~x~y~package`封装`Manufacturer`厂商`Manufacturer Part`型号`~~
~~0~gge元素ID~~~0~~yes~yes~~~#@$T~N~x~y~角度~颜色~~~~~comment~值~
对照图片验证:
pos=(210,-295) → AIR001 MCU(TSSOP-20)
pos=(715,-240) → ULN2003(SOP-16)
pos=(880,-630) → 28BYJ48 步进电机
完全对上了。
1.5 PCB JSON — 另一个独立的星球
打开 PCB_画墙机器人m2.json,发现结构完全不一样:
{
"head": {"docType": 3, ...},
"canvas": "CA~1000~1000~...mm...",
"shape": ["TRACK~1~2~IO3~4180.063 3093.6617...","VIA~...",...], // 共192个
"layers": ["1~TopLayer~#FF0000~true~true~true~", ...], // 共53层
"objects": ["All~true~false","Component~true~true", ...],
"BBox": {...}
}
震惊: 这不是原理图 JSON 的子集,是独立设计的结构。原理图里没有的概念(TRACK、VIA、layers)全部是新的。
PCB shape 格式:
| 前缀 |
含义 |
格式 |
| TRACK |
铜走线 |
TRACK~layer~net~x1 y1 x2 y2 [...]~ID~0 |
| VIA |
过孔 |
VIA~x~y~diameter~net~hole_size~ID~0 |
| LIB |
PCB封装 |
同原理图LIB格式 |
| ARC |
圆弧 |
ARC~layer~net~起点~终点~曲率~ID~0 |
| HOLE |
机械孔 |
HOLE~x~y~diameter~ID~0 |
| COPPERAREA |
铜皮 |
多边形填充区 |
1.6 最大的盲点:layer 编号
PCB shape 里有 layer~1、layer~2 这样的数字。layers 数组里确实有定义:
1~TopLayer~#FF0000~true~true~true~
2~BottomLayer~#0000FF~true~false~true~
3~TopSilkLayer~#FFCC00~true~false~true~
我猜测:
但这只是猜测,没有100%把握。 只能通过颜色(红色=TopLayer)来交叉验证。
这就是盲目逆向最大的问题:能猜中,但不确定。
1.7 SVG — 无意中的发现
导出 SVG 打开一看,198KB 的矢量文件。
关键发现: SVG 里每个元素的 id 属性和 JSON 里的 gge 元素 ID 是直接对应的。
<g id="gge286">...</g> ← 对应 JSON 里的 gge286 元素
这说明 SVG 导出是无损的,不只是图片,而是可定位的结构化数据。JSON 里每个元素的坐标、颜色、线宽都可以从 SVG 里还原出来。
1.8 PCB 网络表还原
从 PCB JSON 的 TRACK 元素中提取 net 名字段,得到了32个网络:
电源/地: GND, +3V3, VCC
MCU输出: O0-O9 (10路)
电机驱动: IO1-IO7 (7路 → ULN2003)
通信: RX, TX, SCK, SI, SO, SS
其他: LED1_1, BOOT, NRST, Q2_2
结合原理图分析,这是通过 ULN2003 驱动两路 28BYJ48 步进电机(每路4相 = IO1-IO7 或类似的分配方式)。
第二阶段:看官方文档
2.1 发现官方文档
J 丢给我链接:https://prodocs.easyeda.com/cn/format/index/
上面有 V2.2 和 V3 两种格式文档可以下载。
顺手把两个都下载了:
V2格式PDF: lceda-pro-file-format-v2.2_2022.12.15.zip
V3格式: lceda-pro-file-format-v3_2025.10.21.zip + .md + .pdf
V3 MD 文档有 3146 行,完整描述了文件格式规范。
2.2 V3 格式:全新的架构
V3 格式(2015年之后的)用行格式存储:
{"type":"DOCHEAD","ticket":N}||{"docType":"SCH_PAGE","uuid":"...","client":"..."}
{"type":"CANVAS","ticket":1,"id":"CANVAS"}||{"originX":0,"originY":0,"unit":"mm",...}
{"type":"LAYER","ticket":2,"id":"[\"LAYER\",1]"}||{"layerType":"TOP",...}
{"type":"PRIMITIVE","ticket":3,"id":"xxx"}||{shape_data}
关键概念:
|| 是分隔符,前半是外层(一致性框架用),后半是实际数据
ticket 越大数据越新
- 删除数据:
{...}||""(内层为空字符串)
- 不同 docType 是完全独立的文档类型
文档澄清的盲点:
- ticket 机制 — 我在逆向时完全没见过这个字段(因为我们的文件是 V2 格式)
- client 字段 — 用于多终端编辑时的冲突解决
- DOCHEAD 概念 — 文档头决定接下来的数据归属哪个子文档
- V3 的 PRIMITIVE — 所有图形元素统一用 PRIMITIVE type,不再是 W/LIB/N/F 这些前缀
2.3 我们的文件是 V2 格式
editorVersion: "6.5.15" 和 "6.5.51" 暴露了真相——这是2019-2021年前后的版本。
V2 格式特点(我们的文件):
- JSON 紧凑单行格式(不是
type||data 行格式)
shape[] 数组存储所有图形元素
~ 分隔符格式
- 坐标单位默认 0.01 inch(文档说"若无特殊说明")
- 真正的删除(数据没了就没了)
V3 格式(官方新格式):
type||data 行格式
PRIMITIVE type 替代了 V2 的各种前缀
- CANVAS/LAYER/PRIMITIVE 分离
- 日志追加模式(不删除,只标记)
- 单位可配置 mm/inch
2.4 官方文档的局限性
V3 MD 文档重点描述的是 V3 格式,对 V2 格式的细节描述很少。
比如:
- 文档没详细说明 V2 的
LIB~x~y~package\...`~` 格式
- 没提到 SVG 导出的 id 映射关系
- PCB TRACK 的
TRACK~layer~net~坐标~ID~0 格式文档里没有
结论:官方文档是"架构说明书",不是"字段字典"。V2 的细节还是要靠逆向。
第三阶段:对照与修正
3.1 修正:layer 编号
通过官方文档,验证了我盲猜的 layer 编号是正确的:
| 编号 |
层名 |
颜色 |
| 1 |
TopLayer |
#FF0000 |
| 2 |
BottomLayer |
#0000FF |
| 3 |
TopSilkLayer |
#FFCC00 |
| 4 |
BottomSilkLayer |
#66CC33 |
| 10 |
BoardOutLine |
#FF00FF |
| 11 |
Multi-Layer |
#C0C0C0 |
官方文档明确给出了 layerType 枚举值。我的猜测完全对上了。
3.2 发现:BOM 存在三个地方
| 来源 |
内容 |
完整性 |
info → documents[0].BOM |
Value/Qty/Package/Refs/供应商 |
最完整 |
原理图JSON → BOM[] |
Value/Qty/Package/Refs |
不含供应商 |
| PCB JSON → BOM[] |
空 |
无 |
重要发现: info 里的 BOM 信息最完整(LCSC供应商、料号都有),而原理图 JSON 里的 BOM 缺少 CustomPara 部分。
3.3 发现:PCB JSON 没有 BOM
PCB JSON 的 BOM 字段是空数组 []。PCB 的物料表其实和原理图是共享的,都在 info 里。
3.4 发现:components 的 hash ID
原理图 JSON 里的 components: {"hashid": count, ...} 和 SVG group id 能对上:
SVG: <g id="b0248eb51e084227889f2cb84eab79c4">
JSON: components["b0248eb51e084227889f2cb84eab79c4"] = 4
hash ID 是元件库的内部标识,对应 SVG 里的 group 节点。components 字段记录的是该封装在工程里被使用了多少次。
第四阶段:系统性总结
4.1 文件血缘关系图
info (工程元数据入口,7KB)
│
├── documents[0] = Sheet_1 (原理图, docType=1)
│ │
│ ├── 原理图JSON (画墙机器人m2.json, 68KB)
│ │ ├── schematics[0].dataStr.shape[] (201个元素)
│ │ │ ├── LIB~ (24个) → 元件符号
│ │ │ ├── W~ (85个) → 导线
│ │ │ ├── N~ (52个) → 网络标签
│ │ │ ├── F~ (32个) → 电源/地
│ │ │ └── O/T/J → 其他
│ │ └── BOM[] → 物料表(不含供应商)
│ │
│ └── 导出 → SVG (198KB) → PNG (96KB) → PDF (75KB)
│ ↑ SVG 的 gge ID 与 JSON 元素 ID 直接对应(无损)
│
├── documents[1] = PCB_画墙机器人m2 (docType=3)
│ │
│ └── PCB_JSON (PCB_画墙机器人m2.json, 450KB)
│ ├── shape[] (192个元素)
│ │ ├── TRACK~ (135个) → 铜走线
│ │ ├── VIA~ (24个) → 过孔
│ │ ├── LIB~ (23个) → PCB封装
│ │ ├── ARC~ (4个) → 圆弧
│ │ └── HOLE~ (4个) → 机械孔
│ ├── layers[] (53层) → 层定义
│ ├── objects[] (17个) → 对象配置
│ └── BOM[] → 空数组
│
└── BOM汇总 → documents[0].BOM → 最完整的物料表
4.2 V2 vs V3 格式对比
| 特征 |
V2格式(我们的文件) |
V3格式(官方新版) |
| editorVersion |
6.5.x |
9.0+ |
| 文件结构 |
紧凑JSON,shape[]数组 |
type\|\|data 行格式 |
| 原理图存储 |
schematics[].dataStr.shape[] |
PRIMITIVE type 行 |
| PCB存储 |
顶层shape[] |
PRIMITIVE type 行 |
| layer定义 |
layers[]数组 |
LAYER type 行 |
| 图形元素前缀 |
W/LIB/N/F/O/J |
统一 PRIMITIVE |
| 坐标单位 |
0.01 inch |
可配置 (mm/inch) |
| 删除处理 |
真删除 |
\|\|"" 标记删除 |
| 多终端支持 |
无 |
ticket + client 机制 |
| 数据模式 |
静态快照 |
日志追加 |
4.3 逆向 vs 文档学习的核心差异
| 维度 |
纯逆向工程 |
文档学习后 |
| 发现 layer 编号含义 |
靠猜(对错各50%) |
? 官方明确 |
| ticket 机制 |
完全不知道 |
? 文档讲得很清楚 |
| V3 架构存在 |
不知道还有个新格式 |
? 文档一开始就说明 |
| LIB 格式细节 |
? 基本还原出来 |
文档没详细展开V2 |
| SVG id 映射 |
? 意外发现 |
文档没提 |
| components hash |
? 猜对了用途 |
文档没提 |
| 删除机制 |
以为数据删了就没了 |
V3: 标记删除可恢复 |
| PCB TRACK 格式 |
? 还原出来了 |
文档没详细描述 |
4.4 最佳实践:双向印证
逆向 → 发现格式细节 → 验证文档描述是否匹配
文档 → 理解设计意图 → 修正逆向中的猜测错误
纯逆向的致命弱点: 不知道自己在猜,不知道自己猜对了。
纯文档的致命弱点: 文档描述的是设计意图,不是实际数据格式。
两者结合,才是完整的工程逆向能力。
附录
A. 电路 BOM
Value Qty Package Refs
---------------------------------------------------------------------------
AIR001 1 TSSOP-20_L6.5-W4.4-P0.65-LS6.4-BL U1
AMS1117-3.3RG 1 SOT-223-3_L6.4-W3.5-P2.30-LS7.0-BR U2
ULN2003 1 SOP-16_L10.0-W3.9-P1.27-LS6.0-BL Q1
J3Y 1 SOT-23-3_L2.9-W1.3-P1.90-LS2.4-TR Q2
28BYJ48 2 28BYJ48 U3,U4
LED-0603_R 1 LED0603_RED LED1
0.1u 1 C0603 C3
47u 2 CAP-D4.0×F1.5 C4,C5
1k 2 R0603 R3,R5
10k 2 R0603 R1,R2
K2-3.6×6.1_SMD 2 KEY-SMD_2P-L6.2-W3.6-LS8.0 RST,SET
USB-Micro_1 1 MICRO-USB-SMD_5P-... USB1
DC005-2.0MM 1 DC-IN-TH_DC005 DC1
HDR-M-2.54_1x3 1 HDR-M-2.54_1X3 J3
HDR-M-2.54_1x5 3 HDR-M-2.54_1X5 COM,J1,J2
HDR-M-2.54_1x6 1 HDR-M-2.54_1X6 SPI
---------------------------------------------------------------------------
总计 20个元件
B. PCB 网络表(32个)
+3V3, VCC, GND, BOOT, NRST,
O0, O1, O2, O3, O4, O5, O6, O7, O8, O9,
IO1, IO2, IO3, IO4, IO5, IO6, IO7,
LED1_1, Q2_2,
RX, TX, SCK, SI, SO, SS
C. 文件清单
/home/cs/workspace/画墙机器人m2/
├── 分析报告.md ← 初版报告
├── 综合分析报告.md ← 本报告
├── 画墙机器人m2.json ← 原理图JSON (V2格式)
├── PCB_画墙机器人m2.json ← PCB JSON (V2格式)
├── Schematic_xxx.svg ← 原理图矢量图
├── Schematic_xxx.png ← 原理图位图
├── Schematic_xxx.pdf ← 原理图PDF
└── info ← 工程元数据
/home/cs/workspace/easyeda_format/
├── lceda-pro-file-format-v3_2025.10.21.md ← V3格式文档 (3千行)
├── lceda-pro-file-format-v3_2025.10.21.pdf ← V3格式PDF
└── #U3010#U6cf0#U5c71#U6d3e1F#.epru ← V3官方示例
/home/cs/workspace/easyeda_format_v2/
├── #U539f#U7406#U56fe#U6587#U6863#U683c#U5f0f.pdf ← V2原理图格式
├── #U901a#U7528#U6587#U6863#U683c#U5f0f.pdf ← V2通用格式
└── PCB#U6587#U6863#U683c#U5f0f.pdf ← V2 PCB格式
报告生成时间:2026-03-25
操作:技术龙虾 @ OpenClaw