#!/usr/bin/env python3 # Copyright (C) 2019 Gabriel Morell # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import decimal from boxes import Boxes, edges, boolarg class SBCMicroRack(Boxes): """Stackable rackable racks for SBC Pi-Style Computers""" webinterface = True ui_group = "Shelf" # see ./__init__.py for names def __init__(self): Boxes.__init__(self) self.addSettingsArgs(edges.FingerJointSettings) self.addSettingsArgs(edges.StackableSettings) self.buildArgParser(x=56, y=85) # count self.argparser.add_argument( "--sbcs", action="store", type=int, default=5, help="how many slots for sbcs", ) # spaces self.argparser.add_argument( "--clearance_x", action="store", type=int, default=3, help="clearance for the board in the box (x) in mm" ) self.argparser.add_argument( "--clearance_y", action="store", type=int, default=3, help="clearance for the board in the box (y) in mm" ) self.argparser.add_argument( "--clearance_z", action="store", type=int, default=28, help="SBC Clearance in mm", ) # mounting holes self.argparser.add_argument( "--hole_dist_edge", action="store", type=float, default=3.5, help="hole distance from edge in mm" ) self.argparser.add_argument( "--hole_grid_dimension_x", action="store", type=int, default=58, help="width of x hole area" ) self.argparser.add_argument( "--hole_grid_dimension_y", action="store", type=int, default=49, help="width of y hole area" ) self.argparser.add_argument( "--hole_diameter", action="store", type=float, default=2.75, help="hole diameters" ) # i/o holes self.argparser.add_argument( "--netusb_z", action="store", type=int, default=18, help="height of the net/usb hole mm" ) self.argparser.add_argument( "--netusb_x", action="store", type=int, default=53, help="width of the net/usb hole in mm" ) # features self.argparser.add_argument( "--stable", action='store', type=boolarg, default=False, help="draw some holes to put a 1/4\" dowel through at the base and top" ) self.argparser.add_argument( "--switch", action='store', type=boolarg, default=False, help="adds an additional vertical segment to hold the switch in place, works best w/ --stable" ) # TODO flesh this idea out better self.argparser.add_argument( "--fan", action='store', type=int, default=0, required=False, help="ensure that the x width is at least this much and as well, draw a snug holder for a fan someplace" ) def paint_mounting_holes(self): cy = self.clearance_y cx = self.clearance_x h2r = self.hole_diameter hde = self.hole_dist_edge hgdx = self.hole_grid_dimension_x hgdy = self.hole_grid_dimension_y self.hole( h2r + cx + hde / 2, h2r + cy + hde / 2, h2r / 2 ) self.hole( h2r + cx + hgdx + hde / 2, h2r + cy + hde / 2, h2r / 2 ) self.hole( h2r + cx + hde / 2, h2r + cy + hgdy + hde / 2, h2r / 2 ) self.hole( h2r + cx + hgdx + hde / 2, h2r + cy + hgdy + hde / 2, h2r / 2 ) def paint_stable_features(self): if self.stable: self.hole( 10,10,6.5 ) def paint_netusb_holes(self): t = self.thickness x = self.x w = x + self.hole_dist_edge * 2 height_per = self.clearance_z + t usb_height = self.netusb_z usb_width = self.netusb_x for i in range(self.sbcs): self.rectangularHole(w/2, (height_per)*i+15 , usb_width, usb_height, r=1) def paint_finger_holes(self): t = self.thickness height_per = self.clearance_z + t for i in range(self.sbcs + 1): self.fingerHolesAt((height_per) * i + +height_per/2 + 1.5, self.hole_dist_edge, self.x, 90) def render(self): # adjust to the variables you want in the local scope x, y = self.x, self.y t = self.thickness height_per = self.clearance_z + t height_total = self.sbcs * height_per # render your parts here self.rectangularWall(height_total + height_per/2, x + self.hole_dist_edge * 2, "eseS", callback=[ self.paint_finger_holes, self.paint_netusb_holes, ], move="right") self.rectangularWall(y + self.hole_dist_edge * 2, x + self.hole_dist_edge * 2, "efef", move="right") for i in range(self.sbcs): self.rectangularWall(y + self.hole_dist_edge * 2, x + self.hole_dist_edge * 2, "efef", callback=[ self.paint_mounting_holes ], move="up") self.rectangularWall(height_total + height_per/2, x + self.hole_dist_edge * 2, "eseS", callback=[ self.paint_finger_holes, self.paint_stable_features ], move="left") if self.switch: self.rectangularWall(height_total + height_per / 2, x + self.hole_dist_edge * 2, "eseS", callback=[self.paint_stable_features], move="down")