[Global Options] Added field_lcsc_part: to select the LCSC/JLCPCB part field

This commit is contained in:
Salvador E. Tropea 2023-01-28 17:59:23 -03:00
parent ac14910505
commit c39d21f3cf
19 changed files with 444 additions and 28 deletions

View File

@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Internal templates import
- Better support for wrong pre-flight options (#360)
- A mechanism to cache downloaded 3D models
- Global options:
- field_lcsc_part: to select the LCSC/JLCPCB part field
- New outputs:
- `vrml` export the 3D model in Virtual Reality Modeling Language (#349)
- `ps_sch_print`, `dxf_sch_print` and `hpgl_sch_print` variants of

View File

@ -790,6 +790,8 @@ global:
This is because the plating reduces the hole, so you need to use a bigger drill.
For more information consult: https://www.eurocircuits.com/pcb-design-guidelines/drilled-holes/.
- `field_3D_model`: [string='_3D_model'] Name for the field controlling the 3D models used for a component.
- `field_lcsc_part`: [string=''] The name of the schematic field that contains the part number for the LCSC/JLCPCB distributor.
When empty KiBot will try to discover it.
- `filters`: [list(dict)] KiBot warnings to be ignored.
* Valid keys:
- `error`: [string=''] Error id we want to exclude.
@ -917,6 +919,7 @@ filters:
Column names are case-insensitive.
* Valid keys:
- `column`: [string=''] Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options.
- *field*: Alias for column.
- `invert`: [boolean=false] Invert the regex match result.
- `match_if_field`: [boolean=false] Match if the field exists, no regex applied. Not affected by `invert`.
@ -942,6 +945,7 @@ filters:
If empty this rule is ignored.
* Valid keys:
- `column`: [string=''] Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options.
- *field*: Alias for column.
- `invert`: [boolean=false] Invert the regex match result.
- `match_if_field`: [boolean=false] Match if the field exists, no regex applied. Not affected by `invert`.
@ -1732,6 +1736,7 @@ Notes:
Can be just the name of the field.
* Valid keys:
- **`field`**: [string=''] Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options.
- **`name`**: [string=''] Name to display in the header. The field is used when empty.
- `comment`: [string=''] Used as explanation for this column. The XLSX output uses it.
- `join`: [list(dict)|list(string)|string=''] List of fields to join to this column.
@ -1826,6 +1831,7 @@ Notes:
'_power', '_current', '_voltage', '_frequency', '_temp_coeff', '_manf', '_size'.
* Valid keys:
- **`field`**: [string=''] Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options.
- **`name`**: [string=''] Name to display in the header. The field is used when empty.
- `comment`: [string=''] Used as explanation for this column. The XLSX output uses it.
- `join`: [list(dict)|list(string)|string=''] List of fields to join to this column.
@ -1870,6 +1876,7 @@ Notes:
Can be just the name of the field.
* Valid keys:
- **`field`**: [string=''] Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options.
- **`name`**: [string=''] Name to display in the header. The field is used when empty.
- `comment`: [string=''] Used as explanation for this column. The XLSX output uses it.
- `join`: [list(dict)|list(string)|string=''] List of fields to join to this column.
@ -2723,6 +2730,7 @@ Notes:
Can be just the name of the field.
* Valid keys:
- **`field`**: [string=''] Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options.
- **`name`**: [string=''] Name to display in the header. The field is used when empty.
- `join`: [list(string)|string=''] List of fields to join to this column.
- **`fit_field`**: [string='Config'] Field name used to determine if a particular part is to be fitted (also DNC and variants).
@ -2766,6 +2774,7 @@ Notes:
regex: 'fiducial'.
* Valid keys:
- `column`: [string=''] Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options.
- *field*: Alias for column.
- `regex`: [string=''] Regular expression to match.
- *regexp*: Alias for regex.
@ -2779,6 +2788,7 @@ Notes:
If empty all the components are included.
* Valid keys:
- `column`: [string=''] Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options.
- *field*: Alias for column.
- `regex`: [string=''] Regular expression to match.
- *regexp*: Alias for regex.
@ -5093,7 +5103,8 @@ They include support for:
- _FusionPCB_drill: Drill files
- _FusionPCB_compress: Gerbers and drill files compressed in a ZIP
- _FusionPCB: _FusionPCB_gerbers+_FusionPCB_drill
- [JLCPCB](https://jlcpcb.com/): contain fabrication outputs compatible with JLC PCB
- [JLCPCB](https://jlcpcb.com/): contain fabrication outputs compatible with JLC PCB.
Use the `field_lcsc_part` global option to specify the LCSC part number field if KiBot fails to detect it.
- _JLCPCB_gerbers: Gerbers.
- _JLCPCB_drill: Drill files
- _JLCPCB_position: Pick and place, applies the `_rot_footprint` filter. You can change this filter.

View File

@ -1297,7 +1297,8 @@ They include support for:
- _FusionPCB_drill: Drill files
- _FusionPCB_compress: Gerbers and drill files compressed in a ZIP
- _FusionPCB: _FusionPCB_gerbers+_FusionPCB_drill
- [JLCPCB](https://jlcpcb.com/): contain fabrication outputs compatible with JLC PCB
- [JLCPCB](https://jlcpcb.com/): contain fabrication outputs compatible with JLC PCB.
Use the `field_lcsc_part` global option to specify the LCSC part number field if KiBot fails to detect it.
- _JLCPCB_gerbers: Gerbers.
- _JLCPCB_drill: Drill files
- _JLCPCB_position: Pick and place, applies the `_rot_footprint` filter. You can change this filter.

View File

@ -295,7 +295,8 @@ outputs:
columns:
# [string=''] Used as explanation for this column. The XLSX output uses it
- comment: ''
# [string=''] Name of the field to use for this column
# [string=''] Name of the field to use for this column.
# Use `_field_lcsc_part` to get the value defined in the global options
field: 'Row'
# [list(dict)|list(string)|string=''] List of fields to join to this column
join:
@ -333,7 +334,8 @@ outputs:
cost_extra_columns:
# [string=''] Used as explanation for this column. The XLSX output uses it
- comment: ''
# [string=''] Name of the field to use for this column
# [string=''] Name of the field to use for this column.
# Use `_field_lcsc_part` to get the value defined in the global options
field: 'Row'
# [list(dict)|list(string)|string=''] List of fields to join to this column
join:
@ -552,7 +554,8 @@ outputs:
specs_columns:
# [string=''] Used as explanation for this column. The XLSX output uses it
- comment: ''
# [string=''] Name of the field to use for this column
# [string=''] Name of the field to use for this column.
# Use `_field_lcsc_part` to get the value defined in the global options
field: 'Row'
# [list(dict)|list(string)|string=''] List of fields to join to this column
join:
@ -1295,7 +1298,8 @@ outputs:
# [list(dict)|list(string)] List of columns to display.
# Can be just the name of the field
columns:
# [string=''] Name of the field to use for this column
# [string=''] Name of the field to use for this column.
# Use `_field_lcsc_part` to get the value defined in the global options
- field: 'Row'
# [list(string)|string=''] List of fields to join to this column
join: ''
@ -1337,7 +1341,8 @@ outputs:
# - column: Footprint
# regex: 'fiducial'
exclude_any:
# [string=''] Name of the column to apply the regular expression
# [string=''] Name of the column to apply the regular expression.
# Use `_field_lcsc_part` to get the value defined in the global options
- column: ''
# `field` is an alias for `column`
# [string=''] Regular expression to match
@ -1365,7 +1370,8 @@ outputs:
# Column names are case-insensitive.
# If empty all the components are included
include_only:
# [string=''] Name of the column to apply the regular expression
# [string=''] Name of the column to apply the regular expression.
# Use `_field_lcsc_part` to get the value defined in the global options
- column: ''
# `field` is an alias for `column`
# [string=''] Regular expression to match

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Salvador E. Tropea
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
# Description: Implements the KiBoM and IBoM filters.
@ -123,6 +123,7 @@ class Generic(BaseFilter): # noqa: F821
if not self.include_only: # Nothing to match against, means include all
return True
for reg in self.include_only:
reg.column = Optionable.solve_field_name(reg.column)
if reg.skip_if_no_field and not c.is_field(reg.column):
# Skip the check if the field doesn't exist
continue
@ -148,6 +149,7 @@ class Generic(BaseFilter): # noqa: F821
if not self.exclude_any: # Nothing to match against, means don't exclude any
return False
for reg in self.exclude_any:
reg.column = Optionable.solve_field_name(reg.column)
if reg.skip_if_no_field and not c.is_field(reg.column):
# Skip the check if the field doesn't exist
continue

View File

@ -240,6 +240,9 @@ class Globals(FiltersOptions):
more precedence than KiCad paths defined in the GUI.
You can make reference to any OS environment variable using ${VARIABLE}.
The KIPRJMOD is also available for expansion """
self.field_lcsc_part = ''
""" The name of the schematic field that contains the part number for the LCSC/JLCPCB distributor.
When empty KiBot will try to discover it """
self.set_doc('filters', " [list(dict)] KiBot warnings to be ignored ")
self._filter_what = 'KiBot warnings'
self.filters = FilterOptionsKiBot

View File

@ -119,10 +119,11 @@ class GS(object):
global_edge_plating = None
global_extra_pth_drill = None
global_field_3D_model = None
global_field_lcsc_part = None
global_hide_excluded = None
global_impedance_controlled = None
global_kiauto_time_out_scale = None
global_kiauto_wait_start = None
global_impedance_controlled = None
# This value will overwrite GS.def_global_output if defined
# Classes supporting global "output" option must call super().__init__()
# after defining its own options to allow Optionable do the overwrite.

View File

@ -128,6 +128,8 @@ DNC = {
# KiCost distributors
DISTRIBUTORS = ['arrow', 'digikey', 'farnell', 'lcsc', 'mouser', 'newark', 'rs', 'tme']
DISTRIBUTORS_F = [d+'#' for d in DISTRIBUTORS]
DISTRIBUTORS_STUBS = ['part#', '#', 'p#', 'pn', 'vendor#', 'vp#', 'vpn', 'num']
DISTRIBUTORS_STUBS_SEPS = '_- '
# ISO ISO4217 currency codes
# Not all, but the ones we get from the European Central Bank (march 2021)
ISO_CURRENCIES = {'EUR', 'USD', 'JPY', 'BGN', 'CZK', 'DKK', 'GBP', 'HUF', 'PLN', 'RON', 'SEK', 'CHF', 'ISK', 'NOK', 'HRK',

View File

@ -11,7 +11,7 @@ import re
from re import compile
from .error import KiPlotConfigurationError
from .gs import GS
from .misc import W_UNKOPS
from .misc import W_UNKOPS, DISTRIBUTORS_STUBS, DISTRIBUTORS_STUBS_SEPS
from . import log
logger = log.get_logger()
@ -468,6 +468,67 @@ class Optionable(object):
def color_str_to_rgb(self, color):
return self.color_to_rgb(self.parse_one_color(color))
@staticmethod
def _solve_field_name(field, empty_when_none):
""" Applies special replacements for field """
# The global name for the LCSC part field
if GS.global_field_lcsc_part:
logger.debug('- User selected: '+GS.global_field_lcsc_part)
return GS.global_field_lcsc_part
# No name defined, try to figure out
if not GS.sch and GS.sch_file:
GS.load_sch()
if not GS.sch:
logger.debug("- No schematic loaded, can't search the name")
return '' if empty_when_none else 'LCSC#'
if hasattr(GS.sch, '_field_lcsc_part'):
return GS.sch._field_lcsc_part
# Look for a common name
fields = {f.lower() for f in GS.sch.get_field_names([])}
for stub in DISTRIBUTORS_STUBS:
fld = 'lcsc'+stub
if fld in fields:
GS.sch._field_lcsc_part = fld
return fld
if stub != '#':
for sep in DISTRIBUTORS_STUBS_SEPS:
fld = 'lcsc'+sep+stub
if fld in fields:
GS.sch._field_lcsc_part = fld
return fld
if 'lcsc' in fields:
GS.sch._field_lcsc_part = 'LCSC'
return 'LCSC'
# Look for a field that only contains LCSC codes
comps = GS.sch.get_components()
lcsc_re = re.compile(r'C\d+')
for f in fields:
found = False
for c in comps:
val = c.get_field_value(f).strip()
if not val:
continue
if lcsc_re.match(val):
found = True
else:
break
if found:
GS.sch._field_lcsc_part = f
return f
logger.debug('- No LCSC field found')
res = '' if empty_when_none else 'LCSC#'
GS.sch._field_lcsc_part = res
return res
@staticmethod
def solve_field_name(field, empty_when_none=False):
if field != '_field_lcsc_part':
return field
logger.debug('Looking for LCSC field name')
field = Optionable._solve_field_name(field, empty_when_none)
logger.debug('Using {} as LCSC field name'.format(field))
return field
class BaseOptions(Optionable):
""" A class to validate and hold output options.

View File

@ -199,7 +199,8 @@ class BoMRegex(Optionable):
self._unkown_is_error = True
with document:
self.column = ''
""" Name of the column to apply the regular expression """
""" Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options """
self.regex = ''
""" Regular expression to match """
self.field = None
@ -215,6 +216,11 @@ class BoMRegex(Optionable):
self.invert = False
""" Invert the regex match result """
def config(self, parent):
super().config(parent)
if not self.column:
raise KiPlotConfigurationError("Missing or empty `column` in field regex ({})".format(str(self._tree)))
class VariantOptions(BaseOptions):
""" BaseOptions plus generic support for variants. """

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: MIT
# Project: KiBot (formerly KiPlot)
"""
@ -22,7 +22,7 @@ from copy import deepcopy
import os
import re
from .gs import GS
from .misc import W_BADFIELD, W_NEEDSPCB, DISTRIBUTORS, W_NOPART, W_MISSREF
from .misc import W_BADFIELD, W_NEEDSPCB, DISTRIBUTORS, W_NOPART, W_MISSREF, DISTRIBUTORS_STUBS, DISTRIBUTORS_STUBS_SEPS
from .optionable import Optionable, BaseOptions
from .registrable import RegOutput
from .error import KiPlotConfigurationError
@ -137,7 +137,8 @@ class BoMColumns(Optionable):
self._unkown_is_error = True
with document:
self.field = ''
""" *Name of the field to use for this column """
""" *Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options """
self.name = ''
""" *Name to display in the header. The field is used when empty """
self.join = BoMJoinField
@ -153,9 +154,10 @@ class BoMColumns(Optionable):
super().config(parent)
if not self.field:
raise KiPlotConfigurationError("Missing or empty `field` in columns list ({})".format(str(self._tree)))
self.field = self.solve_field_name(self.field)
field = self.field.lower()
# Ensure this is None or a list
# Also arrange it as field, cols...
field = self.field.lower()
if isinstance(self.join, type):
self.join = None
elif isinstance(self.join, str):
@ -1030,12 +1032,12 @@ class BoM(BaseOutput): # noqa: F821
mpn_fields = fld_set.intersection(mpn_set)
# Look for distributor part number
dpn_set = set()
for stub in ['part#', '#', 'p#', 'pn', 'vendor#', 'vp#', 'vpn', 'num']:
for stub in DISTRIBUTORS_STUBS:
for dist in DISTRIBUTORS:
dpn_set.add(dist+stub)
if stub != '#':
dpn_set.add(dist+'_'+stub)
dpn_set.add(dist+'-'+stub)
for sep in DISTRIBUTORS_STUBS_SEPS:
dpn_set.add(dist+sep+stub)
dpn_fields = fld_set.intersection(dpn_set)
# Collect the used distributors
dists = set()

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Salvador E. Tropea
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2018 John Beard
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
@ -8,6 +8,7 @@
import os
from pcbnew import (PLOT_FORMAT_GERBER, FromMM, ToMM)
from .gs import GS
from .optionable import Optionable
from .out_any_layer import (AnyLayer, AnyLayerOptions)
from .error import KiPlotConfigurationError
from .macros import macros, document, output_class # noqa: F401
@ -122,6 +123,7 @@ class Gerber(AnyLayer):
# Filter the list of layers using the ones we are interested on
useful = GS.get_useful_layers(USEFUL_LAYERS, layers, include_copper=True)
tpl_layers = [AnyLayer.layer2dict(la) for la in useful]
lcsc_field = Optionable.solve_field_name('_field_lcsc_part', empty_when_none=True)
# Add the list of layers to the templates
for tpl in templates:
outs_used = []
@ -135,7 +137,7 @@ class Gerber(AnyLayer):
skip = True
out['run_by_default'] = False
out['options'] = {'pre_transform': ['_kicost_rename', '_rot_footprint']}
if out['type'] == 'bom' and not GS.sch_file:
if out['type'] == 'bom' and (not GS.sch_file or (out['name'].startswith('JLCPCB') and not lcsc_field)):
skip = True
out['run_by_default'] = False
if out['type'] == 'compress':

View File

@ -35,7 +35,8 @@ class KiBoMRegex(Optionable):
self._unkown_is_error = True
with document:
self.column = ''
""" Name of the column to apply the regular expression """
""" Name of the column to apply the regular expression.
Use `_field_lcsc_part` to get the value defined in the global options """
self.regex = ''
""" Regular expression to match """
self.field = None
@ -44,6 +45,12 @@ class KiBoMRegex(Optionable):
""" {regex} """
self._category = 'Schematic/BoM'
def config(self, parent):
super().config(parent)
if not self.column:
raise KiPlotConfigurationError("Missing or empty `column` in regex ({})".format(str(self._tree)))
self.column = Optionable.solve_field_name(self.column)
def __str__(self):
return self.column+'\t'+self.regex
@ -55,7 +62,8 @@ class KiBoMColumns(Optionable):
self._unkown_is_error = True
with document:
self.field = ''
""" *Name of the field to use for this column """
""" *Name of the field to use for this column.
Use `_field_lcsc_part` to get the value defined in the global options """
self.name = ''
""" *Name to display in the header. The field is used when empty """
self.join = Optionable
@ -67,6 +75,7 @@ class KiBoMColumns(Optionable):
super().config(parent)
if not self.field:
raise KiPlotConfigurationError("Missing or empty `field` in columns list ({})".format(str(self._tree)))
self.column = Optionable.solve_field_name(self.column)
if isinstance(self.join, type):
self.join = None
elif isinstance(self.join, list):

View File

@ -9,7 +9,7 @@ filters:
comment: 'Only parts with JLC (LCSC) code'
type: generic
include_only:
- column: 'LCSC#'
- column: _field_lcsc_part
regex: '^C\d+'
groups:
@ -108,7 +108,7 @@ outputs:
- field: References
name: Designator
- Footprint
- field: 'LCSC#'
- field: _field_lcsc_part
name: 'LCSC Part #'
csv:
hide_pcb_info: true

View File

@ -0,0 +1,131 @@
(kicad_sch (version 20211123) (generator eeschema)
(uuid db0a65e7-fab8-4ee6-8724-c1011468bd27)
(paper "A4")
(lib_symbols
(symbol "Device:R" (pin_numbers hide) (pin_names (offset 0)) (in_bom yes) (on_board yes)
(property "Reference" "R" (id 0) (at 2.032 0 90)
(effects (font (size 1.27 1.27)))
)
(property "Value" "R" (id 1) (at 0 0 90)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at -1.778 0 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "R res resistor" (id 4) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "Resistor" (id 5) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_fp_filters" "R_*" (id 6) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "R_0_1"
(rectangle (start -1.016 -2.54) (end 1.016 2.54)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
)
(symbol "R_1_1"
(pin passive line (at 0 3.81 270) (length 1.27)
(name "~" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -3.81 90) (length 1.27)
(name "~" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
)
)
)
(symbol (lib_id "Device:R") (at 114.3 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 3ba877ba-6c15-4bf9-911a-bede4b8103e2)
(property "Reference" "R2" (id 0) (at 116.078 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 116.078 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 112.522 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 114.3 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "LCSC_pn" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 39c3be48-48be-4598-a62d-ee41b899e213))
(pin "2" (uuid 1b30cb63-49b1-4ba7-b097-7ae72754941f))
)
(symbol (lib_id "Device:R") (at 127 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 615091a6-0d61-4a51-9c02-509e158ea9d6)
(property "Reference" "R3" (id 0) (at 128.778 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 128.778 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 125.222 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "LCSC_pn" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 20f2f92a-ae98-4133-ba84-f5d7a9c977ae))
(pin "2" (uuid e088d214-94d0-44a2-a744-aa518c868708))
)
(symbol (lib_id "Device:R") (at 101.6 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid d90f5601-6146-47ff-a6ef-b6f3da310882)
(property "Reference" "R1" (id 0) (at 103.378 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 103.378 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 99.822 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 101.6 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "LCSC_pn" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 672f8777-9560-4f26-bcf9-d47c285b54e6))
(pin "2" (uuid b9f1a732-28ab-496c-93f7-3f99c9c56900))
)
(sheet_instances
(path "/" (page "1"))
)
(symbol_instances
(path "/d90f5601-6146-47ff-a6ef-b6f3da310882"
(reference "R1") (unit 1) (value "R") (footprint "")
)
(path "/3ba877ba-6c15-4bf9-911a-bede4b8103e2"
(reference "R2") (unit 1) (value "R") (footprint "")
)
(path "/615091a6-0d61-4a51-9c02-509e158ea9d6"
(reference "R3") (unit 1) (value "R") (footprint "")
)
)
)

View File

@ -0,0 +1,131 @@
(kicad_sch (version 20211123) (generator eeschema)
(uuid db0a65e7-fab8-4ee6-8724-c1011468bd27)
(paper "A4")
(lib_symbols
(symbol "Device:R" (pin_numbers hide) (pin_names (offset 0)) (in_bom yes) (on_board yes)
(property "Reference" "R" (id 0) (at 2.032 0 90)
(effects (font (size 1.27 1.27)))
)
(property "Value" "R" (id 1) (at 0 0 90)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at -1.778 0 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "R res resistor" (id 4) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "Resistor" (id 5) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_fp_filters" "R_*" (id 6) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "R_0_1"
(rectangle (start -1.016 -2.54) (end 1.016 2.54)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
)
(symbol "R_1_1"
(pin passive line (at 0 3.81 270) (length 1.27)
(name "~" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -3.81 90) (length 1.27)
(name "~" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
)
)
)
(symbol (lib_id "Device:R") (at 114.3 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 3ba877ba-6c15-4bf9-911a-bede4b8103e2)
(property "Reference" "R2" (id 0) (at 116.078 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 116.078 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 112.522 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 114.3 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Cryptic" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 39c3be48-48be-4598-a62d-ee41b899e213))
(pin "2" (uuid 1b30cb63-49b1-4ba7-b097-7ae72754941f))
)
(symbol (lib_id "Device:R") (at 127 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 615091a6-0d61-4a51-9c02-509e158ea9d6)
(property "Reference" "R3" (id 0) (at 128.778 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 128.778 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 125.222 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Cryptic" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 20f2f92a-ae98-4133-ba84-f5d7a9c977ae))
(pin "2" (uuid e088d214-94d0-44a2-a744-aa518c868708))
)
(symbol (lib_id "Device:R") (at 101.6 54.61 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid d90f5601-6146-47ff-a6ef-b6f3da310882)
(property "Reference" "R1" (id 0) (at 103.378 53.7753 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "R" (id 1) (at 103.378 56.3122 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (id 2) (at 99.822 54.61 90)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 101.6 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Cryptic" "C1234" (id 4) (at 127 54.61 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 672f8777-9560-4f26-bcf9-d47c285b54e6))
(pin "2" (uuid b9f1a732-28ab-496c-93f7-3f99c9c56900))
)
(sheet_instances
(path "/" (page "1"))
)
(symbol_instances
(path "/d90f5601-6146-47ff-a6ef-b6f3da310882"
(reference "R1") (unit 1) (value "R") (footprint "")
)
(path "/3ba877ba-6c15-4bf9-911a-bede4b8103e2"
(reference "R2") (unit 1) (value "R") (footprint "")
)
(path "/615091a6-0d61-4a51-9c02-509e158ea9d6"
(reference "R3") (unit 1) (value "R") (footprint "")
)
)
)

View File

@ -1559,3 +1559,34 @@ def test_sub_pcb_bp(test_dir):
ctx.expect_out_file(fname_b+'charger.kicad_pcb')
ctx.expect_out_file(fname_b+'connector.kicad_pcb')
ctx.clean_up(keep_project=True)
@pytest.mark.skipif(context.ki5(), reason="Needs porting")
def test_lcsc_field_known(test_dir):
""" Test we can detect a known LCSC field name """
prj = 'lcsc_field_known'
ctx = context.TestContextSCH(test_dir, prj, 'lcsc_field_detect', 'JLCPCB')
ctx.run(extra=['_JLCPCB_bom'])
r, _, _ = ctx.load_csv(prj+'_bom_jlc.csv')
assert r[0][3] == 'C1234'
@pytest.mark.skipif(context.ki5(), reason="Needs porting")
def test_lcsc_field_unknown(test_dir):
""" Test we can detect an unknown LCSC field name """
prj = 'lcsc_field_unknown'
ctx = context.TestContextSCH(test_dir, prj, 'lcsc_field_detect', 'JLCPCB')
ctx.run(extra=['_JLCPCB_bom'])
r, _, _ = ctx.load_csv(prj+'_bom_jlc.csv')
assert r[0][3] == 'C1234'
@pytest.mark.skipif(context.ki5(), reason="Needs porting")
def test_lcsc_field_specified(test_dir):
""" Test we select the field """
prj = 'lcsc_field_unknown'
ctx = context.TestContextSCH(test_dir, prj, 'lcsc_field_specified', 'JLCPCB')
ctx.run(extra=['_JLCPCB_bom'])
assert ctx.search_err('User selected.*Cryptic')
r, _, _ = ctx.load_csv(prj+'_bom_jlc.csv')
assert r[0][3] == 'C1234'

View File

@ -0,0 +1,6 @@
# Example KiBot config file
kibot:
version: 1
import:
- file: JLCPCB

View File

@ -0,0 +1,9 @@
# Example KiBot config file
kibot:
version: 1
global:
field_lcsc_part: Cryptic
import:
- file: JLCPCB