OpusBike/CLAUDE.md

4.2 KiB

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

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