99 lines
4.2 KiB
Markdown
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
|