Devesh36/orbit-turntable

ORBIT is a USB-C-powered display turntable for photographing jewellery, models and small products. Four-layer ESP32-C3 / ULN2003 PCB, geared stepper, OLED, push encoder, home switch and buzzer, with an enclosed and exploded assembly. Hardware prototype; firmware and physical qualification remain separate.

Version
0.1.1
License
unset
Stars
0

scripts/validate.ts

import {readFileSync} from 'node:fs'
import {runAllChecks} from '@tscircuit/checks'
import {any_circuit_element,type AnyCircuitElement} from 'circuit-json'
import * as schemas from 'circuit-json'
import {nets} from '../index.circuit'
const reports=[]
for(const entry of ['index','assembly','exploded']){
 const data=JSON.parse(readFileSync(`dist/${entry}/circuit.json`,'utf8')) as AnyCircuitElement[]
 const source=data.filter(e=>e.type==='source_component'),ports=data.filter(e=>e.type==='source_port'),traces=data.filter(e=>e.type==='source_trace'),ns=data.filter(e=>e.type==='source_net')
 const connectivity:string[]=[]
 for(const [name,pins] of Object.entries(nets))for(const pin of pins){
  const [ref,label]=pin.split('.');const c=source.find(c=>c.name===ref);const p=ports.find(p=>p.source_component_id===c?.source_component_id&&(p.name===label||p.port_hints?.includes(label)));const n=ns.find(n=>n.name===name)
  if(!p||!n||!traces.some(t=>t.connected_source_port_ids.includes(p.source_port_id)&&t.connected_source_net_ids?.includes(n.source_net_id)))connectivity.push(`${name}: ${pin}`)
 }
 const schema=data.flatMap((e,i)=>{const schema=(schemas as Record<string,unknown>)[e.type] as typeof any_circuit_element|undefined;const r=(schema??any_circuit_element).safeParse(e);return r.success?[]:[{i,type:e.type,issues:r.error.issues.map(x=>({path:x.path,code:x.code,message:x.message}))}]})
 const independent=await runAllChecks(data)
 const errors=data.filter(e=>e.type.endsWith('_error')),warnings=data.filter(e=>e.type.endsWith('_warning'))
 const copper=data.filter(e=>e.type==='pcb_trace')
 const antenna=copper.flatMap(t=>t.route.filter(p=>p.route_type==='wire'&&p.x < -35.5&&Math.abs(p.y)<25).map(()=>t.pcb_trace_id))
 const board=data.find(e=>e.type==='pcb_board')
 const report={entry,components:source.length,nets:ns.length,traces:copper.length,vias:data.filter(e=>e.type==='pcb_via').length,board:board?{width:board.width,height:board.height,layers:board.num_layers}:null,errors:errors.length,warnings:warnings.length,independentErrors:independent.filter(e=>e.type.endsWith('_error')).length,schemaErrors:schema.length,connectivityErrors:connectivity.length,antennaViolations:antenna.length}
 console.log(JSON.stringify(report,null,2));if(errors.length)console.log(JSON.stringify(errors));if(schema.length)console.log(JSON.stringify(schema));if(connectivity.length)console.log(connectivity);if(report.independentErrors)console.log(JSON.stringify(independent.filter(e=>e.type.endsWith('_error'))));
 reports.push(report)
}
process.exitCode=reports.every(r=>!r.errors&&!r.independentErrors&&!r.schemaErrors&&!r.connectivityErrors&&!r.antennaViolations&&r.traces>0)?0:1