-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Noelia Scotti
committed
Oct 27, 2016
1 parent
2fc6cea
commit 6f4debc
Showing
5 changed files
with
929 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
# | ||
# Example python script to generate a BOM from a KiCad generic netlist | ||
# | ||
# Example: Sorted and Grouped CSV BOM | ||
# | ||
""" | ||
@package | ||
Generate a csv BOM list. | ||
Components are sorted by ref and grouped by value | ||
Fields are (if exist) | ||
Item, Qty, Reference(s), Value, LibPart, Footprint, Datasheet | ||
""" | ||
|
||
from __future__ import print_function | ||
|
||
# Import the KiCad python helper module and the csv formatter | ||
import kicad_netlist_reader | ||
import csv | ||
import sys | ||
|
||
def myEqu(self, other): | ||
"""myEqu is a more advanced equivalence function for components which is | ||
used by component grouping. Normal operation is to group components based | ||
on their value and footprint. | ||
In this example of a custom equivalency operator we compare the | ||
value, the part name and the footprint. | ||
""" | ||
result = True | ||
if self.getValue() != other.getValue(): | ||
result = False | ||
elif self.getPartName() != other.getPartName(): | ||
result = False | ||
elif self.getFootprint() != other.getFootprint(): | ||
result = False | ||
|
||
return result | ||
|
||
# Override the component equivalence operator - it is important to do this | ||
# before loading the netlist, otherwise all components will have the original | ||
# equivalency operator. | ||
kicad_netlist_reader.comp.__eq__ = myEqu | ||
|
||
if len(sys.argv) != 3: | ||
print("Usage ", __file__, "<generic_netlist.xml> <output.csv>", 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, 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) | ||
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', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) | ||
|
||
# Create a new csv writer object to use as the output formatter | ||
out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL ) | ||
|
||
# override csv.writer's writerow() to support encoding conversion (initial encoding is utf8): | ||
def writerow( acsvwriter, columns ): | ||
utf8row = [] | ||
for col in columns: | ||
utf8row.append( str(col) ) # currently, no change | ||
acsvwriter.writerow( utf8row ) | ||
|
||
# Output a set of rows as a header providing general information | ||
writerow( out, ['Source:', net.getSource()] ) | ||
writerow( out, ['Date:', net.getDate()] ) | ||
writerow( out, ['Tool:', net.getTool()] ) | ||
writerow( out, ['Generator:', sys.argv[0]] ) | ||
writerow( out, ['Component Count:', len(components)] ) | ||
writerow( out, [] ) | ||
writerow( out, ['Individual Components:'] ) | ||
writerow( out, [] ) # blank line | ||
writerow( out, columns ) | ||
|
||
# Output all the interesting components individually first: | ||
row = [] | ||
for c in components: | ||
del row[:] | ||
row.append('') # item is blank in individual table | ||
row.append('') # Qty is always 1, why print it | ||
row.append( c.getRef() ) # Reference | ||
row.append( c.getValue() ) # Value | ||
row.append( c.getLibName() + ":" + c.getPartName() ) # LibPart | ||
#row.append( c.getDescription() ) | ||
row.append( c.getFootprint() ) | ||
row.append( c.getDatasheet() ) | ||
|
||
# from column 7 upwards, use the fieldnames to grab the data | ||
for field in columns[7:]: | ||
row.append( c.getField( field ) ); | ||
|
||
writerow( out, row ) | ||
|
||
|
||
writerow( out, [] ) # blank line | ||
writerow( out, [] ) # blank line | ||
writerow( out, [] ) # blank line | ||
|
||
writerow( out, ['Collated Components:'] ) | ||
writerow( out, [] ) # blank line | ||
writerow( out, columns ) # reuse same columns | ||
|
||
|
||
|
||
# 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: | ||
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', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) | ||
item += 1 | ||
row.append( item ) | ||
row.append( len(group) ) | ||
row.append( refs ); | ||
row.append( c.getValue() ) | ||
row.append( c.getLibName() + ":" + c.getPartName() ) | ||
row.append( net.getGroupFootprint(group) ) | ||
row.append( net.getGroupDatasheet(group) ) | ||
|
||
# from column 7 upwards, use the fieldnames to grab the data | ||
for field in columns[7:]: | ||
row.append( net.getGroupField(group, field) ); | ||
|
||
writerow( out, row ) | ||
|
||
f.close() |
Oops, something went wrong.