New Design Review SpecLib/BOM scripts/spectrum_bom_general_prices.py
2025-05-18 14:32:52 +02:00

124 lines
3.4 KiB
Python

# BOM generation script for KiCAD (6+)
# Last update: 26/03/2025
# Author: Jorian Zwerver
# This scripts formats the BOM to the format of SPECTRUM with PRICES
"""
@package
Generate a comma delimited list (csv file type) in SPECTRUM style.
Components are sorted by reference and grouped by value.
Fields are (if exist)
'References', 'Value', 'MPN', 'Manufacturer', 'Description', 'Farnell', 'Mouser', 'Digikey', 'LCSC', 'Quantity'
Command line:
python "pathToFile/SpecLib/BOM scripts/spectrum_bom_general.py" "%I" "%O_BOM_GENERAL.csv"
"""
# Import libraries
from libs import pymouser
from libs import kicad_netlist_reader
from libs import dotenv
import sys
import csv
import sys
import os
import time
# Get netlist from schematic
net = kicad_netlist_reader.netlist(sys.argv[1])
# Load API keys
dotenv.load_dotenv()
# Initialize the package with the API key
MOUSER_API_KEY = os.getenv("MOUSER_API_KEY")
if MOUSER_API_KEY == None:
raise Exception("No .env file found. Please download the .env file from the Google Drive.")
mouser = pymouser.MouserAPI(MOUSER_API_KEY)
# Function to interface with Mouser API
def get_price_from_mouser(mpn, n) -> float:
err, res = mouser.search_by_PN(mpn)
if err:
print("Error during request:")
print(err)
return 0.0
else:
if res['NumberOfResult'] == 0:
print("No results matched the part number")
return 0.0
else:
part_prices = res['Parts'][0]['PriceBreaks']
if not part_prices:
return 0.0
for price in part_prices:
if(n >= price['Quantity']):
value = price['Price'][2:].replace(",",".")
else:
break
return n*float(value)
# Open CSV file
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
# Generate new CSV file with header
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)
out.writerow(['References', 'Value', 'MPN', 'Manufacturer', 'Description', 'Farnell', 'Mouser', 'Mouser Price', 'Digikey', 'LCSC', 'Quantity'])
# Generate groups
grouped = net.groupComponents()
# Keep track of API requests
request_cnt = 0
# Iterate over each group
for group in grouped:
# Get all component references neatly grouped together
refs = ", ".join(component.getRef() for component in group)
component = group[0]
# Component quantity
n = len(group)
# Mouser MPN
mouser_mpn = component.getField('Mouser')
# If there is a Mouser MPN, get component price
if not mouser_mpn:
mouser_price = 0.0
else:
mouser_price = get_price_from_mouser(mouser_mpn, n)
request_cnt = request_cnt + 1
# If too many requests, wait for a bit
if(request_cnt > 29):
print("30 request limit reached. Waiting for one minute.")
time.sleep(60)
request_cnt = 0
# Store all data in CSV
out.writerow([
refs,
component.getValue(),
component.getField('MPN'),
component.getField('Manufacturer'),
component.getDescription(),
component.getField('Farnell'),
mouser_mpn,
mouser_price,
component.getField('Digikey'),
component.getField('LCSC'),
n
])
print("All done!")