# -*- 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]))