#!/usr/bin/env ruby # encoding: utf-8 # ruby: 3.0.0 =begin KiCAD can have a KiCad database library https://docs.kicad.org/master/en/eeschema/eeschema.html#database_libraries this script creates views from the partdb table so to create a database for KiCAD if wil also output the KiCad database library file =end require 'sqlite3' require 'json' # database file DB_PATH = "partdb.db" raise "DB file #{DB_PATH} does not exist" unless File.file? DB_PATH db = SQLite3::Database.new(DB_PATH) db.results_as_hash = true KICAD_FILE = "partdb.kicad_dbl" DEBUG = false # print debug information puts "= create part to properties views =" prop2view = [{property: "kicad_symbol"}, {property: "kicad_footprint"}, {property: "qeda_part"}, {property: "qeda_variant"}, {property: "JLCPCB_CORRECTION"}] prop2view.each do |prop| puts prop[:property] prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_") db.query("DROP VIEW IF EXISTS #{prop[:table]}") view = "CREATE VIEW #{prop[:table]} AS SELECT properties.part AS part, properties.value AS #{prop[:property]} FROM properties JOIN property ON property.id = properties.property WHERE property.name = '#{prop[:property]}'" puts view if DEBUG db.query(view) end puts "= create part to distribution views =" dist2view = [{property: "LCSC"}, {property: "JLCPCB"}, {property: "DigiKey"}] dist2view.each do |prop| puts prop[:property] prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_") db.query("DROP VIEW IF EXISTS #{prop[:table]}") view = "CREATE VIEW #{prop[:table]} AS SELECT distribution.part AS part, distribution.sku AS #{prop[:property]} FROM distribution JOIN distributor ON distributor.id = distribution.distributor WHERE distributor.name = '#{prop[:property]}'" puts view if DEBUG db.query(view) end puts "= create part category tables =" kicad_dbl = {} # kicad database library file kicad_dbl["meta"] = {version: 0} kicad_dbl["name"] = "CuVoodoo Database Library" kicad_dbl["description"] = "database of all my parts" # username/UID and password should be configured in DSN so we don't lead it when we share the resulting file kicad_dbl["source"] = {type: "odbc", dsn: "partdb", timeout_seconds: 3} kicad_dbl["libraries"] = [] categories = db.query("SELECT properties.value AS category FROM properties LEFT JOIN property ON property.id = properties.property WHERE property.name = 'category'").to_a.collect {|row| row['category']} categories.uniq! categories.each do |category| puts category table = "kicad_lib_" + category.downcase.gsub(/[- \/]/,"_") db.query("DROP VIEW IF EXISTS #{table}") view = "CREATE VIEW #{table} AS " view += "SELECT part.id, part.name, " view += "COALESCE(part.description,parent.description) AS description, " (prop2view + dist2view).each do |prop| view += "COALESCE(#{prop[:table]}1.#{prop[:property]},#{prop[:table]}2.#{prop[:property]}) AS #{prop[:property]}, " end view += "COALESCE(part.datasheet,parent.datasheet) AS datasheet FROM part " view += "LEFT JOIN part AS parent ON parent.id = part.family " (prop2view + dist2view).each do |prop| view += "LEFT JOIN #{prop[:table]} AS #{prop[:table]}1 ON #{prop[:table]}1.part = part.id " view += "LEFT JOIN #{prop[:table]} AS #{prop[:table]}2 ON #{prop[:table]}2.part = parent.id " end view += "WHERE part.id IN (SELECT part FROM properties LEFT JOIN property ON property.id = properties.property WHERE property.name = 'category' AND properties.value = '#{category}') " view += "OR parent.id IN (SELECT part FROM properties LEFT JOIN property ON property.id = properties.property WHERE property.name = 'category' AND properties.value = '#{category}')" puts view if DEBUG db.query(view) library = {name: category, table: table, key: "name", symbols: "kicad_symbol", footprints: "kicad_footprint"} library[:properties] = {description: "description"} library[:fields] = [] library[:fields] << {name: "Description", column: "description", visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true} library[:fields] << {name: "Datasheet", column: "datasheet", visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true} (prop2view + dist2view).each do |prop| next if prop[:property].start_with? "kicad_" library[:fields] << {name: prop[:property], column: prop[:property], visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true} end kicad_dbl["libraries"] << library end puts "writing KiCad database library file to #{KICAD_FILE}" File.open(KICAD_FILE, "w") do |file| file.write JSON.pretty_generate(kicad_dbl) end