Printed parts, dxfs and subassemblies now listed alphabetically.

JSON BOM now simplified and in required order.
This commit is contained in:
Chris Palmer 2019-06-18 11:21:14 +01:00
parent 8d49f2b564
commit 774bdbe2cd
3 changed files with 117 additions and 117 deletions

View File

@ -1,64 +1,69 @@
{
"name": "main_assembly",
"count": 1,
"assemblies": [
{
"name": "mains_in_assembly",
"count": 1,
"assemblies": [
{
"name": "feet_assembly",
"count": 1,
"assemblies": [
{
"name": "base_assembly",
"count": 1,
"assemblies": [],
"vitamins": {
"insert(F1BM3): Heatfit insert M3": 2
},
"printed": {
"socket_box.stl": 1
},
"routed": {}
}
],
"vitamins": {
"washer(M3_washer): Washer M3 x 7mm x 0.5mm": 8,
"screw(M3_dome_screw, 10): Screw M3 dome x 10mm": 4,
"nut(M3_nut, nyloc = true): Nut M3 x 2.4mm nyloc": 4
},
"printed": {
"foot.stl": 4
},
"routed": {}
}
],
"vitamins": {
": Wire green & yellow 30/0.25mm strands, length 150mm - not shown": 1,
": Wire blue 30/0.25mm strands, length 150mm - not shown": 1,
": Wire brown 30/0.25mm strands, length 150mm - not shown": 2,
"tubing(HSHRNK32): Heatshrink sleeving ID 3.2mm x 15mm - not shown": 3,
"iec(IEC_inlet_atx): IEC inlet for ATX": 1,
"screw(M3_cs_cap_screw, 12): Screw M3 cs cap x 12mm": 2,
"washer(M3_washer): Washer M3 x 7mm x 0.5mm": 2,
"nut(M3_nut, nyloc = true): Nut M3 x 2.4mm nyloc": 2
},
"printed": {},
"routed": {}
}
],
"vitamins": {
": Wire green & yellow 30/0.25mm strands, length 150mm - not shown": 1,
": Wire blue 30/0.25mm strands, length 150mm - not shown": 1,
"tubing(HSHRNK32): Heatshrink sleeving ID 3.2mm x 15mm - not shown": 5,
": Ferrule for 1.5mm^2 wire - not shown": 3,
"mains_socket(Contactum): Mains socket 13A": 1,
"screw(M3_cs_cap_screw, 20): Screw M3 cs cap x 20mm": 2,
"jack_4mm_shielded(\"blue\", 3, \"royalblue\"): 4mm shielded jack socket blue": 2,
"jack_4mm_shielded(\"brown\", 3, \"sienna\"): 4mm shielded jack socket brown": 1,
"jack_4mm_shielded(\"green\", 3): 4mm shielded jack socket green": 2
[
{
"name": "base_assembly",
"count": 1,
"assemblies": {},
"vitamins": {
"insert(F1BM3): Heatfit insert M3": 2
},
"printed": {
"socket_box.stl": 1
},
"routed": {}
},
"printed": {},
"routed": {}
}
{
"name": "feet_assembly",
"count": 1,
"assemblies": {
"base_assembly": 1
},
"vitamins": {
"washer(M3_washer): Washer M3 x 7mm x 0.5mm": 8,
"screw(M3_dome_screw, 10): Screw M3 dome x 10mm": 4,
"nut(M3_nut, nyloc = true): Nut M3 x 2.4mm nyloc": 4
},
"printed": {
"foot.stl": 4
},
"routed": {}
},
{
"name": "mains_in_assembly",
"count": 1,
"assemblies": {
"feet_assembly": 1
},
"vitamins": {
": Wire green & yellow 30/0.25mm strands, length 150mm - not shown": 1,
": Wire blue 30/0.25mm strands, length 150mm - not shown": 1,
": Wire brown 30/0.25mm strands, length 150mm - not shown": 2,
"tubing(HSHRNK32): Heatshrink sleeving ID 3.2mm x 15mm - not shown": 3,
"iec(IEC_inlet_atx): IEC inlet for ATX": 1,
"screw(M3_cs_cap_screw, 12): Screw M3 cs cap x 12mm": 2,
"washer(M3_washer): Washer M3 x 7mm x 0.5mm": 2,
"nut(M3_nut, nyloc = true): Nut M3 x 2.4mm nyloc": 2
},
"printed": {},
"routed": {}
},
{
"name": "main_assembly",
"count": 1,
"assemblies": {
"mains_in_assembly": 1
},
"vitamins": {
": Wire green & yellow 30/0.25mm strands, length 150mm - not shown": 1,
": Wire blue 30/0.25mm strands, length 150mm - not shown": 1,
"tubing(HSHRNK32): Heatshrink sleeving ID 3.2mm x 15mm - not shown": 5,
": Ferrule for 1.5mm^2 wire - not shown": 3,
"mains_socket(Contactum): Mains socket 13A": 1,
"screw(M3_cs_cap_screw, 20): Screw M3 cs cap x 20mm": 2,
"jack_4mm_shielded(\"blue\", 3, \"royalblue\"): 4mm shielded jack socket blue": 2,
"jack_4mm_shielded(\"brown\", 3, \"sienna\"): 4mm shielded jack socket brown": 1,
"jack_4mm_shielded(\"green\", 3): 4mm shielded jack socket green": 2
},
"printed": {},
"routed": {}
}
]

View File

@ -54,21 +54,13 @@ class BOM:
self.routed = {}
self.assemblies = {}
def data(self, main, count = 1):
return {
"name" : self.name,
"count" : count,
"assemblies" : [main.assemblies[ass].data(main, self.assemblies[ass].count) for ass in self.assemblies],
"vitamins" : self.vitamins,
"printed" : self.printed,
"routed" : self.routed
}
def flat_data(self):
assemblies = {}
for ass in self.assemblies:
assemblies[ass] = self.assemblies[ass].count
return {
"name" : self.name,
"count" : self.count,
"assemblies" : assemblies,
"vitamins" : self.vitamins,
"printed" : self.printed,
@ -167,6 +159,7 @@ class BOM:
def parse_bom(file = "openscad.log", name = None):
main = BOM(name)
main.ordered_assemblies = []
stack = []
for line in open(file):
@ -179,6 +172,9 @@ def parse_bom(file = "openscad.log", name = None):
main.assemblies[stack[-1]].add_assembly(ass) #add to nested BOM
stack.append(ass)
main.add_assembly(ass) #add to flat BOM
if ass in main.ordered_assemblies:
main.ordered_assemblies.remove(ass)
main.ordered_assemblies.insert(0, ass)
else:
if s[0] == '}':
if s[1:] != stack[-1]:
@ -227,14 +223,15 @@ def boms(target = None, assembly = None):
if assembly == "main_assembly":
main.print_bom(True, open(bom_dir + "/bom.txt","wt"))
for ass in sorted(main.assemblies):
for ass in main.assemblies:
with open(bom_dir + "/" + ass + ".txt", "wt") as f:
bom = main.assemblies[ass]
print(bom.make_name(ass) + ":", file=f)
bom.print_bom(False, f)
data = [main.assemblies[ass].flat_data() for ass in main.ordered_assemblies]
with open(bom_dir + "/bom.json", 'w') as outfile:
json.dump(main.assemblies[assembly].data(main), outfile, indent = 4)
json.dump(data, outfile, indent = 4)
print("done")

View File

@ -35,45 +35,43 @@ import blurb
import bom
import shutil
from colorama import Fore
import copy
def is_assembly(s):
return s[-9:] == '_assembly' or s[-11:] == '_assemblies'
def add_assembly(flat_bom, bom, bounds_map):
for b in flat_bom:
if b["name"] == bom["name"]:
b["count"] += bom["count"]
return b
big = False
for ass in bom["assemblies"]:
b = add_assembly(flat_bom, ass, bounds_map)
if b["big"]:
big = True
if not big:
for stl in bom["printed"]:
bounds = bounds_map[stl]
width = bounds[1][0] - bounds[0][0]
depth = bounds[1][1] - bounds[0][1]
if max(width, depth) > 80:
big = True
break
bom["big"] = big or bom["routed"]
flat_bom.append(copy.deepcopy(bom))
return bom
def bom_to_assemblies(bom_dir, bounds_map):
global flat_bom
#
# Make a list of all the parts in the BOM
#
bom = {}
bom_file = bom_dir + "/bom.json"
with open(bom_file) as json_file:
bom = json.load(json_file)
flat_bom = []
add_assembly(flat_bom, bom, bounds_map)
flat_bom = json.load(json_file)
#
# Decide if we need big or small assembly pictures
#
for bom in flat_bom:
big = False
for ass in bom["assemblies"]:
for b in flat_bom:
if b["name"] == ass:
if not "big" in b:
print(ass, bom["name"])
if b["big"]:
big = True
break
if not big:
for stl in bom["printed"]:
bounds = bounds_map[stl]
width = bounds[1][0] - bounds[0][0]
depth = bounds[1][1] - bounds[0][1]
if max(width, depth) > 80:
big = True
break
bom["big"] = big or bom["routed"]
#
# Remove the main assembly if it is a shell
#
ass = flat_bom[-1]
if len(ass["assemblies"]) < 2 and not ass["vitamins"] and not ass["printed"] and not ass["routed"]:
flat_bom = flat_bom[:-1]
@ -278,49 +276,49 @@ def views(target, do_assemblies = None):
printed = ass["printed"]
if printed:
print('### 3D Printed parts', file = doc_file)
i = 0
for p in printed:
keys = sorted(list(printed.keys()))
for i in range(len(keys)):
p = keys[i]
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p], p), file = doc_file, end = '')
if (i % 3) == 2 or i == len(printed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('--|' * n), file = doc_file)
for j in range(n):
part = list(printed.keys())[i - n + j + 1]
part = keys[i - n + j + 1]
print('| ![%s](stls/%s) %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
i += 1
print('\n', file = doc_file)
routed = ass["routed"]
if routed:
print("### CNC Routed parts", file = doc_file)
i = 0
for r in routed:
keys = sorted(list(routed.keys()))
for i in range(len(keys)):
r = keys[i]
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r], r), file = doc_file, end = '')
if (i % 3) == 2 or i == len(routed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('--|' * n), file = doc_file)
for j in range(n):
part = list(routed.keys())[i - n + j + 1]
part = keys[i - n + j + 1]
print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
i += 1
print('\n', file = doc_file)
sub_assemblies = ass["assemblies"]
if sub_assemblies:
print("### Sub-assemblies", file = doc_file)
i = 0
for a in sub_assemblies:
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', a["count"], a["name"]), file = doc_file, end = '')
if (i % 3) == 2 or i == len(sub_assemblies) - 1:
keys = sorted(list(sub_assemblies.keys()))
for i in range(len(keys)):
a = keys[i]
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
if (i % 3) == 2 or i == len(keys) - 1:
n = (i % 3) + 1
print('\n|%s' % ('--|' * n), file = doc_file)
for j in range(n):
a = sub_assemblies[i - n + j + 1]["name"].replace('_assembly', '_assembled')
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
print('| ![%s](assemblies/%s) %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
i += 1
print('\n', file = doc_file)
small = not ass["big"]