"""Rotate J1 by 180 degrees and place its mating face at the left board edge.""" import hashlib import json import shutil import pcbnew as pcb import route_local_r1 as base from schematic_maintenance import ROOT OUT = ROOT / 'out/input-connector-r1' def snapshot(board): return {f.GetReference(): (f.GetPosition().x, f.GetPosition().y, f.GetOrientationDegrees(), f.GetLayer(), [(p.GetNumber(), p.GetPosition().x, p.GetPosition().y, p.GetNetname()) for p in f.Pads()]) for f in board.GetFootprints()} def copper(board): return {t.m_Uuid.AsString(): (t.GetStart().x, t.GetStart().y, t.GetEnd().x, t.GetEnd().y, t.GetLayer(), t.GetWidth(), t.GetNetname()) for t in board.GetTracks()} def main(): assert not (OUT / 'verification.json').exists(), 'Completed checkpoint exists' OUT.mkdir(parents=True, exist_ok=True) base.OUT = OUT path = base.BOARD start_hash = hashlib.sha256(path.read_bytes()).hexdigest() backup = OUT / ('before-' + path.name) if backup.exists(): assert hashlib.sha256(backup.read_bytes()).hexdigest() == start_hash, 'Source changed since failed attempt' else: shutil.copy2(path, backup) board = pcb.LoadBoard(str(path)) before, tracks = snapshot(board), copper(board) initial = base.unconnected_count(board) part = next(f for f in board.GetFootprints() if f.GetReference() == 'J1') assert part.GetOrientationDegrees() == 90 assert not any(t.GetNetname() in {p.GetNetname() for p in part.Pads()} for t in board.GetTracks()), 'Review existing input copper first' part.SetOrientationDegrees(270) part.SetPosition(pcb.VECTOR2I(pcb.FromMM(58.4), pcb.FromMM(67))) part.Reference().SetTextAngle(pcb.EDA_ANGLE(0, pcb.DEGREES_T)) part.Reference().SetPosition(pcb.VECTOR2I(pcb.FromMM(58.4), pcb.FromMM(59))) candidate = path.with_name('PhoneRail-Board1-input-candidate.kicad_pcb') temporary = [candidate.with_suffix(s) for s in ('.kicad_pcb', '.kicad_pro', '.kicad_dru', '.kicad_prl')] assert all(not p.exists() for p in temporary) try: for suffix in ('.kicad_pro', '.kicad_dru'): shutil.copy2(path.with_suffix(suffix), candidate.with_suffix(suffix)) pcb.SaveBoard(str(candidate), board) report = base.drc(candidate, 'drc') assert not report['violations'], report['violations'] reloaded = pcb.LoadBoard(str(candidate)) after = snapshot(reloaded) assert all(value == after[ref] for ref, value in before.items() if ref != 'J1') assert copper(reloaded) == tracks assert base.unconnected_count(reloaded) == initial assert sorted((p[0], p[3]) for p in before['J1'][4]) == sorted((p[0], p[3]) for p in after['J1'][4]) assert hashlib.sha256(path.read_bytes()).hexdigest() == start_hash shutil.copy2(candidate, path) result = {'status': 'PLACEMENT_CORRECTED_NOT_RELEASED', 'reference': 'J1', 'before_position_mm': [63, 67], 'after_position_mm': [58.4, 67], 'before_angle_deg': 90, 'after_angle_deg': 270, 'mating_face': 'Left/outward; nominal outline x=50.25041mm, board edge x=50mm', 'native_drc_violations': 0, 'other_footprints_preserved': len(before)-1, 'existing_track_segments_preserved': len(tracks), 'unconnected_items': initial, 'board_sha256': hashlib.sha256(path.read_bytes()).hexdigest()} (OUT / 'verification.json').write_text(json.dumps(result, indent=2)+'\n', encoding='utf-8') print(json.dumps(result)) finally: for p in temporary: p.unlink(missing_ok=True) if __name__ == '__main__': main()