abse/smartwatch-flex-top-only

Three-panel flex smartwatch with two parallel R3.9 bends, all components flat-top, low-profile JST connector harnesses, split heartbeat optical windows and screw-retained PCB mounting. Modeled 39 × 50.5 × 14.5mm prototype; 100% routing, zero native DRC and shorts. Hardware qualification pending.

Version
0.2.20
License
unset
Stars
0

scripts/verify-pcb-preview.py

from pathlib import Path
from collections import Counter
import hashlib,json
root=Path(__file__).resolve().parent.parent
read=lambda n:json.loads((root/f'dist/{n}/circuit.json').read_text())
flat=read('flat');preview=read('pcb')
def norm(v,key=''):
 if isinstance(v,dict):return {k:norm(x,k) for k,x in v.items() if not k.endswith('_id') and k!='is_on_folded_board'}
 if isinstance(v,list):return [norm(x) for x in v]
 if isinstance(v,(int,float)) and not isinstance(v,bool):return round(float(v),9)
 return v
def normalize(e):
 v=norm(e)
 if 'rotation' in v:v['rotation']=({k:round(x%360,9) for k,x in v['rotation'].items()} if isinstance(v['rotation'],dict) else round(v['rotation']%360,9))
 return json.dumps(v,sort_keys=True)
kinds=['pcb_board','pcb_component','pcb_port','pcb_smtpad','pcb_trace','pcb_via','pcb_plated_hole','pcb_copper_pour','pcb_keepout','pcb_cutout','cad_component']
for k in kinds:assert Counter(normalize(e) for e in flat if e['type']==k)==Counter(normalize(e) for e in preview if e['type']==k),k
assert not any('error' in e['type'] for e in preview)
assert not any(e['type'] in ['pcb_bend','pcb_stiffener'] for e in preview)
sha=lambda p:hashlib.sha256((root/p).read_bytes()).hexdigest()
r={'status':'PASS','version':'0.2.16','scope':'Display-only developed-layout entry omits unsupported bend/stiffener annotations. Every native copper/component and CAD asset matches the full flat manufacturing circuit. Rotations compared modulo360degrees.','pcbBoards':sum(e['type']=='pcb_board' for e in preview),'pcbComponents':sum(e['type']=='pcb_component' for e in preview),'pcbTraces':sum(e['type']=='pcb_trace' for e in preview),'allNativeCopperAndComponentsMatchFullFlatCircuit':True,'cadModelPositionsRotationsAndAssetsMatchFlatCircuit':True,'comparisonPrecisionMM':1e-9,'routeCacheSha256':sha('routing/final/cache.json'),'circuitSha256':sha('dist/pcb/circuit.json'),'nativeErrors':0}
(root/'reports/pcb-viewer-preview.json').write_text(json.dumps(r,indent=2)+'\n');print(r)