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:
@@ -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.
|
||||
Reference in New Issue
Block a user