diff --git a/README.md b/README.md index 629e44b..9c2bd12 100644 --- a/README.md +++ b/README.md @@ -6,26 +6,45 @@ # Usage -``` python +首先查看`config.yaml`,修改工作目录等配置信息 + +然后查看`rule.yaml`,选择适合你的规则 + +然后运行脚本,在输出目录中查看处理完成的gerber + +最后复制钻孔文件 + +``` shell +# yum/apt/brew/scoop/winget install python +pip install pyyaml python modify.py ``` -请手动替换脚本中header和工作目录为你自己的 +# 文件结构 -header获取方法:立创EDA导出gerber→随意打开一个gerber文件 +* `modify.py` 脚本主文件 +* `config.yaml` 通用配置信息 +* `rule.yaml` 针对不同软件gerber的正则识别规则 -## Noitce +# 提示 -目前仅对Kicad与Altium Designer所导出的gerber做适配,其他软件请发Issue并附带目录结构或者自力更生PR +目前仅对有限格式的gerber做适配,其他软件请发Issue并附带目录结构或者自力更生PR -对于Altium Designer所导出的gerber,请自行删除与下单无关的文件,避免影响脚本运行 +脚本并未严格测试,仅给各位提供一个绕过检测的思路,保险起见仍建议各位手动进行修改 -请一定不要漏掉钻孔文件,可能包括金属化和非金属化孔两个文件 +由于钻孔文件格式千奇百怪,脚本**不处理钻孔文件**,脚本完成后你需要手动复制钻孔文件 -导出gerber时注意一些细节 -* 使用`Protel格式文件扩展名`导出,此格式与LCEDA相同 -* 钻孔文件最好也为gerber格式 +作者并没有仔细研究嘉立创的判定规则,目前看来凑合能用,就这样吧 +作者不为使用脚本造成的任何后果负责 + +欢迎一切 新功能/bug/建议/对线/改错字 Issue/PR + +# 工作原理 + +脚本将会将你的gerber重命名为立创EDA的命名格式,并在gerber文件的头部添加立创EDA的注释信息 + +除此之外,脚本不会做任何处理 **低调使用** diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..ec580c8 --- /dev/null +++ b/config.yaml @@ -0,0 +1,35 @@ +# 此处存放文件头 文件名等配置信息 + +# 工作目录 +WorkDir: C:\Users\Public\Desktop + +# 输出目录,可留空 +DestDir: + +Header: |- + G04 EasyEDA Pro v1.9.28, 2023-01-14 19:19:00* + G04 Gerber Generator version 0.3* + +TextFileName: PCB下单必读.txt +TextFileContent: |- + 如何进行PCB下单 + + 请查看: + https://docs.lceda.cn/cn/PCB/Order-PCB + +FileName: + Outline: Gerber_BoardOutlineLayer.GKO + Top_Cu: Gerber_TopLayer.GTL + Bottom_Cu: Gerber_BottomLayer.GBL + InnerLayer1_Cu: Gerber_InnerLayer1.G1 + InnerLayer2_Cu: Gerber_InnerLayer2.G2 + InnerLayer3_Cu: Gerber_InnerLayer3.G3 + InnerLayer4_Cu: Gerber_InnerLayer4.G4 + Top_SilkScreen: Gerber_TopSilkscreenLayer.GTO + Bottom_SilkScreen: Gerber_BottomSilkscreenLayer.GBO + Top_SolderMask: Gerber_TopSolderMaskLayer.GTS + Bottom_SolderMask: Gerber_BottomSolderMaskLayer.GBS + Top_SolderPaste: Gerber_TopPasteMaskLayer.GTP + Bottom_SolderPaste: Gerber_BottomPasteMaskLayer.GBP + Drill_Pth: Drill_PTH_Through.DRL + Drill_Npth: Drill_NPTH_Through.DRL diff --git a/modify.py b/modify.py index 6205625..9bfe3fd 100644 --- a/modify.py +++ b/modify.py @@ -1,75 +1,68 @@ -import os -from tkinter import filedialog +Warn = """\033[0;31;40m +=======警告======= +此脚本仅包含有限的“自动重命名”功能,它: +- 不会对Gerber文件进行解析 +- 不会验证文件格式是否正确 +- 不会处理钻孔文件 +- 极有可能损坏你的文件或引起生产错误 +- 需要你根据实际情况进行修改 +如果你不知道自己在干什么,请手动修改文件而不是使用脚本 +请编辑此脚本以解除警告 +\033[0m""" +print(Warn) +raise Exception("READ THE WARNING") -header="""G04 Layer: TopLayer* -G04 EasyEDA v6.5.9, 2022-08-01 21:18:00* -G04 ac5e******************************************aa,10* -G04 Gerber Generator version 0.2* -G04 Scale: 100 percent, Rotated: No, Reflected: No * -G04 Dimensions in millimeters * -G04 leading zeros omitted , absolute positions ,4 integer and 5 decimal *\n""" -path = r"C:/Users/Acha/Desktop/gerber_PCB1" -textFile="""如何进行PCB下单 +import yaml, os, re -请查看: -https://docs.lceda.cn/cn/PCB/Order-PCB""" -textFileName="PCB下单必读.txt" +fconfig = open("config.yaml", "r", encoding="utf-8") +frule = open("rule.yaml", "r", encoding="utf-8") +Config = yaml.load(fconfig, Loader=yaml.FullLoader) +Rule = yaml.load(frule, Loader=yaml.FullLoader) -currentDir=os.listdir(path) -for file in currentDir: - if os.path.splitext(file)[-1][1:].lower() == "gbl": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BottomLayer.GBL")) - if os.path.splitext(file)[-1][1:].lower() == "gko": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BoardOutlineLayer.GKO")) - if os.path.splitext(file)[-1][1:].lower() == "gbp": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BottomPasteMaskLayer.GBP")) - if os.path.splitext(file)[-1][1:].lower() == "gbo": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BottomSilkscreenLayer.GBO")) - if os.path.splitext(file)[-1][1:].lower() == "gbs": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BottomSolderMaskLayer.GBS")) - if os.path.splitext(file)[-1][1:].lower() == "gtl": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_TopLayer.GTL")) - if os.path.splitext(file)[-1][1:].lower() == "gtp": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_TopPasteMaskLayer.GTP")) - if os.path.splitext(file)[-1][1:].lower() == "gto": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_TopSilkscreenLayer.GTO")) - if os.path.splitext(file)[-1][1:].lower() == "gts": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_TopSolderMaskLayer.GTS")) - if os.path.splitext(file)[-1][1:].lower() == "gd1": - os.rename(os.path.join(path,file),os.path.join(path,"Drill_Through.GD1")) - if os.path.splitext(file)[-1][1:].lower() == "gm1": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_MechanicalLayer1.GM1")) - if os.path.splitext(file)[-1][1:].lower() == "gm13": - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_MechanicalLayer13.GM13")) +WorkDir = Config["WorkDir"] +DestDir = Config["DestDir"] +WorkDirFiles = os.listdir(WorkDir) +if not DestDir: + DestDir=os.path.join(WorkDir,'output') +if not os.path.exists(DestDir): + os.mkdir(DestDir) - if file.find("_PCB-PTH")!=-1: - os.rename(os.path.join(path,file),os.path.join(path,"Drill_PTH_Through.DRL")) - if file.find("_PCB-NPTH")!=-1: - os.rename(os.path.join(path,file),os.path.join(path,"Drill_NPTH_Through.DRL")) - if file.find("_PCB-In1_Cu")!=-1 or file.find(".G1")!=-1: - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_InnerLayer1.G1")) - if file.find("_PCB-In2_Cu")!=-1 or file.find(".G2")!=-1: - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_InnerLayer2.G2")) - if file.find("_PCB-Edge_Cuts")!=-1 : - os.rename(os.path.join(path,file),os.path.join(path,"Gerber_BoardOutlineLayer.GKO")) +#创建PCB下单必读文档 +with open(os.path.join(DestDir, Config["TextFileName"]), "w") as textFile: + textFile.write(Config["TextFileContent"]) -currentDir=os.listdir(path) -for file in currentDir: - fileType=os.path.splitext(file)[-1][1:].lower() - if fileType!="txt" and fileType!="py": - f=open(os.path.join(path,file),"r") - fileData=f.read() - f.close() - f=open(os.path.join(path,file),"w") - f.write(header) - f.write(fileData) - f.close() +#检验文件是否齐全/重复匹配 +for key, value in Rule.items(): + matchFile = [] + rePattern = re.compile(pattern=value) -file=open(textFileName,"w") -file.write(textFile) -file.close() + for fileName in WorkDirFiles: + if rePattern.search(fileName): + matchFile.append(fileName) + if len(matchFile) < 1: + raise Exception(key + "匹配失败") + elif len(matchFile) > 1: + raise Exception(key + "重复匹配") + else: + print(key + " -> " + matchFile[0]) +#改名和加头操作 +for key, value in Rule.items(): + matchFile = "" + rePattern = re.compile(pattern=value) - + for fileName in WorkDirFiles: + if rePattern.search(fileName): + matchFile = fileName + + with open(os.path.join(WorkDir, matchFile), "r") as file: + fileData = file.read() + with open(os.path.join(DestDir, Config["FileName"][key]), "w") as file: + file.write(Config["Header"]) + file.write(fileData) + +fconfig.close() +frule.close() +exit() \ No newline at end of file diff --git a/requitrments.txt b/requitrments.txt new file mode 100644 index 0000000..4818cc5 --- /dev/null +++ b/requitrments.txt @@ -0,0 +1 @@ +pyyaml \ No newline at end of file diff --git a/rule.yaml b/rule.yaml new file mode 100644 index 0000000..0f4dac2 --- /dev/null +++ b/rule.yaml @@ -0,0 +1,67 @@ +# 此处存放各种规则,用于识别不同软件导出的gerber +# 所有规则均支持正则表达式 +# 用不到的层必须注释掉 + +# -------边框层规则------- +# Altium Designer根据你画板时边框所在层选择 +# KiCad一般是-Edge_Cuts或者Keep Out层 + +# KiCad +# Outline: -Edge_Cuts + +# 禁止布线层 Keep Out,Protel格式文件扩展名 +# 适用于Altium Designer +# Outline: (\.gko|\.GKO)$ + +# 机械1层 Mechanical Layer 1,Protel格式文件扩展名 +# 适用于KiCad Altium Designer +# Outline: (\.gm1|\.GM1)$ + +# 机械13层 Mechanical Layer 13,Protel格式文件扩展名 +# 适用于Altium Designer +# Outline: (\.gm13|\.GM13)$ + + +# -------其他层规则------- +# 根据自身情况选择,务必核对清楚 + +# KiCad +# Top_Cu: -F_Cu +# Bottom_Cu: -B_Cu +# # InnerLayer1_Cu: -In1_Cu +# # InnerLayer2_Cu: -In2_Cu +# # InnerLayer3_Cu: -In3_Cu +# # InnerLayer4_Cu: -In4_Cu +# Top_SilkScreen: -F_Silkscreen +# Bottom_SilkScreen: -B_Silkscreen +# Top_SolderMask: -F_Mask +# Bottom_SolderMask: -B_Mask +# Top_SolderPaste: -F_Paste +# Bottom_SolderPaste: -B_Paste + +# Protel格式文件扩展名 +# 适用于 KiCad Altium Designer +# Top_Cu: (\.gtl|\.GTL)$ +# Bottom_Cu: (\.gbl|\.GBL)$ +# # InnerLayer1_Cu: (\.g1|\.G1)$ # 请注意内层后缀名是g1/g2还是g2/g3 +# # InnerLayer2_Cu: (\.g2|\.G2)$ +# # InnerLayer3_Cu: (\.g3|\.G3)$ +# # InnerLayer4_Cu: (\.g4|\.G4)$ +# Top_SilkScreen: (\.gto|\.GTO)$ +# Bottom_SilkScreen: (\.gbo|\.GBO)$ +# Top_SolderMask: (\.gts|\.GTS)$ +# Bottom_SolderMask: (\.gbs|\.GBS)$ +# Top_SolderPaste: (\.gtp|\.GTP)$ +# Bottom_SolderPaste: (\.gbp|\.GBP)$ + +# 奇怪格式,别管它 +# Top_Cu: TOP +# Bottom_Cu: BOTTOM +# InnerLayer1_Cu: MID1_L2 +# InnerLayer2_Cu: MID2_L3 +# Top_SilkScreen: SST +# Bottom_SilkScreen: SSB +# Top_SolderMask: SMT +# Bottom_SolderMask: SMB +# Top_SolderPaste: SPT +# Bottom_SolderPaste: SPB \ No newline at end of file