@@ -46,15 +46,11 @@ def warn(self, msg):
4646 wx .LogWarning (msg )
4747
4848
49- log = None # type: Logger
49+ log = None # type: Logger or None
5050
5151
52- def skip_component (m , config , extra_data , filter_layer ):
53- # type: (Component, Config, dict, str) -> bool
54- # filter part by layer
55- if filter_layer is not None and filter_layer != m .layer :
56- return True
57-
52+ def skip_component (m , config , extra_data ):
53+ # type: (Component, Config, dict) -> bool
5854 # skip blacklisted components
5955 ref_prefix = re .findall ('^[A-Z]*' , m .ref )[0 ]
6056 if m .ref in config .component_blacklist :
@@ -65,6 +61,10 @@ def skip_component(m, config, extra_data, filter_layer):
6561 if config .blacklist_empty_val and m .val in ['' , '~' ]:
6662 return True
6763
64+ # skip virtual components if needed
65+ if config .blacklist_virtual and m .attr == 'Virtual' :
66+ return True
67+
6868 # skip components with dnp field not empty
6969 if config .dnp_field and m .ref in extra_data \
7070 and config .dnp_field in extra_data [m .ref ] \
@@ -87,15 +87,14 @@ def skip_component(m, config, extra_data, filter_layer):
8787 return False
8888
8989
90- def generate_bom (pcb_modules , config , extra_data , filter_layer = None ):
91- # type: (list, Config, dict, str ) -> list
90+ def generate_bom (pcb_modules , config , extra_data ):
91+ # type: (list, Config, dict) -> dict
9292 """
9393 Generate BOM from pcb layout.
9494 :param pcb_modules: list of modules on the pcb
9595 :param config: Config object
9696 :param extra_data: Extra fields data
97- :param filter_layer: include only parts for given layer
98- :return: BOM table (qty, value, footprint, refs)
97+ :return: dict of BOM tables (qty, value, footprint, refs) and dnp components
9998 """
10099
101100 def convert (text ):
@@ -114,18 +113,16 @@ def natural_sort(l):
114113
115114 # build grouped part list
116115 warning_shown = False
116+ skipped_components = []
117117 part_groups = {}
118118 for i , m in enumerate (pcb_modules ):
119- if skip_component (m , config , extra_data , filter_layer ):
119+ if skip_component (m , config , extra_data ):
120+ skipped_components .append (i )
120121 continue
121122
122123 # group part refs by value and footprint
123124 norm_value = units .componentValue (m .val )
124125
125- # skip virtual components if needed
126- if config .blacklist_virtual and m .attr == 'Virtual' :
127- continue
128-
129126 extras = []
130127 if config .extra_fields :
131128 if m .ref in extra_data :
@@ -134,11 +131,9 @@ def natural_sort(l):
134131 else :
135132 # Some components are on pcb but not in schematic data.
136133 # Show a warning about possibly outdated netlist/xml file.
137- # Doing it only once when generating full bom is enough.
138- if filter_layer is None :
139- log .warn (
140- 'Component %s is missing from schematic data.' % m .ref )
141- warning_shown = True
134+ log .warn (
135+ 'Component %s is missing from schematic data.' % m .ref )
136+ warning_shown = True
142137 extras = ['' ] * len (config .extra_fields )
143138
144139 group_key = (norm_value , tuple (extras ), m .footprint , m .attr )
@@ -169,7 +164,23 @@ def sort_func(row):
169164 config .component_sort_order .append ('~' )
170165 bom_table = sorted (bom_table , key = sort_func )
171166
172- return bom_table
167+ result = {
168+ 'both' : bom_table ,
169+ 'skipped' : skipped_components
170+ }
171+
172+ for layer in ['F' , 'B' ]:
173+ filtered_table = []
174+ for row in bom_table :
175+ filtered_refs = [ref for ref in row [3 ]
176+ if pcb_modules [ref [1 ]].layer == layer ]
177+ if filtered_refs :
178+ filtered_table .append ((len (filtered_refs ), row [1 ],
179+ row [2 ], filtered_refs , row [4 ]))
180+
181+ result [layer ] = sorted (filtered_table , key = sort_func )
182+
183+ return result
173184
174185
175186def open_file (filename ):
@@ -274,14 +285,10 @@ def main(parser, config, logger):
274285 if not pcbdata or not components :
275286 logger .error ('Parsing failed.' )
276287 return
277- pcbdata ["bom" ]["both" ] = generate_bom (components , config , extra_fields )
278288
279- # build BOM
280- for layer in ['F' , 'B' ]:
281- bom_table = generate_bom (components , config , extra_fields ,
282- filter_layer = layer )
283- pcbdata ["bom" ][layer ] = bom_table
289+ pcbdata ["bom" ] = generate_bom (components , config , extra_fields )
284290
291+ # build BOM
285292 bom_file = generate_file (pcb_file_dir , pcb_file_name , pcbdata , config )
286293
287294 if config .open_browser :
0 commit comments