# Busbar Designer + Hex Holder Designer Web "combine" for cylindrical-cell battery pack production. Two pages: | Page | Purpose | |-------------|---------------------------------------------------------------------------| | `/holder` | Parametric **hex cell holder** designer — adjust pack size / cell type, see 3D, download STL for printing. | | `/` | **Busbar** designer — import cell coordinates, group into busbars (parallel + series), export STEP/DXF/SVG for laser cutting. | The holder page has a **Design busbars →** button that auto-creates a busbar project pre-loaded with the exact cell coordinates from the configured holder. --- Web tool for designing nickel/copper **busbars** over cylindrical-cell battery packs (21700, 18650, ...) built with hex-shaped cell holders. Workflow: 1. Import cell-center coordinates (paste from OpenSCAD console, CSV, JSON — or generate from `cell_dia / wall / rows / cols`). 2. View cells on a 2D canvas at real mm scale. 3. Click cells to select; group selected cells into named **busbars** (parallel groups), then chain busbars in series. 4. Each busbar is drawn as a strip of configurable width with circular pads + welding-window holes over each cell center. 5. Export busbar geometry to **STEP** (mandatory), plus **DXF** and **SVG** for laser/waterjet cutting. ## Quick start Requires **Python 3.10+** and **OpenSCAD** on the host (only needed for the `/holder` page; the busbar page works without it). ```powershell # Windows / PowerShell cd busbar-designer python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt python app.py ``` OpenSCAD install: Windows — `winget install OpenSCAD.OpenSCAD`; Linux — `apt install openscad`. Then open for the busbar designer, or for the hex holder designer. > First-time install pulls **build123d** (~ 200 MB; bundles OpenCASCADE via OCP) and may take several minutes. ### Linux / macOS ```bash cd busbar-designer python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python app.py ``` ## Geometry source of truth All cell-center math matches Addy's `Hex-Cell-Holder/hex_cell.scad`: | Variable | Formula | 21700 default | |-----------------|------------------------------------------|---------------| | `hex_w` | `cell_dia + 2*wall` | `22.8 mm` | | `hex_pt` | `hex_w / 2 / cos(30°)` | `13.164 mm` | | `opening_dia` | `cell_dia − 2*cell_top_overlap` | `15.2 mm` | | row pitch (Y) | `1.5 * hex_pt` | `19.746 mm` | | col pitch (X) | `hex_w` | `22.8 mm` | | `rect` row shift | `0` (even) / `0.5*hex_w` (odd) | `11.4 mm` | ## Import formats The importer auto-detects: - **OpenSCAD ECHO**: `ECHO: "Cell 1: x = 0.0, y = 0.0"` (paste straight from console). - If your `hex_cell.scad` doesn't print these, drop `scad_snippet.scad` (in this repo) at the bottom of the file. - **CSV**: `index,x,y` (header optional). - **JSON**: `[{"id":1,"x":0,"y":0}, ...]` or `[[x,y], ...]`. - **Generator** tab: enter `cell_dia / wall / rows / cols / pack_style` — coordinates are computed with the exact OpenSCAD formulas. ## Persistence State is stored in a SQLite file (`data/busbar.db` by default; override with `BUSBAR_DB` env var): | Table | What | |-------------|------------------------------------------------------------------------| | `projects` | Full editor state (cells + busbars + params) per project | | `presets` | Named param bundles you save from the params panel | | `snapshots` | Auto-history per project; max `SNAPSHOT_RETENTION` (default 20) kept | **REST API** (all JSON): | Method | Path | What | |--------|-----------------------------------------------|-------------------------------| | GET | `/api/projects` | list projects | | POST | `/api/projects` | create `{name, data}` | | GET | `/api/projects/{id}` | full project | | PUT | `/api/projects/{id}` | update `{name?, data?, snapshot?, note?}` | | DELETE | `/api/projects/{id}` | delete (cascades to snapshots) | | GET | `/api/projects/{id}/snapshots` | list snapshots | | GET | `/api/snapshots/{sid}` | full snapshot | | POST | `/api/snapshots/{sid}/restore` | roll project back | | GET | `/api/presets` | list presets | | POST | `/api/presets` | create `{name, params}` | | PUT | `/api/presets/{id}` | update | | DELETE | `/api/presets/{id}` | delete | **UI behaviour**: - Active project ID is in the URL: `?p=42`. Bookmark or open from another device → same state. - Auto-save fires 1.5 s after the last change. The first save in any 60 s window also creates a history snapshot. - "History" button shows the snapshot list with a Restore action. - Presets are saved server-side and apply to any project with one click. **Backup**: the entire DB is one file. Copy `data/busbar.db` (or the `data/` folder in Docker) for offline backup. ## Export | Format | Use | Backend | |--------|---------------------------------------------|--------------------------| | STEP | CAD (FreeCAD, Fusion, SolidWorks) | `build123d` → OpenCASCADE | | DXF | Laser cutter / CNC (2D) | `build123d` → ezdxf | | SVG | Quick preview, illustrator | `build123d` | STEP files are written as **flat 3D faces** (not solids) so a fab shop can lay them out before cutting. If you need a thick solid (e.g., 0.2 mm nickel) toggle "Extrude busbars" — the backend will extrude each strip to the configured thickness. ## Project layout ``` busbar-designer/ ├── app.py # Flask server: static files + /api/export/{step,dxf,svg} ├── busbar_export.py # build123d → STEP / DXF / SVG ├── requirements.txt ├── scad_snippet.scad # paste into hex_cell.scad to echo per-cell coordinates ├── CLAUDE.md # architecture notes for Claude / future contributors ├── tests/ │ └── test_export.py └── static/ ├── index.html ├── styles.css └── js/ ├── app.js ├── importer.js ├── viewport.js ├── groups.js ├── geometry.js └── exporter.js ``` ## Deploy to a home server ### Recommended: manual LXC + `install.sh` 1. **Create LXC in Proxmox web UI** — Debian 12 standard template, unprivileged, 4 cores / 8 GB RAM / 32 GB disk, network DHCP. Enable `Features → nesting=1`. 2. **Inside the LXC** (`pct enter ` from the host): ```bash REPO_URL=https://gitea.example.com/me/busbar-designer.git \ bash -c "$(curl -fsSL https://gitea.example.com/me/busbar-designer/raw/branch/main/deploy/install.sh)" ``` 3. Open `http://:5000` from any device on your LAN. Update after `git push` to your Gitea: ```bash pct exec -- bash /opt/busbar-designer/deploy/update.sh ``` See [`deploy/README.md`](deploy/README.md) for backup/restore, troubleshooting, and what `install.sh` actually installs. ### Alternative: Docker ```bash git clone busbar-designer && cd busbar-designer mkdir -p data docker compose up -d --build ``` `data/` is bind-mounted at `/app/data` so the SQLite DB survives `docker compose down`. ### Reverse proxy (optional) If you want it behind your existing nginx / Caddy / Traefik: ```nginx location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_read_timeout 120s; # STEP export can take a few seconds client_max_body_size 5m; } ``` For Caddy: ``` busbar.example.com { reverse_proxy 127.0.0.1:5000 } ``` ### Security The app has no authentication. Either: - expose only on your LAN (default), or - put it behind an authenticating reverse proxy (Caddy `basic_auth`, Authelia, Pocket-ID, etc.). ## Troubleshooting - **`pip install build123d` fails on Windows / Python 3.13** — the prebuilt OCP wheels lag the latest Python release. If your `python --version` is 3.13, install Python 3.12 from python.org and use it for the venv: `py -3.12 -m venv .venv`. - **STEP opens empty in FreeCAD** — make sure at least one busbar exists and contains ≥ 1 cell. The exporter writes only assigned busbars. - **Port 5000 in use** — set `PORT=5050 python app.py`. ## License MIT.