feat: add PCARS 1 & 2 UDP telemetry parser (port 5606)

- Auto-detect PCARS1 (1367-byte V1) vs PCARS2 (559-byte V2) packet format
- Parse speed, RPM, gear, inputs, tyres, engine temps, damage, weather
- Map PCARS-specific fields to TelemetryFrame (oil/water temp, damage, etc.)
- Add FeedSource::Pcars + 16 PCARS-specific Option fields to TelemetryFrame
- Port 5606 as optional bind-listen feed (like Telemetry Tool)
- 5 new unit tests for PCARS parser (32 total)
- Shared binary_utils module for all parsers
This commit is contained in:
Jan-Peter von Hunnius 2026-06-04 09:49:00 +02:00
parent 7a1c37fc86
commit a50d3af290
4 changed files with 570 additions and 0 deletions

View file

@ -10,6 +10,7 @@ use std::fmt;
pub enum FeedSource {
Ksudp,
TelemetryTool,
Pcars,
}
/// Per-wheel index convention: FL=0, FR=1, RL=2, RR=3.
@ -106,6 +107,24 @@ pub struct TelemetryFrame {
pub last_sector_times: Option<[i32; 3]>,
pub driver_id: Option<u32>,
// ── PCARS-specific fields ──────────────────────────────────────
pub oil_temp_celsius: Option<i16>,
pub water_temp_celsius: Option<i16>,
pub fuel_capacity: Option<u8>,
pub boost_amount: Option<u8>,
pub crash_state: Option<u8>,
pub odometer_km: Option<f32>,
pub aero_damage: Option<u8>,
pub engine_damage: Option<u8>,
pub ambient_temperature: Option<i8>,
pub track_temperature: Option<i8>,
pub rain_density: Option<u8>,
pub track_length: Option<f32>,
pub full_position: Option<[f32; 3]>,
pub tyre_wear: Option<[u8; 4]>,
pub brake_temp_celsius: Option<[i16; 4]>,
pub suspension_damage: Option<[u8; 4]>,
// ── Meta ───────────────────────────────────────────────────────
pub source: FeedSource,
pub raw_size: usize,
@ -179,6 +198,22 @@ impl Default for TelemetryFrame {
sector_times: None,
last_sector_times: None,
driver_id: None,
oil_temp_celsius: None,
water_temp_celsius: None,
fuel_capacity: None,
boost_amount: None,
crash_state: None,
odometer_km: None,
aero_damage: None,
engine_damage: None,
ambient_temperature: None,
track_temperature: None,
rain_density: None,
track_length: None,
full_position: None,
tyre_wear: None,
brake_temp_celsius: None,
suspension_damage: None,
source: FeedSource::Ksudp,
raw_size: 0,
}
@ -213,6 +248,7 @@ impl fmt::Display for FeedSource {
match self {
FeedSource::Ksudp => write!(f, "KSUDP"),
FeedSource::TelemetryTool => write!(f, "Telemetry Tool"),
FeedSource::Pcars => write!(f, "PCARS"),
}
}
}