# %% Imports import shutil import subprocess import zipfile from pathlib import Path # %% Find the relevant files projects = list(Path(__file__).parent.glob("*.kicad_pro")) if len(projects) == 1: root_project = projects[0].resolve() else: raise NotImplementedError("Need to determine which project is the root one (when multiple exist for sim)") project_name = root_project.stem dir_out = root_project.parent / "outputs" if dir_out.exists(): shutil.rmtree(str(dir_out)) dir_out.mkdir(parents=True) print(f"Writing outputs to {dir_out}") # %% Verify state of repository # TODO: check if repo is committed and pushed or if we're in CI # %% Check Kicad version kicad_version = subprocess.run(["kicad-cli", "version"], capture_output=True, check=True).stdout.decode() major, minor, patch = kicad_version.split(".") if int(major) < 7: raise ValueError(f"Requires minimum Kicad version 7.0.0 buf found {kicad_version}") # %% General documentation PDFs subprocess.run( [ "kicad-cli", "sch", "export", "pdf", str(root_project.with_suffix(".kicad_sch")), "-o", str(dir_out / f"{project_name}_schematic.pdf"), ], check=True, ) subprocess.run( [ "kicad-cli", "pcb", "export", "pdf", str(root_project.with_suffix(".kicad_pcb")), "-o", str(dir_out / f"{project_name}_fabrication_drawing.pdf"), "--include-border-title", "--layers", ",".join(["Edge.Cuts", "F.Cu", "F.Mask", "F.Silkscreen", "F.Fab"]), ], check=True, ) subprocess.run( [ "kicad-cli", "pcb", "export", "step", str(root_project.with_suffix(".kicad_pcb")), "-o", str(dir_out / f"{project_name}.step"), "--subst-models", "--no-virtual", # TODO: decide if I want virtual models. I might just generate both ], check=True, ) # %% Fabrication Files dir_gerber = dir_out / f"{project_name}_gerbers" dir_gerber.mkdir(exist_ok=True) subprocess.run( [ "kicad-cli", "pcb", "export", "gerbers", str(root_project.with_suffix(".kicad_pcb")), "-o", str(dir_gerber), ], check=True, ) subprocess.run( [ "kicad-cli", "pcb", "export", "drill", str(root_project.with_suffix(".kicad_pcb")), "--separate-files", "--generate-map", # not necessary but kinda nice since I can't nicely make a drill table in the main pdf # "-o", # -0 flag is not working so I'm just using cwd instead # str(dir_gerber), ], cwd=str(dir_gerber.resolve()), check=True, ) # TODO: add version strings to every single filename # %% Zip up the gerbers with zipfile.ZipFile(dir_gerber.with_suffix(".zip"), "w") as z: for f in dir_gerber.glob("*"): z.write(f, f.name) # %% Assembly files subprocess.run( [ "kicad-cli", "pcb", "export", "pdf", str(root_project.with_suffix(".kicad_pcb")), "-o", str(dir_out / f"{project_name}_assembly_drawing.pdf"), "--include-border-title", "--layers", ",".join(["Edge.Cuts", "F.Mask", "F.Silkscreen", "F.Fab"]), ], check=True, ) subprocess.run( [ "kicad-cli", "sch", "export", "python-bom", str(root_project.with_suffix(".kicad_sch")), "-o", str(dir_out / f"{project_name}_bom.xml"), ], check=True, ) # TODO: post-process XML BOM into something more useful or skip XML altogether and just make an interactive HTML BOM # subprocess.run( # [ # "python3", # "path/to/InteractiveHtmlBom/generate_interactive_bom.py", # TODO: locate this somewhere reasonable # str(root_project.with_suffix(".kicad_pcb")), # ], # check=True, # )