Skip to content

Commit

Permalink
Merge bb6a370 into 62267da
Browse files Browse the repository at this point in the history
  • Loading branch information
eeintech committed Aug 18, 2021
2 parents 62267da + bb6a370 commit 8461bdc
Show file tree
Hide file tree
Showing 14 changed files with 575 additions and 24 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test_deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ name: tests | linting | publishing
on:
push:
branches:
- master
- main
tags:
- "*.*.*"
paths-ignore:
- README.md
- images/**
pull_request:
branches:
- master
- main

jobs:
style:
Expand Down Expand Up @@ -86,6 +86,7 @@ jobs:
env:
DIGIKEY_CLIENT_ID: ${{ secrets.DIGIKEY_CLIENT_ID }}
DIGIKEY_CLIENT_SECRET: ${{ secrets.DIGIKEY_CLIENT_SECRET }}
MOUSER_PART_API_KEY: ${{ secrets.MOUSER_PART_API_KEY }}
- name: Coveralls
run: |
coveralls --version
Expand Down
7 changes: 7 additions & 0 deletions kintree/config/config_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ def load_config(path):
except:
cprint('[INFO]\tWarning: Failed to load Digi-Key configuration', silent=silent)
result = False
# Load Mouser configuration files
try:
config_files = os.path.join(path_to_root, 'mouser', '')
load_config(config_files)
except:
cprint('[INFO]\tWarning: Failed to load Mouser configuration', silent=silent)
result = False
# Load LCSC configuration files
try:
config_files = os.path.join(path_to_root, 'lcsc', '')
Expand Down
1 change: 1 addition & 0 deletions kintree/config/digikey/digikey_config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SUPPLIER_INVENTREE_NAME: Digi-Key
SEARCH_NAME: null
SEARCH_DESCRIPTION: null
SEARCH_REVISION: null
Expand Down
1 change: 1 addition & 0 deletions kintree/config/lcsc/lcsc_config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SUPPLIER_INVENTREE_NAME: LCSC Electronics
SEARCH_NAME: null
SEARCH_DESCRIPTION: null
SEARCH_REVISION: null
Expand Down
1 change: 1 addition & 0 deletions kintree/config/mouser/mouser_api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MOUSER_PART_API_KEY: null
10 changes: 10 additions & 0 deletions kintree/config/mouser/mouser_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SUPPLIER_INVENTREE_NAME: Mouser Electronics
SEARCH_NAME: null
SEARCH_DESCRIPTION: null
SEARCH_REVISION: null
SEARCH_KEYWORDS: null
SEARCH_SKU: null
SEARCH_MANUFACTURER: null
SEARCH_MPN: null
SEARCH_SUPPLIER_URL: null
SEARCH_DATASHEET: null
10 changes: 8 additions & 2 deletions kintree/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
version_info = {
'MAJOR_REVISION': 0,
'MINOR_REVISION': 4,
'RELEASE_STATUS': 3, # Digit means stable version
'RELEASE_STATUS': 4, # Digit means stable version
}
try:
version = '.'.join([str(v) for v in version_info.values()])
Expand Down Expand Up @@ -95,6 +95,9 @@ def load_user_config():
CONFIG_DIGIKEY_CATEGORIES = os.path.join(CONFIG_USER_FILES, 'digikey_categories.yaml')
# CONFIG_DIGIKEY_PARAMETERS = os.path.join(CONFIG_USER_FILES, 'digikey_parameters.yaml')

# Mouser
CONFIG_MOUSER_API = os.path.join(CONFIG_USER_FILES, 'mouser_api.yaml')

# KiCad
CONFIG_KICAD = os.path.join(CONFIG_USER_FILES, 'kicad.yaml')
CONFIG_KICAD_CATEGORY_MAP = os.path.join(CONFIG_USER_FILES, 'kicad_map.yaml')
Expand All @@ -120,14 +123,17 @@ def load_user_config():
AUTOMATIC_BROWSER_OPEN = CONFIG_GENERAL.get('AUTOMATIC_BROWSER_OPEN', False)

# Supported suppliers APIs
SUPPORTED_SUPPLIERS_API = ['Digi-Key', 'LCSC']
SUPPORTED_SUPPLIERS_API = ['Digi-Key', 'Mouser', 'LCSC']

# Digi-Key user configuration
CONFIG_DIGIKEY = config_interface.load_file(os.path.join(CONFIG_USER_FILES, 'digikey_config.yaml'))

# LCSC user configuration
CONFIG_LCSC = config_interface.load_file(os.path.join(CONFIG_USER_FILES, 'lcsc_config.yaml'))

# Mouser user configuration
CONFIG_MOUSER = config_interface.load_file(os.path.join(CONFIG_USER_FILES, 'mouser_config.yaml'))

# Generic API user configuration
CONFIG_SEARCH_API = config_interface.load_file(os.path.join(CONFIG_USER_FILES, 'search_api.yaml'))

Expand Down
31 changes: 27 additions & 4 deletions kintree/database/inventree_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ..config import config_interface
from ..database import inventree_api
from fuzzywuzzy import fuzz
from ..search import search_api, digikey_api, lcsc_api
from ..search import search_api, digikey_api, mouser_api, lcsc_api


def connect_to_server(timeout=5) -> bool:
Expand Down Expand Up @@ -250,6 +250,8 @@ def get_value_from_user_key(user_key: str, default_key: str, default_value=None)
user_search_key = None
if supplier == 'Digi-Key':
user_search_key = settings.CONFIG_DIGIKEY.get(user_key, None)
elif supplier == 'Mouser':
user_search_key = settings.CONFIG_MOUSER.get(user_key, None)
elif supplier == 'LCSC':
user_search_key = settings.CONFIG_LCSC.get(user_key, None)
else:
Expand All @@ -262,12 +264,31 @@ def get_value_from_user_key(user_key: str, default_key: str, default_value=None)
# Get value for user key, return value from default key if not found
return part_info.get(user_search_key, part_info.get(default_key, default_value))

def get_supplier_name(supplier: str) -> str:
''' Get InvenTree supplier name '''
# Check that supplier is supported
if supplier not in settings.SUPPORTED_SUPPLIERS_API:
return ''

if supplier == 'Digi-Key':
supplier_name = settings.CONFIG_DIGIKEY.get('SUPPLIER_INVENTREE_NAME', None)
elif supplier == 'Mouser':
supplier_name = settings.CONFIG_MOUSER.get('SUPPLIER_INVENTREE_NAME', None)
elif supplier == 'LCSC':
supplier_name = settings.CONFIG_LCSC.get('SUPPLIER_INVENTREE_NAME', None)
else:
supplier_name = supplier

return supplier_name

# Check that supplier argument is valid
if not supplier or (supplier != 'custom' and supplier not in settings.SUPPORTED_SUPPLIERS_API):
return part_form
# Get default keys
if supplier == 'Digi-Key':
default_search_keys = digikey_api.get_default_search_keys()
elif supplier == 'Mouser':
default_search_keys = mouser_api.get_default_search_keys()
elif supplier == 'LCSC':
default_search_keys = lcsc_api.get_default_search_keys()
else:
Expand All @@ -279,7 +300,7 @@ def get_value_from_user_key(user_key: str, default_key: str, default_value=None)
part_form['description'] = get_value_from_user_key('SEARCH_DESCRIPTION', default_search_keys[1], default_value='')
part_form['revision'] = get_value_from_user_key('SEARCH_REVISION', default_search_keys[2], default_value=settings.INVENTREE_DEFAULT_REV)
part_form['keywords'] = get_value_from_user_key('SEARCH_KEYWORDS', default_search_keys[1], default_value='')
part_form['supplier_name'] = supplier if supplier in settings.SUPPORTED_SUPPLIERS_API else ''
part_form['supplier_name'] = get_supplier_name(supplier)
part_form['supplier_part_number'] = get_value_from_user_key('SEARCH_SKU', default_search_keys[4], default_value='')
part_form['supplier_link'] = get_value_from_user_key('SEARCH_SUPPLIER_URL', default_search_keys[7], default_value='')
part_form['manufacturer_name'] = get_value_from_user_key('SEARCH_MANUFACTURER', default_search_keys[5], default_value='')
Expand Down Expand Up @@ -309,10 +330,12 @@ def supplier_search(supplier: str, part_number: str, test_mode=False) -> dict:
cprint(f'\n[MAIN]\t{supplier} search for {part_number}', silent=settings.SILENT)
if supplier == 'Digi-Key':
part_info = digikey_api.fetch_part_info(part_number)
elif supplier == 'Mouser':
part_info = mouser_api.fetch_part_info(part_number)
elif supplier == 'LCSC':
part_info = lcsc_api.fetch_part_info(part_number)

# Check Digi-Key data exist
# Check supplier data exist
if not part_info:
cprint(f'[INFO]\tError: Failed to fetch data for "{part_number}"', silent=settings.SILENT)

Expand All @@ -325,7 +348,7 @@ def supplier_search(supplier: str, part_number: str, test_mode=False) -> dict:

def inventree_create(part_info: dict, categories: list, kicad=False, symbol=None, footprint=None, show_progress=True, is_custom=False):
''' Create InvenTree part from supplier part data and categories '''
# TODO: Make 'supplier' a variable for use with other APIs (eg. LCSC, Mouser, etc)

part_pk = 0
new_part = False

Expand Down
85 changes: 71 additions & 14 deletions kintree/kintree_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import PySimpleGUI as sg
# Digi-Key API
from .search import digikey_api as digikey_api
# Mouser API
from .search import mouser_api as mouser_api
# SnapEDA API
from .search import snapeda_api as snapeda_api
# Progress
Expand Down Expand Up @@ -77,8 +79,8 @@ def user_settings_window():
return


def search_api_settings_window():
''' Part search API settings window '''
def digikey_api_settings_window():
''' Digi-Key API settings window '''

user_settings = config_interface.load_file(settings.CONFIG_DIGIKEY_API)

Expand Down Expand Up @@ -131,6 +133,55 @@ def save_settings(user_settings: dict):
return


def mouser_api_settings_window():
''' Mouser API settings window '''

user_settings = config_interface.load_file(settings.CONFIG_MOUSER_API)

search_api_layout = [
[
sg.Text('Mouser Part API Key '),
sg.InputText(user_settings['MOUSER_PART_API_KEY'], key='api_key'),
],
[
sg.Button('Test', size=(15, 1)),
sg.Button('Save', size=(15, 1)),
],
]
search_api_window = sg.Window(
'Mouser API (v1) Settings', search_api_layout, location=(500, 500)
)

while True:
api_event, api_values = search_api_window.read()

def save_settings(user_settings: dict):
new_settings = {
'MOUSER_PART_API_KEY': api_values['api_key'],
}
user_settings = {**user_settings, **new_settings}
config_interface.dump_file(user_settings, settings.CONFIG_MOUSER_API)
mouser_api.setup_environment()

if api_event == sg.WIN_CLOSED:
search_api_window.close()
return
elif api_event == 'Test':
# Automatically save settings
save_settings(user_settings)
if mouser_api.test_api():
result_message = 'Successfully connected to Mouser API'
else:
result_message = 'Failed to connect to Mouser API'
sg.popup_ok(result_message,
title='Mouser API Connect Test',
location=(500, 500))
else:
save_settings(user_settings)
search_api_window.close()
return


def inventree_settings_window():
''' InvenTree settings window '''

Expand Down Expand Up @@ -778,12 +829,23 @@ def build_choices(items: dict, category: str, subcategory=None) -> list:

return symbol, template, footprint

# Main

# Init
def init():
# Disable Digi-Key API logger
digikey_api.disable_api_logger()
# Fix for Windows EXE
import multiprocessing
multiprocessing.freeze_support()


# Main
def main():
''' Main GUI window '''

# Disable Digi-Key logger
init()

CREATE_CUSTOM = False

# Select PySimpleGUI theme
Expand All @@ -796,6 +858,7 @@ def main():
[
'User',
'Digi-Key',
'Mouser',
'KiCad',
'InvenTree',
],
Expand Down Expand Up @@ -842,7 +905,9 @@ def main():
if event == 'User':
user_settings_window()
elif event == 'Digi-Key':
search_api_settings_window()
digikey_api_settings_window()
elif event == 'Mouser':
mouser_api_settings_window()
elif event == 'InvenTree':
inventree_settings_window()
elif event == 'KiCad':
Expand Down Expand Up @@ -924,6 +989,8 @@ def main():
'\n- Part number is valid and not blank'
if values['supplier'] == 'Digi-Key':
error_message += '\n- Digi-Key API settings are correct ("Settings > Digi-Key")'
elif values['supplier'] == 'Mouser':
error_message += '\n- Mouser API settings are correct ("Settings > Mouser")'
elif values['supplier'] == 'LCSC':
error_message += '\n- Part number starts with "C" (LCSC code)'
# Missing Part Information
Expand Down Expand Up @@ -1176,13 +1243,3 @@ def main():
CREATE_CUSTOM = False

window.close()


if __name__ == '__main__':
# Disable Digi-Key API logger
digikey_api.disable_api_logger()
# Fix for Windows EXE
import multiprocessing
multiprocessing.freeze_support()
# Run main window
main()
1 change: 0 additions & 1 deletion kintree/search/lcsc_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def get_default_search_keys():
def find_categories(part_details: str):
''' Find categories '''
try:
part_details['parentCatalogName']
return part_details['parentCatalogName'], part_details['catalogName']
except:
return None, None
Expand Down
Loading

0 comments on commit 8461bdc

Please sign in to comment.