文件
phonerail/.claude/skills/solidworks-assembly/SKILL.md
T
zhou yang和Claude Opus 5 ff50ccd4b0 新增 solidworks-assembly skill:EasyEDA STEP → SolidWorks 装配与干涉检查
本机环境已实测:SOLIDWORKS 2025 SP01.1(RevisionNumber 33.1.1)、
Python 3.14.3 64 位 + pywin32,GetActiveObject 可挂已开实例。

已跑通的链路:
- EasyEDA get3DFile 导 STEP —— 桥有 30s 硬超时,必须异步启动+轮询;
  4MB 分块 base64 取回(刀片 31.2MB/25s,底板 53.9MB/44s)
- GetImportFileData + LoadFile4 导入(得到带位号的装配树,一块板 95 个文档)
- 遍历 GetDocuments 拿临时顶层 SLDASM → AddComponent4 插入(⛔ AddComponent5 恒返回 None)
- ToolsCheckInterference2(0, EMPTY, False, pc, pf) 5 参形式可调
- CloseAllDocuments(True) 清理(295 文档 0.9s)

⛔ 未完成:刀片摆位(CreateTransform 卡在 pywin32 封送)、
坐标系(插入后两板被重心归零,§14 的平移量不能直接用)。
⇒ 现状能装能查,但两板堆在原点,干涉结果无工程意义。

NOTES-probed.md 记了 18 节实测坑,包括:
- 无参成员是属性不是方法(含 GetMathUtility 这个例外)
- SaveAs3 返回 True 但写出的是废件(外部引用断链)
- LoadFile4 不会插进当前装配体
- 动态派发"找不到成员"时用 _oleobj_.GetIDsOfNames + Invoke 绕行

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0168Bu6SEx3cXXCJLkdnE6zB
2026-09-12 14:08:36 +08:00

4.7 KiB
原始文件 Blame 文件历史

name, description
name description
solidworks-assembly 把 EasyEDA 的 PCB 导成 STEP、在本机 SOLIDWORKS 里装配并做干涉检查。用于「底板 + 刀片插在一起会不会撞」这类机械核对,也用于量插槽插入深度这类 EDA 侧算不出来的数。涉及 SolidWorks / STEP / 3D 装配 / 干涉检查 / 机械干涉 时触发。

SolidWorks 装配与干涉检查(PhoneRail 专用)

⚠ 动手前先读 NOTES-probed.md —— 那是本机逐条实测出来的 API 口径与坑, 每一条都踩过一次。不读会把同样的坑再踩一遍。 环境已实测:SOLIDWORKS 2025 SP01.1(RevisionNumber = 33.1.1)、 Python 3.14.3 64 位 + pywin32(32 位 Python 连不上 64 位 SW,本机不存在这问题)。

什么时候用

  • 底板与刀片、刀片与刀片之间的机械干涉核对(EDA 侧只能算 2.5D 净距,算不了竖插后的三维关系)
  • 量 EDA 侧拿不到的机械数:插槽插入深度、塑料体内腔、刀片底边离底板多高
  • ⚠ 但凡实物在手,优先用卡尺。STEP 里的连接器是厂商标称模型,不含公差; 3D 能替代"按标称值推算",替代不了实测。

整条链(每一步都已实测通过)

1. 从 EasyEDA 导出 STEP

# 桥有 30 s 硬超时,大板同步调用必断 ⇒ 异步启动 + 轮询
START = "window.__gen={state:'running'}; (async()=>{ ... get3DFile(name,'step',['Component Model'],'Outfit',true) ... })(); return {started:true};"
# 再每 5 s 查 window.__gen.state,done 后用 4 MB 分块 base64 取回

实测:刀片 31.2 MB(生成 22.6 s + 取回 2 s)、底板 53.9 MB(生成 40 s + 取回 4 s)。 归档在 .claude/r2/3d/(已 .gitignore)。细节见 NOTES §6。

2. 导入 SolidWorks

app  = wc.GetActiveObject('SldWorks.Application')   # 挂已开着的实例
data = app.GetImportFileData(step_path)
err  = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
app.LoadFile4(step_path, 'r', data, err)            # err.value == 0 即成功

导进来是带位号的装配树(R1~R0402~…、U4~TSSOP-24~…),一块板 95 个文档。 ⛔ 第三参不能传 None(报"类型不匹配");⛔ OpenDoc6 导 STEP 返回 None。见 NOTES §3。

3. 找到可插引用 + 装配

# 导入后**不要关文档**,遍历 GetDocuments 找:有路径 + GetType==2 + .SLDASM
p = ...   # → %TEMP%\swx…\IC~~\PhoneRail_base.step.SLDASM
c = asm.AddComponent4(p, '', 0.0, 0.0, 0.0)          # ✅ 用 AddComponent4

⛔ AddComponent5(8 参)在本机恒返回 None,换参数没用,直接用 AddComponent4。 ⛔ 别走"另存再插":SaveAs3 出来的是废件、CopyDocument 返回 2、OpenDoc7 打不开 STEP。 见 NOTES §11/§12/§15。

4. 干涉检查

pc = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_VARIANT, None)
pf = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_VARIANT, None)
n  = asm.ToolsCheckInterference2(0, EMPTY, False, pc, pf)   # 5 参,少一个都报"非选择性的参数"

⛔ 第 2 参只能传 EMPTY(VARIANT(VT_DISPATCH, None)),塞零部件元组会报"服务器出现意外情况"。

5. 清理

app.CloseAllDocuments(True)      # 295 个文档 0.9 s 关完,SW 不退出

⛔ 一关就清空 %TEMP%\swx…\IC~~\,所以第 3 步必须在清理之前做完。

⛔ 未完成的两步(别当成能用)

  1. 刀片摆位。变换矩阵算好了(NOTES §14),但 CreateTransform 卡在 pywin32 封送: GetMathUtility 要用 dispid 绕行才拿得到(NOTES §17),拿到后 CreateTransform 又报"找不到成员"——同一个病一层套一层,未解。
  2. 坐标系:AddComponent4 插进总装后,两块板都被重心归零 (刀片 x -45~45 / y -34~34、底板 x -49~49 / y -49~49), NOTES §14 那套"原点 = 板左下角"的平移量不能直接用,要按 GetBox 现算。

⇒ 现状:能装、能查干涉,但两块板都堆在原点,查出来的干涉没有工程意义。 要么解掉上面两点,要么在 SolidWorks 里手工拖一次(更快)。

调试时的通用招数

动态派发报"找不到成员"时,先确认名字在不在:

did = app._oleobj_.GetIDsOfNames('GetMathUtility')          # 在 → 返回 dispid
raw = app._oleobj_.Invoke(did, 0, pythoncom.DISPATCH_METHOD, 1)

还有一条贯穿始终的规律:无参成员基本都是属性(app.GetDocumentCount / doc.GetTitle / doc.EditRebuild3 都不加括号),有参的才是方法。但有例外(GetMathUtility), 拿不准就去 sldworks.tlb 查 invkind(NOTES §8 给了读法)。