feat: add use-case session management, analysis algorithms, and REST API (v0.5.0)
- Add session layer with UseCaseSession, SessionRun, SessionManager for use-case driven telemetry analysis (shift points, track mapping) - Add analysis module with shift point detection (gear RPM ranges, upshift events, recommended shift RPM) and track map reconstruction (spline-aligned interpolation for center line from boundary runs) - Add 9 REST API endpoints for session CRUD, run management, and analysis triggers under /api/sessions/* - Add RecordingManager with always-on ring buffers (5 min, 18k frames) replacing raw binary file dumps - Wire SessionManager in main.rs with Arc<Mutex> shared state - Add TelemetryFrame Serialize derives for JSON API output - Fix stop_recording race: hold active lock across flush I/O - Fix flush: separate ring buffer lock from JSON serialization - Fix flush failure propagation: errors prevent Stopped status - Add data_truncated flag on SessionRun for ring buffer wrap detection - Deduplicate gear_display into shared free function - Deduplicate session_display into closure - Mutex poisoning recovery on all session API handlers
This commit is contained in:
parent
56d3169033
commit
47a0896134
10 changed files with 2333 additions and 91 deletions
79
README.md
79
README.md
|
|
@ -32,6 +32,7 @@ Press **q** or **Ctrl+C** to quit.
|
|||
| `RUSTY_TELEMETRY_GAME_HOST` | IP of the machine running the sim game (used for KSUDP handshake target) | `127.0.0.1` |
|
||||
| `RUSTY_TELEMETRY_LISTEN` | Local address to bind for incoming UDP feeds (Telemetry Tool, PCARS) | `0.0.0.0` |
|
||||
| `RUSTY_TELEMETRY_BIND` | Fallback for both of the above (backward compatibility) | — |
|
||||
| `RUSTY_TELEMETRY_API_PORT` | REST API server port | `8080` |
|
||||
|
||||
### Same Machine
|
||||
|
||||
|
|
@ -98,7 +99,7 @@ The terminal UI shows one panel per active feed:
|
|||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ rusty-telemetry v0.4.0 -- Telemetry Listener │
|
||||
│ rusty-telemetry v0.5.0 -- Telemetry Listener │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ ╔ * Receiving ╗ │
|
||||
│ ║ 20.0 Hz 1200 packets 15.2 KB/s last: 0.05s ║
|
||||
|
|
@ -116,7 +117,7 @@ The terminal UI shows one panel per active feed:
|
|||
│ ║ 0.0 Hz 0 packets 0.0 KB/s last: never ║
|
||||
│ ╚ PCARS Port :5606 ╝ │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ Session: ./data/20260604_103000/ Ctrl+C Quit │
|
||||
│ Recording: 550e8400-… Ctrl+C Quit │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
|
|
@ -128,16 +129,76 @@ Each panel shows:
|
|||
|
||||
## Data Capture
|
||||
|
||||
All raw UDP packets are written to per-feed binary dump files:
|
||||
A recording is auto-started on launch. All raw UDP packets are written to per-feed JSONL files under a UUID-based directory:
|
||||
|
||||
```
|
||||
./data/<YYYYMMDD_HHMMSS>/
|
||||
├── feed_9996_ksudp.bin
|
||||
├── feed_10101_telemetry_tool.bin
|
||||
└── feed_5606_pcars.bin
|
||||
./data/<uuid>/
|
||||
├── manifest.json
|
||||
├── feed_9996_ksudp.jsonl
|
||||
├── feed_10101_telemetry_tool.jsonl
|
||||
└── feed_5606_pcars.jsonl
|
||||
```
|
||||
|
||||
Each packet is prefixed with a 4-byte big-endian length header, allowing sequential replay of captured sessions.
|
||||
Each recording contains a `manifest.json` with metadata (game, track, car, use case, status, timestamps) and JSONL files for each feed. Each line in a JSONL file is a serialized `TelemetryFrame` object, enabling sequential replay and analysis of captured sessions.
|
||||
|
||||
## REST API
|
||||
|
||||
A built-in HTTP API server runs on port 8080 for recording management and live telemetry access.
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/api/live` | Live telemetry snapshot (all feeds) |
|
||||
| GET | `/api/recordings` | List all recordings |
|
||||
| POST | `/api/recordings` | Start new recording |
|
||||
| GET | `/api/recordings/{id}` | Get recording details |
|
||||
| POST | `/api/recordings/stop` | Stop active recording |
|
||||
| POST | `/api/recordings/{id}/stop` | Stop specific recording |
|
||||
| DELETE | `/api/recordings/{id}` | Delete recording |
|
||||
| GET | `/api/recordings/{id}/data/{feed_name}` | Download raw feed JSONL |
|
||||
| GET | `/api/use-cases` | List valid use cases |
|
||||
| GET | `/api/games` | List supported games |
|
||||
|
||||
### Start Recording Body
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Session",
|
||||
"game": "assetto_corsa",
|
||||
"track": "nurburgring",
|
||||
"car": "ferrari_488",
|
||||
"use_case": "general",
|
||||
"notes": "Testing session"
|
||||
}
|
||||
```
|
||||
|
||||
All fields are optional.
|
||||
|
||||
### Live Telemetry Response
|
||||
|
||||
```json
|
||||
{
|
||||
"feeds": [
|
||||
{
|
||||
"label": "KSUDP",
|
||||
"port": 9996,
|
||||
"health": "alive",
|
||||
"frequency_hz": 20.0,
|
||||
"total_packets": 1200,
|
||||
"data_rate_kb_s": 15.2,
|
||||
"speed_kmh": 245.0,
|
||||
"gear": "5",
|
||||
"engine_rpm": 8750.0,
|
||||
"throttle": 0.85,
|
||||
"brake": 0.0,
|
||||
"lap_time": "1:23.456",
|
||||
"spline_position": 0.453
|
||||
}
|
||||
],
|
||||
"active_recording": "550e8400-e29b-41d4-a716-446655440000"
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
|
|
@ -156,7 +217,9 @@ cargo test
|
|||
```
|
||||
src/
|
||||
├── main.rs Multi-port UDP listener, TUI event loop, KSUDP handshake
|
||||
├── api.rs REST API server (axum) for recording management and live telemetry
|
||||
├── binary_utils.rs Shared safe binary read helpers (bounds-checked, zero fallback)
|
||||
├── recording.rs Recording session manager (manifest, CRUD, auto-start)
|
||||
├── telemetry_frame.rs Unified telemetry data model (TelemetryFrame)
|
||||
├── feed_state.rs Per-feed health/frequency state machine with ring buffer
|
||||
├── parser_ksudp.rs AC KSUDP binary parser (RTCarInfo, 6 tests)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue