No description
Find a file
Jan-Peter v. Hunnius 56d3169033 fix: resolve 7 code review issues from v0.4.x
- Fix KSUDP clutch field reading fuel at offset 59 (KSUDP has no clutch input)
- Replace Notify with watch::channel for reliable shutdown (no missed wakeups)
- Deduplicate read_u16 from parser_pcars into shared binary_utils
- Remove dead Display impl for FeedSource
- Remove unused read_i8 helper from binary_utils
- Change Vec<Instant> to [Instant; 50] in FeedState (eliminate heap alloc)
- Cache rarely-changing strings by driver_id in Telemetry Tool parser
2026-06-04 11:12:55 +02:00
src fix: resolve 7 code review issues from v0.4.x 2026-06-04 11:12:55 +02:00
.gitignore feat: multi-port UDP listener with data dump 2026-06-03 11:50:06 +02:00
Cargo.lock docs: rewrite README.md, add remote operation docs, bump v0.4.1 2026-06-04 10:39:00 +02:00
Cargo.toml docs: rewrite README.md, add remote operation docs, bump v0.4.1 2026-06-04 10:39:00 +02:00
README.md docs: rewrite README.md, add remote operation docs, bump v0.4.1 2026-06-04 10:39:00 +02:00

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.100 in config.ini
  • PCARS: Set target IP to 192.168.1.100 in 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:

  1. Sends HANDSHAKE to AC's port 9996
  2. Receives 408-byte response (car name, driver name, track name in UTF-16LE)
  3. Sends SUBSCRIBE_UPDATE to 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.

  1. Download from RaceDepartment
  2. Extract to <AC>/apps/python/Telemetry_Tool_plugin/
  3. Edit config.ini:
    [telemetry_tool_plugin]
    to_ip = 127.0.0.1
    to_port = 10101
    
  4. Enable in python.ini: [TELEMETRY_TOOL_PLUGIN] ACTIVE=1
  5. 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.