- Complete README rewrite covering all three feeds (KSUDP, Telemetry Tool, PCARS) - Document environment variables (GAME_HOST, LISTEN, BIND) - Add same-machine and remote setup examples - Document TUI layout, data capture format, architecture, testing - Bump version 0.3.0 → 0.4.1 |
||
|---|---|---|
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
rusty-telemetry
Multi-port UDP telemetry listener for sim racing games, with a terminal UI.
Receives real-time telemetry from Assetto Corsa and Project CARS 1 & 2 via UDP, parses binary packet formats, and displays live data in a terminal dashboard built with ratatui.
Supported Games
| Game | Feed | Port | Protocol | Data |
|---|---|---|---|---|
| Assetto Corsa | KSUDP (built-in) | 9996 | 3-phase handshake, binary RTCarInfo | Speed, RPM, gear, inputs, G-forces, lap times, per-wheel slip, suspension |
| Assetto Corsa | Telemetry Tool Plugin | 10101 | Binary per-driver structs | All of KSUDP + tyre core temps, driver names, ERS, DRS, all cars |
| Project CARS 1 | UDP Telemetry | 5606 | Binary V1 format (1367 bytes) | Speed, RPM, gear, inputs, engine temps, damage, weather, tyre wear |
| Project CARS 2 | UDP Telemetry | 5606 | Binary V2 format (559 bytes) | All of PCARS1 + full 3D position, turbo boost, tyre compounds |
All feeds are optional. If a feed fails to bind (e.g. the game isn't running), it shows as "not available" in the TUI and the other feeds continue normally.
Build and Run
cargo run --release
Press q or Ctrl+C to quit.
Configuration
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
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) | — |
Same Machine
No configuration needed — defaults work out of the box:
cargo run --release
Remote Setup (game on a different machine)
Run rusty-telemetry on a separate machine (e.g. 192.168.1.100) while the game runs on another (e.g. 192.168.1.2):
# On the analysis machine:
RUSTY_TELEMETRY_GAME_HOST=192.168.1.2 cargo run --release
Then point the games at the analysis machine:
- KSUDP: Works automatically — AC sends telemetry back to the handshake's source address
- Telemetry Tool: Set
to_ip = 192.168.1.100inconfig.ini - PCARS: Set target IP to
192.168.1.100in the in-game UDP settings
Feed Setup
KSUDP (AC built-in, port 9996)
No additional setup. AC's built-in Remote Telemetry UDP server listens on port 9996 at startup. rusty-telemetry performs a 3-phase handshake automatically:
- Sends
HANDSHAKEto AC's port 9996 - Receives 408-byte response (car name, driver name, track name in UTF-16LE)
- Sends
SUBSCRIBE_UPDATEto start continuous streaming at ~20 Hz
Important: Start AC before rusty-telemetry so AC can bind port 9996 first.
Telemetry Tool Plugin (AC, port 10101)
Optional third-party Python plugin by IkoRein. Provides richer data than KSUDP: tyre core temperatures, driver names, ERS, DRS, and data for all cars in the session.
- Download from RaceDepartment
- Extract to
<AC>/apps/python/Telemetry_Tool_plugin/ - Edit
config.ini:[telemetry_tool_plugin] to_ip = 127.0.0.1 to_port = 10101 - Enable in
python.ini:[TELEMETRY_TOOL_PLUGIN] ACTIVE=1 - Restart AC
Project CARS 1 & 2 (port 5606)
Configure in-game to send telemetry to your machine's IP on port 5606.
PCARS 2: Options → System → UDP Protocol → set target IP/port, format 2 recommended.
PCARS 1: Options → Visual → UDP Protocol → set target IP/port.
The parser auto-detects the format: PCARS 1 (1367-byte packets, 3-byte header) or PCARS 2 (559-byte car physics packets, 12-byte header).
TUI
The terminal UI shows one panel per active feed:
┌──────────────────────────────────────────────────────────┐
│ rusty-telemetry v0.4.0 -- Telemetry Listener │
├──────────────────────────────────────────────────────────┤
│ ╔ * Receiving ╗ │
│ ║ 20.0 Hz 1200 packets 15.2 KB/s last: 0.05s ║
│ ║ 245 km/h Gear:5 8750 RPM Lap:1:23.456 ║
│ ║ THR: 85% BRK: 0% Pos:0.453 ║
│ ╚→ :9996 recv :42132 [subscribed]╝ │
│ │
│ ╔ * Receiving ╗ │
│ ║ 60.0 Hz 3600 packets 45.8 KB/s last: 0.01s ║
│ ║ 180 km/h Gear:4 7200 RPM Lap:1:18.123 ║
│ ║ THR: 72% BRK: 0% Pos:0.500 ║
│ ╚ Telemetry Tool Port :10101 ╝ │
│ │
│ ╔ . Bound, waiting for data ╗ │
│ ║ 0.0 Hz 0 packets 0.0 KB/s last: never ║
│ ╚ PCARS Port :5606 ╝ │
├──────────────────────────────────────────────────────────┤
│ Session: ./data/20260604_103000/ Ctrl+C Quit │
└──────────────────────────────────────────────────────────┘
Each panel shows:
- Health indicator and status (
*green/alive,~yellow/stale,.gray/waiting,!red/error) - Packet frequency, total count, data rate, time since last packet
- Live telemetry: speed, gear, RPM, lap time, throttle/brake percentage, track position
- Connection mode (handshake with target/recv ports, or bind-listen)
Data Capture
All raw UDP packets are written to per-feed binary dump files:
./data/<YYYYMMDD_HHMMSS>/
├── feed_9996_ksudp.bin
├── feed_10101_telemetry_tool.bin
└── feed_5606_pcars.bin
Each packet is prefixed with a 4-byte big-endian length header, allowing sequential replay of captured sessions.
Testing
cargo test
32 unit tests covering:
- Binary parsers for all three feed formats (KSUDP, Telemetry Tool, PCARS V1/V2)
- Ring buffer frequency calculation and edge cases
- Feed health state machine transitions (Waiting → Alive → Stale → Alive)
- Packet validation, error handling, boundary conditions
Architecture
src/
├── main.rs Multi-port UDP listener, TUI event loop, KSUDP handshake
├── binary_utils.rs Shared safe binary read helpers (bounds-checked, zero fallback)
├── 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)
├── parser_telemetry_tool.rs AC Telemetry Tool binary parser (357-byte driver struct, 7 tests)
├── parser_pcars.rs PCARS 1 & 2 binary parser with auto-detection (5 tests)
└── ui.rs Ratatui TUI rendering
License
Private project — not yet licensed for distribution.