app
AI Flow: Reverse Engineering
Public Made by Adomby adom
Photos of a PCB to a tagged KiCad copy: parts placed, copper and nets with their evidence, a schematic, a measured confidence score, bench tests and a video of the run.
main
Caleb
Version 0.3.0: new copper reader, dome via filter, every layer read from the photos, net evidence, measured confidence;…
e874d7d
const p=require(process.env.HOME+'/.cache/hero-studio/node_modules/puppeteer-core');const sleep=ms=>new Promise(r=>setTimeout(r,ms));
const U='http://localhost:8893/';
(async()=>{const b=await p.launch({headless:'new',executablePath:process.env.HOME+'/.cache/puppeteer/chrome/linux-150.0.7871.24/chrome-linux64/chrome',args:['--no-sandbox','--disable-gpu'],protocolTimeout:900000});
// flow window at 1x
let pg=await b.newPage();await pg.setViewport({width:1920,height:1080});await pg.goto(U,{waitUntil:'load'});await sleep(7000);
const clickN=async n=>{await pg.evaluate(n=>{const s=[...document.querySelectorAll('.n')].find(e=>e.textContent.trim()==='#'+n);const t=s.closest('button,[data-n],.rec,.item,li')||s.parentElement;t.scrollIntoView({block:'center'});t.click()},n)};
const tab=async t=>{await pg.evaluate(t=>{[...document.querySelectorAll('button')].find(e=>e.textContent.trim()===t).click()},t)};
await tab('AI Flow timeline');await sleep(5000);await pg.screenshot({path:'cap/f_timeline.png'});await tab('PCB');await sleep(3000);
for(const n of [6,15,73,81,97,101,120,123,126,133]){try{await clickN(n);await sleep(n>=76?14000:7000);await pg.screenshot({path:`cap/f_rec${n}.png`});console.log('rec',n)}catch(e){console.log('skip',n,e.message)}}
await tab('Schematic');await sleep(16000);await pg.screenshot({path:'cap/f_sch.png'});
await tab('Findings');await sleep(3000);await pg.screenshot({path:'cap/f_findings.png'});
await pg.close();
// board viewer at 2x, layer states and net highlights
const R=(s)=>new RegExp(s);
const shots=[
['126-connect','all-top','Top','Copper|Silk · Top|Board edge'],
['126-connect','all-bot','Bottom','Copper|Silk · Bot|Board edge'],
['126-connect','in2','Top','Copper · In2|Board edge'],
['126-connect','in3','Top','Copper · In3|Board edge'],
['126-connect','inner','Top','Copper · In[23]|Board edge'],
['123-mimic','f-cu','Top','Copper · Top|Board edge'],
['123-mimic','b-cu','Bottom','Copper · Bot|Board edge'],
['123-mimic','f-silk','Top','Silk · Top|Board edge'],
['123-mimic','b-silk','Bottom','Silk · Bot|Board edge'],
['123-mimic','f-mask','Top','Mask · Top|Board edge'],
['123-mimic','b-mask','Bottom','Mask · Bot|Board edge'],
['123-mimic','top','Top','Copper · Top|Silk · Top|Mask · Top|Board edge'],
['123-mimic','bot','Bottom','Copper · Bot|Silk · Bot|Mask · Bot|Board edge'],
['124-connect','route2','Top','Copper|Board edge'],
['125-connect','route4','Top','Copper|Board edge'],
['129-connect','route8','Top','Copper|Board edge'],
];
for(const [v,name,side,on] of shots){pg=await b.newPage();await pg.setViewport({width:1920,height:1080,deviceScaleFactor:2});
await pg.goto(`${U}files/views/${v}-pcb.html`,{waitUntil:'load',timeout:300000});await sleep(9000);
await pg.evaluate((side,on)=>{[...document.querySelectorAll('button')].find(e=>e.textContent.trim()===side)?.click();const re=new RegExp(on);document.querySelectorAll('.lyr').forEach(l=>{const c=l.querySelector('input');const w=re.test(l.querySelector('.lyr-name').textContent);if(c.checked!==w)c.click()});document.querySelectorAll('.panel').forEach(x=>x.style.display='none');window.AdomPcb?.fit?.()},side,on);
await sleep(4000);await pg.screenshot({path:`cap/p_${name}.png`});console.log('pcb',name);
if(name==='top'){for(const n of ['GND','VIN','PHASE_X1','DRV_SDO']){await pg.evaluate(n=>window.AdomPcb.highlightNet(n),n);await sleep(2500);await pg.screenshot({path:`cap/n_${n}.png`});console.log('net',n)}}
await pg.close()}
pg=await b.newPage();await pg.setViewport({width:1920,height:1080,deviceScaleFactor:2});await pg.goto(U+'files/views/123-mimic-sch.html',{waitUntil:'load',timeout:300000});await sleep(10000);await pg.screenshot({path:'cap/s_sch.png'});
console.log(await pg.evaluate(()=>[...document.querySelectorAll('select option')].map(e=>e.textContent).slice(0,12)));
await b.close();console.log('CAP_DONE')})().catch(e=>{console.error(e);process.exit(1)});