#!/usr/bin/env python3 """对账 4:封装库完整性。 三项: 1. 原理图里每个元件引用的封装,库里都有; 2. 封装的焊盘号集合 ⊇ 符号的引脚号集合(少一个焊盘 = 网络接不上,PCB 里才会暴露); 3. 文件能被 KiCad 解析(交给 kicad-cli 做)。 """ import json, os, re, sys, collections sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from k_netlist import parse_pads ROOT = os.path.dirname(os.path.abspath(__file__)) SRC = os.path.join(ROOT, "eda_src") PRETTY = os.path.join(os.path.dirname(ROOT), "kicad", "lib", "PhoneRail.pretty") def fp_pads(path): s = open(path, encoding="utf-8").read() return {m.group(1) for m in re.finditer(r'\(pad "([^"]*)"', s)} def main(): have = {} for f in os.listdir(PRETTY): if f.endswith(".kicad_mod"): have[f[:-10]] = fp_pads(os.path.join(PRETTY, f)) ok = True for board in ("Board1", "Board2"): base = parse_pads(os.path.join(SRC, board, "netlist.asc")) want = collections.Counter(base["parts"].values()) missing = sorted(n for n in want if n and n not in have) print(f"[{board}] 引用封装 {len(want)} 种", end="") if missing: print(f" ✘ 库里缺 {len(missing)}: {missing[:6]}"); ok = False else: print(" ✔ 全部存在") # 焊盘号 vs 引脚号 tree = json.load(open(os.path.join(SRC, "_tree.json"), encoding="utf-8")) pages = next(x for x in tree["boards"] if x["board"] == board)["pages"] bad = [] for p in pages: g = json.load(open(os.path.join(SRC, board, p["name"] + ".geom.json"), encoding="utf-8")) for c in (g["prims"]["Component"] or []): if c["ComponentType"] != "part": continue fp = (c.get("Footprint") or {}).get("name") if fp not in have: continue pins = {str(q["PinNumber"]) for q in (c.get("__pins") or [])} miss = pins - have[fp] if miss: bad.append((c["Designator"], fp, sorted(miss)[:4])) if bad: print(f" ✘ 引脚号在封装里找不到对应焊盘 {len(bad)}: {bad[:4]}"); ok = False else: print(" ✔ 焊盘号覆盖全部引脚号") print("\n" + ("封装库检查通过 ✔" if ok else "封装库有问题 ✘")) sys.exit(0 if ok else 1) if __name__ == "__main__": main()