def _read_netlist(self,netlist_path=None): self._netlist_path = self.find_netlist_path(netlist_path) if self._netlist_path is None: return None # Generate an instance of a generic netlist and load the netlist tree. self._netlist = kicad_netlist_reader.netlist(self._netlist_path) # subset the components to those wanted in the BOM, controlled # by <configure> block in kicad_netlist_reader.py components = self._netlist.getInterestingComponents() compfields = self._netlist.gatherComponentFieldUnion(components) compfields -= set(['PartCount']) partfields = self._netlist.gatherLibPartFieldUnion() partfields -= set(['Reference','Value','Datasheet','Footprint','PartCount']) additional_columns = compfields | partfields # union self._column_names = ['Item','Reference(s)','Quantity'] self._base_column_length = len(self._column_names) if 'PartNumber' in additional_columns: self._column_names.append('PartNumber') if 'Vendor' in additional_columns: self._column_names.append('Vendor') if 'Description' in additional_columns: self._column_names.append('Description') # Get all of the components in groups of matching parts + values # (see kicad_netlist_reader.py) self._grouped_components = self._netlist.groupComponents(components)
# Import the KiCad python helper module and the csv formatter import kicad_netlist_reader import csv import sys import re if len(sys.argv) != 4: print("Usage ", __file__, "<generic_netlist.xml> <output.csv> <quantity>", file=sys.stderr) sys.exit(1) # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: e = "Can't open output file for writing: " + sys.argv[2] print(__file__, ":", e, file=sys.stderr) f = sys.stdout quantity_multiplier = 1 if (int(sys.argv[3]) > 1): quantity_multiplier = int(sys.argv[3]) # subset the components to those wanted in the BOM, controlled
def generate_boms(): if len(sys.argv) != 2: print("Usage ", __file__, "<netlist.xml>", file=sys.stderr) sys.exit(1) input_path = sys.argv[1] # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(input_path) # Open a file to write to, if the file cannot be opened output to stdout # instead try: output_dir = os.path.join(os.path.dirname(input_path),'bom') if not os.path.exists(output_dir): os.makedirs(output_dir) output_path = os.path.join(output_dir,'bom_pcb.csv') # if os.path.exists(output_path): # shutil.copyfile(output_path,output_path+'.bck') f = open(output_path, 'w') except IOError: e = "Can't open output file for writing: " + output_path print(__file__,":",e,sys.stderr) f = sys.stdout # subset the components to those wanted in the BOM, controlled # by <configure> block in kicad_netlist_reader.py components = net.getInterestingComponents() # Header providing general information # source = os.path.basename(net.getSource()) # f.write('Source: ' + source + '\n') # f.write('Date: ' + str(net.getDate()) + '\n') # f.write('Tool: ' + str(net.getTool()) + '\n') # f.write('Component Count: ' + str(len(components)) + '\n') # f.write('\n') compfields = net.gatherComponentFieldUnion(components) partfields = net.gatherLibPartFieldUnion() # remove Reference, Value, Datasheet, and Footprint, they will come from 'columns' below partfields -= set(['Reference','Value','Datasheet','Footprint']) columnset = compfields | partfields # union # prepend an initial 'hard coded' list and put the enchillada into list 'columns' columns = ['Item','Reference(s)','Value','Footprint','Quantity'] + sorted(list(columnset)) # Create a new csv writer object to use as the output formatter out = csv.writer(f,quotechar='\"',quoting=csv.QUOTE_MINIMAL ) # override csv.writer's writerow() to support utf8 encoding: def writerow(acsvwriter,columns): utf8row = [] for col in columns: utf8row.append(str(col).encode('utf8')) acsvwriter.writerow(utf8row) # Get all of the components in groups of matching parts + values # (see kicad_netlist_reader.py) grouped = net.groupComponents(components) # Output component information organized by group, aka as collated: row = [] for c in columns: row.append(c) writerow(out,row) item = 0 for group in grouped: del row[:] refs = "" # Add the reference of every component in the group and keep a reference # to the component so that the other data can be filled in once per group for component in group: if len(refs) > 0: refs += " " refs += component.getRef() c = component # Fill in the component groups common data # columns = ['Item','Reference(s)','Value','Footprint','Quantity'] + sorted(list(columnset)) item += 1 row.append(item) row.append(refs); row.append(c.getValue()) row.append(c.getFootprint()) row.append(len(group)) # from column 4 upwards, use the fieldnames to grab the data for field in columns[4:]: row.append( net.getGroupField(group, field) ); writerow(out,row) f.close() # Create vendor set vendor_set = set() for group in grouped: try: vendor = net.getGroupField(group,'Vendor') vendor_set |= set([vendor]) except: pass # Make order csv file for each vendor for vendor in vendor_set: # Open a file to write to, if the file cannot be opened output to stdout # instead try: output_dir = os.path.join(os.path.dirname(input_path),'bom') if not os.path.exists(output_dir): os.makedirs(output_dir) filename = str(vendor) + '_order_pcb.csv' output_path = os.path.join(output_dir,filename) f = open(output_path, 'w') # Create a new csv writer object to use as the output formatter out = csv.writer(f,quotechar='\"',quoting=csv.QUOTE_MINIMAL ) except IOError: e = "Can't open output file for writing: " + output_path print(__file__,":",e,sys.stderr) f = sys.stdout for group in grouped: del row[:] try: if vendor == net.getGroupField(group,'Vendor'): row.append(len(group)) row.append(net.getGroupField(group,'PartNumber')) except: pass writerow(out,row) f.close()
#print(other.getValue()) #elif self.getField("Manufacturer") != other.getField("Manufacturer"): # result = False '''elif self.getPartName() != other.getPartName(): result = False print('\''+other.getPartName()+'\'') print('\''+self.getPartName()+'\'')''' return result kicad_netlist_reader.comp.__eq__ = myEqu #kicad_netlist_reader.netlist().excluded_values.append("TestPoint") # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(sys.argv[1]) components = net.getInterestingComponents() grouped = net.groupComponents() thin = Side(style='thin', color="000000") thick = Side(style='thick', color="000000") wb = Workbook() worksheet = wb.active worksheet.page_setup.orientation = worksheet.ORIENTATION_LANDSCAPE title = NamedStyle(name="title") title.font = Font(bold=True, size=14) wb.add_named_style(title) header = NamedStyle(name="header")
try: f = open(args.output, 'w') except IOError: e = "Can't open output file for writing: " + args.output print(__file__, ":", e, sys.stderr) f = sys.stdout dates = [] tools = [] components = [] columnset = set() for netlist_file in args.netlist: # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(netlist_file) dates.append(net.getDate()) tools.append(net.getTool()) # subset the components to those wanted in the BOM, controlled # by <configure> block in kicad_netlist_reader.py components += net.getInterestingComponents() compfields = kicad_netlist_reader.netlist.gatherComponentFieldUnion( components) partfields = net.gatherLibPartFieldUnion() # remove Reference, Value, Datasheet, and Footprint, they will come from 'columns' below partfields -= set(['Reference', 'Value', 'Datasheet', 'Footprint'])
# Set up the database connection conn = sqlite3.connect(dbpath) cur = conn.cursor() # Get the default manufactuer from the database defaultMfgr = getmfgr('M0000000') if(defaultMfgr is None): defaultMfgr = 'Default MFG Error' # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(infile) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(outfile, 'w') except IOError: e = "Can't open output file for writing: " + outfile print( __file__, ":", e, sys.stderr ) f = sys.stdout # subset the components to those wanted in the BOM, controlled # by <configure> block in kicad_netlist_reader.py components = net.getInterestingComponents() compfields = net.gatherComponentFieldUnion(components)
infile = args.infile outfile = args.outfile # Set up the database connection conn = sqlite3.connect(dbpath) cur = conn.cursor() # Get the default manufactuer from the database defaultMfgr = getmfgr('M0000000') if (defaultMfgr is None): defaultMfgr = 'Default MFG Error' # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop net = kicad_netlist_reader.netlist(infile) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(outfile, 'w') except IOError: e = "Can't open output file for writing: " + outfile print(__file__, ":", e, sys.stderr) f = sys.stdout # subset the components to those wanted in the BOM, controlled # by <configure> block in kicad_netlist_reader.py components = net.getInterestingComponents() compfields = net.gatherComponentFieldUnion(components)
def process(pcbfile, side=pcbnew.F_Cu, netlist=None, output=None): refs = None # load netlist if netlist is not None: net = kicad_netlist_reader.netlist(netlist) refs = [x.getRef() for x in net.getInterestingComponents()] # build BOM print("Loading %s" % pcbfile) pcb = pcbnew.LoadBoard(pcbfile) bom_table = generate_bom(pcb, filter_layer=side, filter_refs=refs) footprints = load_footprints(pcb, layer=side) board_xmin, board_ymin, board_width, board_height = get_bbox(pcb) margin = Point(5, 15) text_margin = Point(5, 2) # Render all components into a base surface for performance base = cairo.RecordingSurface(cairo.Content.COLOR_ALPHA, None) ctx = cairo.Context(base) # Render Footprints render_footprints(pcb, ctx, footprints, BASE_STYLE) # Show Board Edge for context ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(0.25) ctx.rectangle(board_xmin, board_ymin, board_width, board_height) ctx.stroke() # for each part group, print page to PDF fname_out = output if output is None: sidename = "top" if side == pcbnew.F_Cu else "bottom" fname_out = os.path.splitext( pcbfile)[0] + "_place_" + sidename + ".pdf" with cairo.PDFSurface(fname_out, 72, 72) as pdf: for i, bom_row in enumerate(bom_table): print("Plotting page (%d/%d)" % (i + 1, len(bom_table))) pdf.set_size((board_width + 2 * margin.x) * POINTS_PER_MM, (board_height + 2 * margin.y) * POINTS_PER_MM) ctx = pangocairo.CairoContext(cairo.Context(pdf)) # Scale from points to mm ctx.scale(POINTS_PER_MM, POINTS_PER_MM) # Render Text render_text( ctx, text_margin.x, margin.y - text_margin.y, board_width + 2 * margin.x - 2 * text_margin.x, "%dx %s, %s" % (len(bom_row.refs), bom_row.value, bom_row.footprint), align_bottom=True) render_text( ctx, text_margin.x, board_height + margin.y + text_margin.y, board_width + 2 * margin.x - 2 * text_margin.x, ", ".join( bom_row.refs)) # Offset within page for margins+header ctx.translate(margin.x, margin.y) # Set corner of board on kicad page to 0,0 ctx.translate(-board_xmin, -board_ymin) ctx.set_source_surface(base, 0.0, 0.0) ctx.paint() render_footprints( pcb, ctx, footprints, HIGHLIGHT_STYLE, include_only=bom_row.refs) pdf.show_page() print("Output written to %s" % fname_out)