import os.path from operator import attrgetter import itertools import rdflib from rdflib import Literal, URIRef from rdflib.namespace import RDF, RDFS # from ..kicad import rdf as kicad_rdf from . import * from ..kicad.export import * class KicadImportProjectCommand(CliCommand): def __init__(self): super().__init__("kicad-import-project", "Import a KiCAD project") def run(self, argv): p = argparse.ArgumentParser(prog=self.key, description=self.description) p.add_argument("-o", "--output-dir", dest="output_dir", required=False) p.add_argument("-i", "--input", required=False) args = p.parse_args(argv) run(args) def run(args): config = read_config() if args.input is "-": src = sys.stdin else: if args.input is None: (filename, _) = os.path.splitext(config['project']['file']) filename += '.xml' else: filename = args.input if not isfile(filename): raise CliException("No such file: %s. Did you export the BOM?" % filename) src = open(filename, 'r') project_url = config['project']['url'] with src: project = export_to_graph(src, project_url) debug('Loaded %s tuples' % len(project)) if args.output_dir is not None: parent = args.output_dir if not os.path.exists(parent): os.mkdir(parent) output_file = os.path.join(parent, "project.ttl") with open(output_file, 'wb') as dst: project.serialize(destination=dst, encoding='utf-8', format='turtle') def import_project(g): for idx, t in enumerate(project.triples((None, None, None))): g.add(t) with_database(import_project) def export_to_graph(src: object, project_url: str) -> rdflib.Graph: export = Export.from_xml_file(src) # print('components:') # for c in export.components: # print(c) # for name in export.component_fields(): # cli.info(name) # cli.info('components:') # fmt = '%2s%3s' # cli.info(fmt % ('Ref', '')) components = sorted(export.components, key=attrgetter('ref')) component_count = 0 part_count = 0 has_part = 0 has_digikey = 0 for cls, cs in itertools.groupby(components, key=attrgetter('ref_class')): # cli.info('--- Class: %s ---' % cls) cs = sorted(cs, key=attrgetter('value')) for c in cs: component_count += 1 value = str(c.value) part = c.find_field('part') digikey = c.find_field('digikey') footprint = c.footprint if c.ref_class is not None: ref_class = c.ref_class ref_instance = c.ref_instance else: ref_class = c.ref ref_instance = '' # cli.info(fmt % (ref_class, ref_instance)) # cli.info(' Value: %s' % c.value.text) # if c.footprint: # cli.info(' Footprint: %s' % c.footprint) if part is not None: if part != 'NA': has_part += 1 if part is not None else 0 part_count += 1 if digikey is not None: has_digikey += 1 else: part = None else: part_count += 1 part = 'MISSING' # if part is not None: # cli.info(' Part: %s' % part) # if digikey is not None: # cli.info(' Digikey: %s' % digikey) # cli.info() # cli.info('=== Summary ===') # cli.info('Project URL: %s' % project_url) # cli.info('Number of components: %d' % component_count) # cli.info('Number of parts: %d' % part_count) # cli.info('Assigned part: %d / %2.f%%' % (has_part, (has_part / part_count) * 100)) # cli.info('Assigned digikey: %d / %2.f%%' % (has_digikey, (has_digikey / part_count) * 100)) g = create_graph(kicad=True) project = URIRef(project_url) g.add((project, RDF.type, kicad_rdf.KICAD_TYPE.project)) # The components and fields could/should have been a BNodes. Their generated names are not very nice. # TODO: try using a hash of the current value and put that under a special generated namespace. # 'http://example.org/my-board' + ref='C10' => 'http://example.org/my-boardC10' # hash('http://example.org/my-boardC10') => 123456 # add_prefix(hash) => 'https://trygvis.io/purl/kicad/generated#123456' footprints = set() for c in export.components: ns = rdflib.Namespace(project_url) node = ns[c.ref] g.add((project, kicad_rdf.KICAD.component, node)) g.add((node, RDF.type, kicad_rdf.KICAD_TYPE.schematic_component)) g.add((node, RDFS.label, Literal(c.ref))) g.add((node, kicad_rdf.KICAD.value, Literal(c.value.text))) footprint_uri = URIRef(kicad_rdf.KICAD_FOOTPRINT[quote_plus(c.footprint)]) if not footprint_uri in footprints: g.add((footprint_uri, RDF.type, kicad_rdf.KICAD_TYPE.footprint)) g.add((footprint_uri, RDFS.label, Literal(c.footprint))) footprints.add(footprint_uri) g.add((node, kicad_rdf.KICAD.footprint, footprint_uri)) for name, value in c.fields.items(): f = ns['%s-%s' % (c.ref, name)] g.add((node, kicad_rdf.KICAD.field, f)) g.add((f, RDF.type, kicad_rdf.KICAD_TYPE.field)) g.add((f, kicad_rdf.KICAD.field_name, Literal(name))) g.add((f, kicad_rdf.KICAD.field_value, Literal(value))) # TODO: serialize the data from too return g