docs: update README and AGENTS.md for session persistence, characteristics, track endpoints
- Document session persistence model (split metadata/frames files, lazy load) - Add characteristics API endpoints and response examples - Add track API endpoints to endpoint table - Fix use case name track_map → track_mapping - Update architecture with characteristics.rs and track_model.rs - Update test count to 33 - Rewrite AGENTS.md: accurate ports, persistence paths, tech stack
This commit is contained in:
parent
ed7dbcf1c9
commit
ba84fc0a6b
2 changed files with 111 additions and 7 deletions
54
AGENTS.md
Normal file
54
AGENTS.md
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# AGENTS.md — rusty-telemetry Project Context
|
||||||
|
|
||||||
|
## Mandatory Reference
|
||||||
|
|
||||||
|
**Before starting any work on this project, always read the Joplin note that contains the full project plan and architecture.**
|
||||||
|
|
||||||
|
- **Joplin Note ID**: `6c0dcb2a567348fd9796f50c790082e4`
|
||||||
|
- **Title**: "Sim Racing Telemetry Analysis Platform — Project Plan"
|
||||||
|
- **Tags**: sim-racing, lua, telemetry, rust, project-plan, assetto-corsa
|
||||||
|
|
||||||
|
Use the `joplin_get_note` tool with note ID `6c0dcb2a567348fd9796f50c790082e4` to retrieve the full project plan.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
`rusty-telemetry` is a Rust-based multi-port UDP telemetry listener and analysis platform for sim racing. It receives telemetry from Assetto Corsa (KSUDP + Telemetry Tool) and Project CARS 1 & 2, provides a terminal dashboard (ratatui), and exposes a REST API for session management, analysis, and car characteristics aggregation.
|
||||||
|
|
||||||
|
## Companion Repository
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|-------|-------|
|
||||||
|
| **Repo** | `racecraft` |
|
||||||
|
| **Path** | `~/WebstormProjects/racecraft` |
|
||||||
|
| **Language** | TypeScript (Vue 3) |
|
||||||
|
| **Purpose** | Web client — live telemetry, session UI, charts, track maps |
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- Rust (edition 2021)
|
||||||
|
- Tokio (async runtime)
|
||||||
|
- Axum 0.8 (REST API)
|
||||||
|
- Ratatui (terminal UI)
|
||||||
|
- Serde (JSON serialization)
|
||||||
|
|
||||||
|
## Key Ports
|
||||||
|
|
||||||
|
| Port | Feed Name | Source | Format |
|
||||||
|
|-------|-------------------|-------------------------------|---------|
|
||||||
|
| 9996 | ksudp | AC built-in engine | Binary (3-phase handshake, RTCarInfo) |
|
||||||
|
| 10101 | telemetry_tool | Telemetry Tool Python plugin | Binary (per-driver structs, ~60 Hz) |
|
||||||
|
| 5606 | pcars | Project CARS 1 & 2 | Binary (V1 1367B / V2 559B, auto-detected) |
|
||||||
|
| 8080 | REST API | Axum HTTP server | JSON |
|
||||||
|
|
||||||
|
## Data Persistence
|
||||||
|
|
||||||
|
- **Recordings**: `./data/<uuid>/` — manifest.json + per-feed JSONL files (written on shutdown)
|
||||||
|
- **Sessions**: `./data/sessions/<id>.json` (metadata + analysis) + `<id>.frames.json` (frames, lazy-loaded)
|
||||||
|
- **Track Models**: stored in session analysis results, served via `/api/tracks`
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run --release # Start server + TUI
|
||||||
|
cargo test # Run 33 unit tests
|
||||||
|
```
|
||||||
64
README.md
64
README.md
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Multi-port UDP telemetry listener and analysis platform for sim racing games.
|
Multi-port UDP telemetry listener and analysis platform for sim racing games.
|
||||||
|
|
||||||
Receives real-time telemetry from **Assetto Corsa** and **Project CARS 1 & 2** via UDP, parses binary packet formats, and provides live data via a terminal dashboard and REST API. Supports use-case driven analysis sessions for shift point optimization and track mapping.
|
Receives real-time telemetry from **Assetto Corsa** and **Project CARS 1 & 2** via UDP, parses binary packet formats, and provides live data via a terminal dashboard and REST API. Supports use-case driven analysis sessions for shift point optimization and track mapping, with persistent session storage and cross-session car characteristics aggregation.
|
||||||
|
|
||||||
## Supported Games
|
## Supported Games
|
||||||
|
|
||||||
|
|
@ -147,14 +147,22 @@ Each recording has a `manifest.json` with metadata (game, track, car, use case,
|
||||||
|
|
||||||
Use-case sessions allow targeted data capture and analysis:
|
Use-case sessions allow targeted data capture and analysis:
|
||||||
|
|
||||||
1. **Create a session** with a use case (`shift_points` or `track_map`)
|
1. **Create a session** with a use case (`shift_points` or `track_mapping`)
|
||||||
2. **Start runs** — each run captures frames from the ring buffer between start and stop
|
2. **Start runs** — each run captures frames from the ring buffer between start and stop
|
||||||
3. **Complete the session** — auto-analyzes captured data and stores results
|
3. **Complete the session** — auto-analyzes captured data and stores results
|
||||||
4. **Retrieve analysis** — shift point RPM ranges or track boundary coordinates
|
4. **Retrieve analysis** — shift point RPM ranges or track boundary coordinates
|
||||||
5. **Re-open if needed** — re-open a completed session to add more runs, then complete again
|
5. **Re-open if needed** — re-open a completed session to add more runs, then complete again
|
||||||
6. **Delete runs** — remove unwanted runs from a session (must be stopped first)
|
6. **Delete runs** — remove unwanted runs from a session (must be stopped first)
|
||||||
|
|
||||||
Sessions are in-memory and independent of persistent recordings.
|
Sessions are persistent: session metadata, runs, and analysis results survive a restart. On startup, all sessions are loaded from disk and incomplete runs are normalized to stopped state. Session data is stored separately from recordings:
|
||||||
|
|
||||||
|
```
|
||||||
|
./data/sessions/
|
||||||
|
├── <session_id>.json # Metadata (runs, analysis results, car_name)
|
||||||
|
└── <session_id>.frames.json # Telemetry frames (lazy-loaded on demand)
|
||||||
|
```
|
||||||
|
|
||||||
|
Session metadata is loaded at startup for fast listing; frame data is lazy-loaded only when analysis or frame extraction is requested. Writes are atomic (temp file + rename) and frame serialization is offloaded to a background thread to avoid blocking the API.
|
||||||
|
|
||||||
#### Feed Merging
|
#### Feed Merging
|
||||||
|
|
||||||
|
|
@ -206,6 +214,11 @@ A built-in HTTP API server runs on port 8080 for recording management and live t
|
||||||
| POST | `/api/sessions/{id}/complete` | Complete session + auto-analyze |
|
| POST | `/api/sessions/{id}/complete` | Complete session + auto-analyze |
|
||||||
| GET | `/api/sessions/{id}/analysis` | Get analysis results |
|
| GET | `/api/sessions/{id}/analysis` | Get analysis results |
|
||||||
| POST | `/api/sessions/{id}/analyze` | Re-run analysis on completed session |
|
| POST | `/api/sessions/{id}/analyze` | Re-run analysis on completed session |
|
||||||
|
| GET | `/api/characteristics/cars` | List all cars with aggregated shift-point data |
|
||||||
|
| GET | `/api/characteristics/cars/{car}` | Get detailed shift-point profile for a car |
|
||||||
|
| GET | `/api/tracks` | List all track models |
|
||||||
|
| GET | `/api/tracks/{track}` | Get a track model by key |
|
||||||
|
| POST | `/api/sessions/{id}/build-track-model` | Build a track model from a track mapping session |
|
||||||
|
|
||||||
### Start Recording Body
|
### Start Recording Body
|
||||||
|
|
||||||
|
|
@ -289,7 +302,7 @@ Returns the updated session on success.
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{ "id": "shift_points", "name": "ShiftPoints", "guidance": "1. Drive to a long straight..." },
|
{ "id": "shift_points", "name": "ShiftPoints", "guidance": "1. Drive to a long straight..." },
|
||||||
{ "id": "track_map", "name": "TrackMap", "guidance": "1. Drive a complete lap..." }
|
{ "id": "track_mapping", "name": "TrackMapping", "guidance": "1. Drive a complete lap..." }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -298,6 +311,41 @@ Each object contains:
|
||||||
- `name` — human-readable name
|
- `name` — human-readable name
|
||||||
- `guidance` — step-by-step instructions for the use case
|
- `guidance` — step-by-step instructions for the use case
|
||||||
|
|
||||||
|
### Car Characteristics
|
||||||
|
|
||||||
|
The characteristics endpoints aggregate shift-point analysis data across all completed `shift_points` sessions for each car. This provides a growing database of optimal shift RPMs per gear, useful for comparing setups and tracking improvements over time.
|
||||||
|
|
||||||
|
**`GET /api/characteristics/cars`** — returns a summary list:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"car_name": "Ferrari 488 GT3",
|
||||||
|
"session_count": 3,
|
||||||
|
"recommended_shift_rpm": 7500.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**`GET /api/characteristics/cars/{car}`** — returns detailed per-gear data:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"car_name": "Ferrari 488 GT3",
|
||||||
|
"gears": [
|
||||||
|
{
|
||||||
|
"gear": 2,
|
||||||
|
"min_rpm": 3200,
|
||||||
|
"max_rpm": 8500,
|
||||||
|
"min_speed_kmh": 45.0,
|
||||||
|
"max_speed_kmh": 120.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"recommended_shift_rpm": 7500.0,
|
||||||
|
"session_count": 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Shift Point Analysis Response
|
### Shift Point Analysis Response
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
@ -353,7 +401,7 @@ Then start the web client on the same machine — it proxies `/api/*` to `localh
|
||||||
cargo test
|
cargo test
|
||||||
```
|
```
|
||||||
|
|
||||||
32 unit tests covering:
|
33 unit tests covering:
|
||||||
- Binary parsers for all three feed formats (KSUDP, Telemetry Tool, PCARS V1/V2)
|
- Binary parsers for all three feed formats (KSUDP, Telemetry Tool, PCARS V1/V2)
|
||||||
- Ring buffer frequency calculation and edge cases
|
- Ring buffer frequency calculation and edge cases
|
||||||
- Feed health state machine transitions (Waiting → Alive → Stale → Alive)
|
- Feed health state machine transitions (Waiting → Alive → Stale → Alive)
|
||||||
|
|
@ -364,10 +412,12 @@ cargo test
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── main.rs Multi-port UDP listener, TUI event loop, KSUDP handshake
|
├── main.rs Multi-port UDP listener, TUI event loop, KSUDP handshake
|
||||||
├── api.rs REST API server (axum) — recordings, sessions, live telemetry
|
├── api.rs REST API server (axum) — recordings, sessions, tracks, characteristics, live telemetry
|
||||||
├── recording.rs Recording manager — ring buffers, manifest CRUD, flush to JSONL
|
├── recording.rs Recording manager — ring buffers, manifest CRUD, flush to JSONL
|
||||||
├── session.rs Session manager — use-case sessions, runs, frame extraction
|
├── session.rs Session manager — persistent sessions, runs, frame extraction, lazy-loading
|
||||||
├── analysis.rs Analysis algorithms — shift points, track mapping
|
├── analysis.rs Analysis algorithms — shift points, track mapping
|
||||||
|
├── characteristics.rs Car characteristics aggregation — cross-session shift-point profiles
|
||||||
|
├── track_model.rs Track model geometry — center line computation, boundary data
|
||||||
├── binary_utils.rs Shared safe binary read helpers (bounds-checked, zero fallback)
|
├── binary_utils.rs Shared safe binary read helpers (bounds-checked, zero fallback)
|
||||||
├── telemetry_frame.rs Unified telemetry data model (TelemetryFrame)
|
├── telemetry_frame.rs Unified telemetry data model (TelemetryFrame)
|
||||||
├── feed_state.rs Per-feed health/frequency state machine with ring buffer
|
├── feed_state.rs Per-feed health/frequency state machine with ring buffer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue