文件
phonerail/.claude/refresh_cache.py
zhou yang和Claude Opus 5 2bfe308b30 初始导入:PhoneRail 五路手机直供电源板
原理图/PCB 已在 EasyEDA 里做到 12 页跨页 0 漏接,固件刚完成骨架包 A1。
这次是把已有的一切一次性纳入版本控制,没有改动任何设计内容。

纳入:
- 设计与需求文档、PROGRESS.md、小米8 参考原理图 PDF 与追脚脚本
- .claude/ 下的 EasyEDA 桥接工具链与几何/网表缓存(eda-parts.json、
  pcb-parts.json、pcb-pads.json、p2-ch1.json 等,是重画各页的唯一事实来源)
- 117 张验证截图(本项目所有方向问题都是靠人眼看截图发现的,属于证据不是垃圾)
- firmware/ 的 A1 骨架与 site/ 文档站源码

.gitignore 排除:构建产物(firmware/build、host/build、sdkconfig)、
site/node_modules、__pycache__、桥接日志 _bridge.log、脚本自标的 *.stale。

.gitattributes 默认 `* -text`:现有 .py/.json 大多是 CRLF,原样存,
不让 git 重写行尾。唯一例外是 *.sh 强制 LF —— 带 \r 的 shell 脚本 bash 跑不了。

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

90 行
3.7 KiB
Python

# -*- coding: utf-8 -*-
u"""重新抓 pcb-parts.json / pcb-pads.json / sch-xy.json 三份缓存。
原理图改动 + importChanges 之后跑一次。
用法: /c/Python314/python .claude/refresh_cache.py"""
import io, json, os, sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run
PCB = '7e9415a16a909c51'
PAGES = [("P1-INPUT", "9a6096762e036e23"), ("P1B-5V", "508b1219ec8a9f83"),
("P2-CHANNEL", "e528be1438486876"), ("P2B-CH2", "b8afe2b674df51f1"),
("P2C-CH3", "38c5dbbf943f1a9e"), ("P2D-CH4", "2365af19390c50d6"),
("P2E-CH5", "af0926ecaacd8bac"), ("P3-CONTROL", "12f74666e70167e4"),
("P3B-EXPAND", "f42285b3728794d0"), ("P5-BTB", "58bacf3ddd60ed4e"),
("P6-FAN-EDL", "fd00f13e59336392")]
JS_PCB = """
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r=>setTimeout(r,2000));
const comps = await eda.pcb_PrimitiveComponent.getAll();
const parts = [], pads = [];
for (const c of comps) {
const d = c.getState_Designator();
const id = c.getState_PrimitiveId();
const x = c.getState_X(), y = c.getState_Y(), rot = c.getState_Rotation();
let fp = null;
try { fp = c.getState_Footprint(); } catch(e) {}
parts.push({d, fp: fp ? {libraryUuid: fp.libraryUuid, uuid: fp.uuid, name: fp.name} : null,
x: Math.round(x*10)/10, y: Math.round(y*10)/10, rot, layer: c.getState_Layer(), np: 0, bb: null});
let ps = [];
try { ps = await eda.pcb_PrimitiveComponent.getAllPinsByPrimitiveId(id); } catch(e) {}
let x0=null,y0=null,x1=null,y1=null;
for (const p of ps || []) {
const px = p.getState_X(), py = p.getState_Y();
let w = 0, h = 0;
try { const s = p.getState_Pad(); w = +s[1] || 0; h = +s[2] || 0; } catch(e) {}
const a = px - w/2, b = py - h/2, cc = px + w/2, dd = py + h/2;
x0 = (x0===null? a : Math.min(x0,a)); y0 = (y0===null? b : Math.min(y0,b));
x1 = (x1===null? cc: Math.max(x1,cc)); y1 = (y1===null? dd: Math.max(y1,dd));
}
parts[parts.length-1].np = (ps||[]).length;
pads.push({d, fp: fp ? fp.name : null, rot, np: (ps||[]).length,
off: (x0===null? null : [Math.round((x0-x)*10)/10, Math.round((y0-y)*10)/10,
Math.round((x1-x)*10)/10, Math.round((y1-y)*10)/10])});
}
return {parts, pads};
""" % PCB
JS_SCH = """
const sleep = ms => new Promise(r=>setTimeout(r,ms));
const out = {};
for (const [name, uuid] of %s) {
await eda.dmt_EditorControl.openDocument(uuid);
await sleep(900);
const lst = [];
for (const c of await eda.sch_PrimitiveComponent.getAll()) {
if (c.getState_ComponentType() !== 'part') continue;
let d = ''; try { d = c.getState_Designator() || ''; } catch(e) {}
if (!d) continue;
lst.push([d, Math.round(c.getState_X()), Math.round(c.getState_Y()), c.getState_Rotation()]);
}
out[name] = lst;
}
return out;
"""
r = run(JS_PCB, timeout=300)
assert r.get('success'), json.dumps(r, ensure_ascii=False)[:500]
parts, pads = r['result']['parts'], r['result']['pads']
sch = {}
for i in range(0, len(PAGES), 4):
rr = run(JS_SCH % json.dumps(PAGES[i:i+4], ensure_ascii=False), timeout=180)
assert rr.get('success'), json.dumps(rr, ensure_ascii=False)[:500]
sch.update(rr['result'])
for fn, obj in (('pcb-parts.json', parts), ('pcb-pads.json', pads), ('sch-xy.json', sch)):
with io.open(os.path.join(HERE, fn), 'w', encoding='utf-8') as f:
f.write(json.dumps(obj, ensure_ascii=False, indent=0))
print(fn, len(obj))
miss = [p['d'] for p in parts if not p['fp']]
if miss:
print(u'!! 取不到封装: %s' % ' '.join(miss[:20]))
nopad = [p['d'] for p in pads if not p['off']]
if nopad:
print(u'!! 取不到焊盘: %s' % ' '.join(nopad[:20]))