FastAPI backend for the Hyperloop telemetry GUI. It exposes the REST API and WebSocket endpoints that browsers and Raspberry Pi hubs connect to.
- Hubs connect over
WS /huband authenticate with a per-hub device token. - Browsers log in with a NetID and the shared team password, then use JWT bearer tokens for REST and
WS /ws/client?token=...for live telemetry. - State is kept in memory (
src/storage/memory_store.py) and resets on restart.
cd cloud-services
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
uvicorn src.main:app --host 0.0.0.0 --port 8080 --reloadAPI docs: http://localhost:8080/docs
With the defaults in .env.example (development), log in as NetID dev with password hyperloop-dev,
and hubs can connect with dev-token-rpi-bridge-01 / dev-token-rpi-bridge-02. None of these
fallbacks work when ENVIRONMENT=production; the service refuses to start until real values are set.
POST /auth/login- NetID + team password (JSON or form). Returns a JWT with roleoperator. The NetID must be on the allowlist (ALLOWED_NETIDSand/orALLOWED_NETIDS_FILE). Failed attempts are rate limited per NetID and per client IP (HTTP 429 withRetry-After).POST /auth/login-viewer- No credentials. Returns a JWT with roleviewer(read-only).GET /auth/me- Current user (username,email,role).
Only operator tokens can send hub commands; viewers get HTTP 403. Removing a NetID from the allowlist
revokes that person's existing sessions.
Production setup, password rotation and hub token generation: .claude/auth-setup.md in the
hyperloop-gui repository.
GET /api/hubs- List every configured hub (fromDEVICE_TOKENS) withconnected,lastSeen,capabilitiesandprofile(offline hubs are included)GET /api/hubs/{hubId}- Hub detailsGET /api/hubs/{hubId}/telemetry- Recent telemetryGET /api/hubs/{hubId}/ports- Detected serial portsGET /api/hubs/{hubId}/connections- Open serial connectionsPOST /api/hubs/{hubId}/commands/write- Serial write (operator only)POST /api/hubs/{hubId}/commands/flash- Flash firmware (operator only)POST /api/hubs/{hubId}/commands/restart- Restart device (operator only)POST /api/hubs/{hubId}/commands/close- Close connection (operator only)
WS /hub(aliasWS /api/device/ws/uplink) - Hub connection (device token handshake)WS /ws/client?token=<jwt>- Browser telemetry stream (subscribe/unsubscribe by hub + port). Also carrieshealth,task_statusandhub_status(hub online/offline) to every client.
Hubs may add capabilities (for example flash:bin, device_snapshot) and a profile
({name, mode, uplink}) to their handshake. Hubs that send neither are treated as bench hubs that
accept .ino/.hex firmware, so older rpi-hub-server versions keep working.
Message and REST models are defined in src/protocol/bench_v1.py and src/models.py.
contracts/openapi.json is generated from them and consumed by the web client's type generation:
python -m src.protocol.exporttests/test_contracts.py fails when the committed file is out of date.
- Start this service (see Quick Start).
- In
rpi-hub-server/.env:HUB_ID=rpi-bridge-01 SERVER_ENDPOINT=ws://localhost:8080/hub DEVICE_TOKEN=dev-token-rpi-bridge-01
- Start the hub:
uvicorn src.main:app --host 127.0.0.1 --port 8000
pytest tests/ -v