import argparse import rdflib import trygvis.eda.digikey.rdf as digikey_rdf from trygvis.eda import cli, EdaException class MakeBomCommand(cli.CliCommand): def __init__(self): super().__init__("make-bom", "Create a BOM for a project with all info for each part.") def run(self, argv): p = argparse.ArgumentParser(prog=self.key, description=self.description) p.add_argument("--project") p.add_argument("--version") args = p.parse_args(argv) run(args) class DigiKeyPart(object): def __init__(self, part_number): self.part_number = part_number self.attributes = {} def set_attribute(self, key, value): self.attributes[key] = value class Component(object): def __init__(self, ref, value): self.ref = ref self.value = value self.fields = {} def set_field(self, field_name, field_value): self.fields[field_name] = field_value def run(args): cli.with_database(lambda g: work(args, g)) def work(args, g): config = cli.read_config() project_url = args.project if args.project is not None else config['project']['url'] components = {} dk_parts = {} if args.version is not None: version_url = args.version version_uuid = None timestamp = None else: cli.info("Finding latest version") res = cli.sparql(g, """ SELECT ?project ?timestamp ?version_uuid WHERE { ?project a kicad:project ; kicad:timestamp ?timestamp ; kicad:version-uuid ?version_uuid ; kicad:version-of ?orig_project . } ORDER BY DESC(?timestamp) LIMIT 1 """, init_bindings={"orig_project": rdflib.URIRef(project_url)}) for row in res: version_url = row.project version_uuid = row.version_uuid timestamp = row.timestamp break else: raise EdaException("Could not find any version of project %s" % project_url) cli.info("Loading components for version %s, uuid=%s, timestamp=%s" % (version_url, version_uuid, timestamp)) res = cli.sparql(g, """ SELECT ?ref ?value WHERE { ?version a kicad:project ; kicad:component ?cmp . ?cmp a kicad:component ; kicad:value ?value ; rdfs:label ?ref . } ORDER BY ?ref """, init_bindings={"version": rdflib.URIRef(version_url)}) for row in res: c = Component(row.ref, row.value) components[row.ref] = c cli.info('ref=%s, value=%s' % (c.ref, c.value)) if len(components) == 0: raise EdaException("Could not find any components") cli.info("Loading custom component attributes") res = cli.sparql(g, """ SELECT ?ref ?field ?field_name ?field_value WHERE { ?version a kicad:project ; kicad:component ?cmp . ?cmp a kicad:component ; rdfs:label ?ref ; kicad:field ?field . ?field a kicad:field ; kicad:field-name ?field_name ; kicad:field-value ?field_value . } ORDER BY ?ref ?field_name """, init_bindings={"version": rdflib.URIRef(version_url)}) for row in res: # cli.debug('row: %s' % str(row)) c = components[row.ref] assert isinstance(c, Component) c.set_field(row.field_name, row.field_value) cli.info('%5s: %-20s %s' % (c.ref, row.field_name + ':', row.field_value)) cli.info("Loading Digi-Key parts for project") res = cli.sparql(g, """ SELECT ?ref ?part_number ?type ?value ?attr_type WHERE { ?version a kicad:project ; kicad:component ?cmp . ?cmp a kicad:component ; rdfs:label ?ref ; kicad:field ?d . ?d kicad:field-name "digikey" ; kicad:field-value ?part_number . ?part a dk:part ; # rdfs:label ?label ; dk:partNumber ?part_number ; dk:attribute-value ?attr_value . ?attr_value rdfs:label ?value . ?attr_type a dk:attributeType ; rdfs:label ?type ; dk:value ?attr_value . } ORDER BY ?ref ?attr_type ?attr_value """, init_bindings={"version": rdflib.URIRef(version_url)}) for row in res: pn = row.part_number if not hasattr(dk_parts, pn): part = DigiKeyPart(pn) dk_parts[pn] = part else: part = dk_parts[pn] part.set_attribute(row.type, row.value) cli.info('%-30s %-50s %-50s %s' % (pn, row.type, row.value, row.attr_type)) cli.info("Footprint check:") res = cli.sparql(g, """ SELECT ?ref ?footprint ?part_number ?package_value ?case_value # * WHERE { ?version a kicad:project ; kicad:component ?cmp . ?cmp a kicad:component ; rdfs:label ?ref ; kicad:field ?dk_field . optional { ?cmp kicad:footprint ?footprint_url . ?footprint_url rdfs:label ?footprint . } . ?dk_field kicad:field-name "digikey" ; kicad:field-value ?part_number . ?part a dk:part ; dk:partNumber ?part_number . optional { ?part dk:attribute-value ?package_url . ?package_url rdfs:label ?package_value . ?package_type a dk:attributeType ; dk:value ?package_url . } . # optional { # ?part dk:attribute-value ?case_url . # ?case_url rdfs:label ?case_value . # ?case_type a dk:attributeType ; dk:value ?case_url . # } . # VALUES (?project_url) { (...) } . # VALUES (?package_type) { (dk-attr-type:pv16) } . # VALUES (?case_type) { (dk-attr-type:pv1291) } . } ORDER BY ?ref """, init_bindings={"version": rdflib.URIRef(version_url), "package_type": digikey_rdf.DIGIKEY_ATTRIBUTE_TYPE["pv16"], "cast_type": digikey_rdf.DIGIKEY_ATTRIBUTE_TYPE["pv1291"]}) for row in res: cli.info("%-5s %-50s %-50s %s %s" % (row.ref, row.part_number, row.footprint, row.package_value, row.case_value))