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).
This commit is contained in:
wenil
2026-05-24 18:59:50 +03:00
commit d8cb0dc06d
28 changed files with 4172 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
# 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.