OpusBike/CLAUDE.md

99 lines
4.2 KiB
Markdown

# CLAUDE.md — OpusBike
> Project P-000014 · Company C-000001 (ProActys GmbH)
> Live: **https://monitor.proactys.swiss/opusbike/**
## What is this
PWA webapp that connects to a **Bosch Smart System eBike** via Web Bluetooth and displays live telemetry: **Speed, Torque, Ride Time, Total Kilometer, Mode** (OFF/ECO/TOUR/eMTB/TURBO).
## Architecture
```
/opt/opusbike/
├── webapp/ Static PWA (HTML/CSS/JS, no framework)
│ ├── index.html Single page — connect view + ride dashboard
│ ├── manifest.json PWA manifest (start_url: ".", scope: ".")
│ ├── css/style.css Brand-compliant styling
│ ├── js/
│ │ ├── app.js Main UI logic + Demo mode
│ │ ├── bleService.js Web Bluetooth connection to Bosch
│ │ ├── boschProtocol.js Bosch BLE protocol decoder (varint TLV)
│ │ ├── wsRelay.js WebSocket relay client (source/viewer)
│ │ ├── sw.js Service worker (cache-first)
│ │ └── qrcode.js Inline QR code generator
│ └── icons/ PWA icons (192, 512, apple-touch, favicon.svg)
├── server/
│ ├── relay.js Node.js WebSocket relay (ws library, port 3030)
│ └── package.json
├── Dockerfile nginx:alpine serving /usr/share/nginx/html on port 8080
├── Dockerfile.relay Node 20 alpine running relay.js on port 3030
├── docker-compose.yml Two services: nginx + relay, network: shared
└── nginx.conf Static file serving config
```
## How it works
### Three connection modes
1. **Direct BLE** — Chrome (desktop/Android) or **Bluefy** (iOS) connects directly to the Bosch Smart System via Web Bluetooth. Data is also forwarded to the WS relay for other viewers.
2. **WebSocket Relay** — Devices without Web Bluetooth (Safari, Firefox) auto-connect to the relay as viewers. They see the same live dashboard streamed from the BLE source.
3. **Demo Mode** — Simulates realistic riding data. Also broadcasts via WS relay so all connected devices see the demo.
### iOS / iPhone support
Safari does NOT support Web Bluetooth. The app detects iOS and shows a banner recommending **Bluefy** (free App Store app) which adds Web Bluetooth to iOS. URL: https://apps.apple.com/app/bluefy-web-ble-browser/id1492822055
Once Bluefy is installed, open `https://monitor.proactys.swiss/opusbike/` in Bluefy → tap "Connect via Bluetooth" → pair with the Bosch system → ride.
### Bosch BLE Protocol
- Service UUID: `0000fee7-0000-1000-8000-00805f9b34fb`
- Characteristic UUID: `00000011-0000-1000-8000-00805f9b34fb`
- Encoding: varint TLV (tag 0x01=speed/10, 0x02=torque, 0x03=totalKm/1000, 0x04=mode)
- Filter names: `smart system`, `Bosch`, `BRC`
### WebSocket relay protocol
- URL: `wss://monitor.proactys.swiss/opusbike/ws`
- Register: `{ type: "register", role: "source" | "viewer" }`
- Telemetry: `{ type: "telemetry", data: { speed, torque, totalKm, mode } }`
- Server broadcasts: `source_connected`, `source_disconnected` to viewers
## Caddy routing (in /home/ubuntu/monitoring/Caddyfile)
```
monitor.proactys.swiss {
handle /opusbike/ws → opusbike-relay:3030 (WebSocket)
handle_path /opusbike/* → opusbike-nginx:8080 (static, prefix stripped)
handle → gitea:3000 (Gitea at root)
}
```
## Deploy
```bash
cd /opt/opusbike
docker compose up -d --build # rebuild both containers
docker restart monitoring-proxy-1 # reload Caddy (bind mount inode issue)
```
**Important:** After editing the Caddyfile, you MUST `docker restart monitoring-proxy-1` (not just `caddy reload`) because the Edit tool creates a new file inode which breaks the bind mount.
## Brand
- Skill S-000007 (ProActys brand charter)
- Colors: Primary #4285F4, Dark #364052, Navy #051229, Ice #E1E8F0
- Font: Segoe UI, Arial, Helvetica, sans-serif
- Always: capital P capital A in "ProActys"
## TODO / Known issues
- [ ] Bosch BLE protocol needs real-device validation (UUIDs + TLV tags are estimated)
- [ ] Test Bluefy on real iPhone + real Bosch Smart System
- [ ] Add battery level if available in BLE data
- [ ] Add cadence (RPM) if available
- [ ] Consider adding ride history / local storage