Files
busbar-designer/README.md
T
wenil d8cb0dc06d Initial commit: Busbar Designer
Web tool for designing nickel/copper busbars over cylindrical-cell battery
packs (21700, 18650) in hex holders. Flask + build123d backend exports
STEP/DXF/SVG; vanilla JS frontend with live preview, multi-project SQLite
persistence, snapshot history.

Deploy scripts in deploy/ (proxmox-lxc.sh, install.sh, update.sh).
2026-05-24 18:59:50 +03:00

197 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Busbar Designer
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+**. On Windows / PowerShell:
```powershell
cd busbar-designer
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python app.py
```
Then open <http://localhost:5000> in your browser.
> 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
Three supported paths — pick one. Full docs in [`deploy/README.md`](deploy/README.md).
### Option A — Proxmox VE (one-liner from the PVE host)
```bash
bash -c "$(curl -fsSL https://gitea.local/me/busbar-designer/raw/branch/main/deploy/proxmox-lxc.sh)"
```
Creates a Debian 12 LXC and installs the service inside. Whiptail prompts for container ID, hostname, disk/CPU/RAM, network, repo URL, branch. Defaults to 4 GB disk, 2 cores, 1 GB RAM, dhcp.
### Option B — Inside an existing Debian/Ubuntu (LXC, VM, bare)
```bash
REPO_URL=https://gitea.local/me/busbar-designer.git \
bash -c "$(curl -fsSL https://gitea.local/me/busbar-designer/raw/branch/main/deploy/install.sh)"
```
Sets up the venv, installs deps, drops a systemd unit, starts the service. Update with `bash /opt/busbar-designer/deploy/update.sh`.
### Option C — Docker
```bash
git clone <repo> busbar-designer && cd busbar-designer
mkdir -p data
docker compose up -d --build
```
The `data/` folder is mounted into the container 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.