app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
#!/usr/bin/env python3
"""NATIVE-resolution capture of the pcbnew taskbar button on AdomLapper.
desktop_screenshot_screen returns a downscaled frame (1568 px on a 2560 px
display), which made the first set of settings shots grainy. This captures
the taskbar band on the box itself (DPI-aware CopyFromScreen), pulls the PNG
over, and crops 1:1 around the button found by its green icon.
Usage: cap2.py <name> [frames] (frames>1 keeps the frame with the most
salmon/orange tint, for the attention-flash states)."""
import base64, json, os, subprocess, sys, time
from PIL import Image
SHOTS = "/home/adom/project/adom-desktop-kicad-bridge/dashboard/ui/assets/shots"
PULL = "/tmp/claude-1001/-home-adom-project/a82462cd-99a1-4a08-b142-383081e6ec8a/scratchpad/pull"
W, H = 272, 88
os.makedirs(PULL, exist_ok=True)
PS = r'''
Add-Type -AssemblyName System.Drawing
Add-Type -TypeDefinition 'using System.Runtime.InteropServices; public class D2 { [DllImport("user32.dll")] public static extern bool SetProcessDPIAware(); [DllImport("user32.dll")] public static extern int GetSystemMetrics(int n); }'
[D2]::SetProcessDPIAware() | Out-Null
$w=[D2]::GetSystemMetrics(0); $h=[D2]::GetSystemMetrics(1)
$band = 110
$bmp = New-Object System.Drawing.Bitmap $w, $band
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.CopyFromScreen(0, $h - $band, 0, 0, $bmp.Size)
$out = Join-Path $env:TEMP "adom-tb-%NAME%.png"
$bmp.Save($out, [System.Drawing.Imaging.ImageFormat]::Png)
Write-Output $out
'''
def ab(verb, args):
out = subprocess.run(["timeout", "120", "adom-bridge", "--ai-thread", "kicad-icon",
"--target", "AdomLapper", verb, json.dumps(args)],
capture_output=True, text=True).stdout
return json.loads(out)
def grab(tag):
ps = PS.replace("%NAME%", tag)
r = ab("run_script", {"interpreter": "powershell",
"scriptB64": base64.b64encode(ps.encode()).decode(),
"reason": "Capture the taskbar band at native resolution for a real settings screenshot"})
remote = (r.get("stdout") or "").strip().splitlines()[-1]
p = ab("pull_file", {"filePaths": [remote], "saveTo": PULL})
local = None
for cand in (p.get("files") or p.get("saved") or []):
local = cand if isinstance(cand, str) else (cand.get("localPath") or cand.get("path") or cand.get("saveTo"))
if not local:
local = os.path.join(PULL, os.path.basename(remote))
return Image.open(local).convert("RGB")
def button_center(im):
w, h = im.size; px = im.load()
cols = []
for x in range(w):
n = sum(1 for y in range(h) if (lambda r, g, b: g > 110 and g > r + 40 and g > b + 40 and r < 120)(*px[x, y]))
if n >= 10: cols.append(x)
runs, s, p = [], None, None
for x in cols:
if s is None: s = x
elif x != p + 1: runs.append((s, p)); s = x
p = x
if s is not None: runs.append((s, p))
runs = [r for r in runs if 22 <= r[1] - r[0] <= 50]
if not runs: raise SystemExit("green icon not found; runs=%r" % runs)
a, b = runs[-1]
# icon centre x; the button spans the full band height: centre ~ h-46 at 150%
return (a + b) // 2, h - 47
def tint(im):
px = im.load(); n = 0
for x in range(im.width):
for y in range(im.height):
r, g, b = px[x, y]
if r > 120 and r > g + 35 and r > b + 20 and g < 150: n += 1
return n
name = sys.argv[1]; frames = int(sys.argv[2]) if len(sys.argv) > 2 else 1
best, score = None, -1
for i in range(frames):
im = grab(f"{name}-{i}")
if os.environ.get('CENTER'):
cx, cy = [int(v) for v in os.environ['CENTER'].split(',')]
else:
cx, cy = button_center(im)
crop = im.crop((cx - W // 2, cy - H // 2, cx + W // 2, cy + H // 2))
sc = tint(crop)
print(f"frame {i}: band={im.size} center=({cx},{cy}) tint={sc}")
if sc > score: best, score = crop, sc
if frames > 1: time.sleep(0.45)
best.save(f"{SHOTS}/{name}.png")
best.resize((W * 2, H * 2), Image.NEAREST).save(
f"/tmp/claude-1001/-home-adom-project/a82462cd-99a1-4a08-b142-383081e6ec8a/scratchpad/n-{name}-x2.png")
print("saved", name, "tint", score)