From 774bdbe2cd745c363f7b84b17e39eaac29c8c0d1 Mon Sep 17 00:00:00 2001 From: Chris Palmer Date: Tue, 18 Jun 2019 11:21:14 +0100 Subject: [PATCH] Printed parts, dxfs and subassemblies now listed alphabetically. JSON BOM now simplified and in required order. --- examples/MainsBreakOutBox/bom/bom.json | 131 +++++++++++++------------ scripts/bom.py | 21 ++-- scripts/views.py | 82 ++++++++-------- 3 files changed, 117 insertions(+), 117 deletions(-) diff --git a/examples/MainsBreakOutBox/bom/bom.json b/examples/MainsBreakOutBox/bom/bom.json index 1e3c053..3416c32 100644 --- a/examples/MainsBreakOutBox/bom/bom.json +++ b/examples/MainsBreakOutBox/bom/bom.json @@ -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": {} -} \ No newline at end of file + { + "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": {} + } +] \ No newline at end of file diff --git a/scripts/bom.py b/scripts/bom.py index 97600ef..16ddaf7 100644 --- a/scripts/bom.py +++ b/scripts/bom.py @@ -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") diff --git a/scripts/views.py b/scripts/views.py index c4ab110..faeb7a4 100644 --- a/scripts/views.py +++ b/scripts/views.py @@ -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"]