Compare commits
17 Commits
cd7fb288ad
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
469cb53119 | ||
|
|
5e12d5b81f | ||
|
|
38798ce8ea | ||
|
|
3d3fffee0e | ||
|
|
1e8af81591 | ||
|
|
3d4c36bcbd | ||
|
|
0826ef9df1 | ||
|
|
058c1bc455 | ||
|
|
aefd0879c3 | ||
| 8cf9b909e2 | |||
| ff063efde7 | |||
| 577b9e11e0 | |||
| 53a395af71 | |||
| b1d4a80a2f | |||
| 9cd18828eb | |||
| 4df8d34871 | |||
| 3c7968bdcd |
@@ -28,14 +28,21 @@ TEMP_DRC_REPORT_NAME = "_drc"
|
|||||||
TEMP_ERC_REPORT_NAME = "_erc"
|
TEMP_ERC_REPORT_NAME = "_erc"
|
||||||
|
|
||||||
# quiet
|
# quiet
|
||||||
STDOUT=subprocess.DEVNULL
|
KICAD_CLI_STDOUT=subprocess.DEVNULL
|
||||||
# verbose
|
# verbose
|
||||||
# STDOUT=subprocess.STDOUT
|
# KICAD_CLI_STDOUT=subprocess.STDOUT
|
||||||
|
|
||||||
class OutputReportType(Enum):
|
class OutputReportType(Enum):
|
||||||
JSON = 1
|
JSON = 1
|
||||||
REPORT = 2
|
REPORT = 2
|
||||||
|
|
||||||
|
def get_file_extension(self) -> str:
|
||||||
|
match self:
|
||||||
|
case OutputReportType.JSON: return "json"
|
||||||
|
case OutputReportType.REPORT: return "rpt"
|
||||||
|
# dont trust it
|
||||||
|
case _: return "txt"
|
||||||
|
|
||||||
# this is a thin vale on the kicad cli tool
|
# this is a thin vale on the kicad cli tool
|
||||||
class KicadProject:
|
class KicadProject:
|
||||||
|
|
||||||
@@ -49,16 +56,17 @@ class KicadProject:
|
|||||||
def erc_check(
|
def erc_check(
|
||||||
self,
|
self,
|
||||||
report_format : OutputReportType = OutputReportType.JSON,
|
report_format : OutputReportType = OutputReportType.JSON,
|
||||||
return_report : bool = False
|
return_report : bool = False,
|
||||||
|
additional_args : str = ""
|
||||||
) -> None | dict | str:
|
) -> None | dict | str:
|
||||||
format_type = report_format.name.lower()
|
format_type = report_format.name.lower()
|
||||||
pcb_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
||||||
erc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_ERC_REPORT_NAME}.{format_type}"
|
erc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_ERC_REPORT_NAME}.{report_format.get_file_extension()}"
|
||||||
|
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} sch erc {pcb_file_path} --output {erc_report_path} --format {format_type}',
|
f'{KICAD_CLI_PATH} sch erc {sch_file_path} --output {erc_report_path} --format {format_type} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
@@ -77,17 +85,19 @@ class KicadProject:
|
|||||||
def drc_check(
|
def drc_check(
|
||||||
self,
|
self,
|
||||||
report_format : OutputReportType = OutputReportType.JSON,
|
report_format : OutputReportType = OutputReportType.JSON,
|
||||||
return_report : bool = False
|
return_report : bool = False,
|
||||||
|
additional_args : str = ""
|
||||||
) -> None | dict | str:
|
) -> None | dict | str:
|
||||||
format_type = report_format.name.lower()
|
format_type = report_format.name.lower()
|
||||||
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
||||||
drc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_DRC_REPORT_NAME}.{format_type}"
|
drc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_DRC_REPORT_NAME}.{report_format.get_file_extension()}"
|
||||||
|
print(f"{format_type=}, {drc_report_path=}")
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} pcb drc {pcb_file_path} --output {drc_report_path} --format {format_type}',
|
f'{KICAD_CLI_PATH} pcb drc {pcb_file_path} --output {drc_report_path} --format {format_type} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
print(f"{retcode=}")
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
print(f"drc check failed return code {retcode}")
|
print(f"drc check failed return code {retcode}")
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -103,14 +113,15 @@ class KicadProject:
|
|||||||
|
|
||||||
def process_bom(
|
def process_bom(
|
||||||
self,
|
self,
|
||||||
return_csv : bool = False
|
return_csv : bool = False,
|
||||||
|
additional_args : str = ""
|
||||||
) -> None | list[list[str]]:
|
) -> None | list[list[str]]:
|
||||||
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
||||||
bom_output_path = Path(BOM_OUTPUT_PATH) / f"{self.project_name}{BOM_REPORT_NAME}.csv"
|
bom_output_path = Path(BOM_OUTPUT_PATH) / f"{self.project_name}{BOM_REPORT_NAME}.csv"
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} sch export bom {sch_file_path} --output {bom_output_path}',
|
f'{KICAD_CLI_PATH} sch export bom {sch_file_path} --output {bom_output_path} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
@@ -131,6 +142,7 @@ class KicadProject:
|
|||||||
background : str = "default",
|
background : str = "default",
|
||||||
preset : str = "follow_pcb_editor",
|
preset : str = "follow_pcb_editor",
|
||||||
zoom : int = 2,
|
zoom : int = 2,
|
||||||
|
additional_args : str = ""
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
image_typ = "png" | "jpg"
|
image_typ = "png" | "jpg"
|
||||||
@@ -140,9 +152,9 @@ class KicadProject:
|
|||||||
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
||||||
render_output_path = Path(PCB_IMAGE_OUTPUT_PATH) / f"{self.project_name}_render.{image_type}"
|
render_output_path = Path(PCB_IMAGE_OUTPUT_PATH) / f"{self.project_name}_render.{image_type}"
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} pcb render {pcb_file_path} --output {render_output_path} --preset {preset} --zoom {zoom} ',
|
f'{KICAD_CLI_PATH} pcb render {pcb_file_path} --output {render_output_path} --preset {preset} --zoom {zoom} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
@@ -152,13 +164,13 @@ class KicadProject:
|
|||||||
self.created_files.append(render_output_path)
|
self.created_files.append(render_output_path)
|
||||||
|
|
||||||
# i am not giving you the pdf to output if you want to do that yourself go ahead
|
# i am not giving you the pdf to output if you want to do that yourself go ahead
|
||||||
def create_schmatic_pdf(self) -> None:
|
def create_schmatic_pdf(self, additional_args="") -> None:
|
||||||
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
|
||||||
sch_report_path = Path(SCHEMATIC_OUTPUT_PATH) / f"{self.project_name}{SCHEMATIC_FILE_SUFFIX}.pdf"
|
sch_report_path = Path(SCHEMATIC_OUTPUT_PATH) / f"{self.project_name}{SCHEMATIC_FILE_SUFFIX}.pdf"
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} sch export pdf {sch_file_path} --output {sch_report_path}',
|
f'{KICAD_CLI_PATH} sch export pdf {sch_file_path} --output {sch_report_path} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
@@ -167,13 +179,14 @@ class KicadProject:
|
|||||||
|
|
||||||
self.created_files.append(sch_report_path)
|
self.created_files.append(sch_report_path)
|
||||||
|
|
||||||
def create_pcb_pdf(self, layers : list[str] = ["F.Cu", "B.Cu"]) -> None:
|
|
||||||
|
def create_pcb_pdf(self, layers : list[str] = ["F.Cu", "B.Cu"], additional_args : str = "") -> None:
|
||||||
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
|
||||||
pcb_report_path = Path(PCB_PDF_OUTPUT_PATH) / f"{self.project_name}{PCB_PDF_FILE_SUFFIX}.pdf"
|
pcb_report_path = Path(PCB_PDF_OUTPUT_PATH) / f"{self.project_name}{PCB_PDF_FILE_SUFFIX}.pdf"
|
||||||
retcode = subprocess.call(
|
retcode = subprocess.call(
|
||||||
f'{KICAD_CLI_PATH} pcb export pdf {pcb_file_path} --output {pcb_report_path} --layers {",".join(layers)}',
|
f'{KICAD_CLI_PATH} pcb export pdf {pcb_file_path} --output {pcb_report_path} --layers {",".join(layers)} {additional_args}',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=STDOUT
|
stdout=KICAD_CLI_STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
if (retcode != 0):
|
if (retcode != 0):
|
||||||
@@ -189,13 +202,12 @@ def commit_files(files: list[Path], commit_message : str) -> None:
|
|||||||
ret_add = subprocess.call(f"git add {file}", shell=True)
|
ret_add = subprocess.call(f"git add {file}", shell=True)
|
||||||
ret_commit = subprocess.call(f"git commit -m \"{commit_message}\"", shell=True)
|
ret_commit = subprocess.call(f"git commit -m \"{commit_message}\"", shell=True)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
# find all kicad project files to operate on
|
# find all kicad project files to operate on
|
||||||
for path in Path(".").rglob('*.kicad_pro'):
|
for path in Path(".").rglob('*.kicad_pro'):
|
||||||
k = KicadProject(path)
|
k = KicadProject(path)
|
||||||
k.drc_check(report_format=OutputReportType.RPT)
|
k.drc_check(report_format = OutputReportType.REPORT)
|
||||||
k.erc_check(report_format=OutputReportType.RPT)
|
k.erc_check(report_format = OutputReportType.REPORT)
|
||||||
k.process_bom()
|
k.process_bom()
|
||||||
k.create_schmatic_pdf()
|
k.create_schmatic_pdf()
|
||||||
k.get_image()
|
k.get_image()
|
||||||
|
|||||||
13
docs/test_drc.rpt
Normal file
13
docs/test_drc.rpt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
** Drc report for test.kicad_pcb **
|
||||||
|
** Created on 2026-02-18T17:38:29+1300 **
|
||||||
|
|
||||||
|
** Found 1 DRC violations **
|
||||||
|
[invalid_outline]: Board has malformed outline (no edges found on Edge.Cuts layer)
|
||||||
|
Local override; error
|
||||||
|
@(0.0000 mm, 0.0000 mm): PCB
|
||||||
|
|
||||||
|
** Found 0 unconnected pads **
|
||||||
|
|
||||||
|
** Found 0 Footprint errors **
|
||||||
|
|
||||||
|
** End of Report **
|
||||||
5
docs/test_erc.rpt
Normal file
5
docs/test_erc.rpt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERC report (2026-02-18T17:38:29+1300, Encoding UTF8)
|
||||||
|
|
||||||
|
***** Sheet /
|
||||||
|
|
||||||
|
** ERC messages: 0 Errors 0 Warnings 0
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.1 KiB |
Reference in New Issue
Block a user