fix: F1 24 parser matches official EA SPORTS UDP spec with packet types
This commit is contained in:
@@ -8,6 +8,12 @@ def get_parser():
|
|||||||
|
|
||||||
|
|
||||||
class F124Parser:
|
class F124Parser:
|
||||||
|
"""F1 24 UDP telemetry parser based on official EA SPORTS specification."""
|
||||||
|
|
||||||
|
# Packet header (29 bytes)
|
||||||
|
HEADER_SIZE = 29
|
||||||
|
CAR_TELEMETRY_SIZE = 43 # sizeof(CarTelemetryData) with padding
|
||||||
|
|
||||||
def game_id(self) -> str:
|
def game_id(self) -> str:
|
||||||
return "f1_24"
|
return "f1_24"
|
||||||
|
|
||||||
@@ -15,22 +21,64 @@ class F124Parser:
|
|||||||
td = TelemetryData(game_id="f1_24", timestamp=time.time())
|
td = TelemetryData(game_id="f1_24", timestamp=time.time())
|
||||||
td.raw = {"raw_hex": data.hex(), "length": len(data), "addr": f"{addr[0]}:{addr[1]}"}
|
td.raw = {"raw_hex": data.hex(), "length": len(data), "addr": f"{addr[0]}:{addr[1]}"}
|
||||||
|
|
||||||
if len(data) < 1289:
|
if len(data) < 50:
|
||||||
return td
|
return td
|
||||||
|
|
||||||
try:
|
try:
|
||||||
td.speed_kmh = struct.unpack_from("<f", data, 37)[0]
|
# Parse header
|
||||||
td.speed_mph = td.speed_kmh * 0.621371
|
packet_id = struct.unpack_from("<B", data, 6)[0]
|
||||||
td.rpm = struct.unpack_from("<H", data, 41)[0]
|
player_idx = struct.unpack_from("<B", data, 27)[0]
|
||||||
td.max_rpm = struct.unpack_from("<H", data, 43)[0]
|
td.raw["packet_id"] = packet_id
|
||||||
td.gear = struct.unpack_from("<B", data, 46)[0] & 0x0F
|
td.raw["player_index"] = player_idx
|
||||||
td.throttle = struct.unpack_from("<f", data, 47)[0]
|
|
||||||
td.brake = struct.unpack_from("<f", data, 55)[0]
|
if packet_id == 6: # Car Telemetry Packet (ID=6)
|
||||||
td.steering = struct.unpack_from("<B", data, 45)[0] / 127.0
|
offset = self.HEADER_SIZE + player_idx * self.CAR_TELEMETRY_SIZE
|
||||||
td.lap_number = struct.unpack_from("<B", data, 262)[0]
|
|
||||||
td.lap_time = struct.unpack_from("<f", data, 63)[0]
|
td.speed_kmh = struct.unpack_from("<H", data, offset)[0]
|
||||||
td.best_lap = struct.unpack_from("<f", data, 268)[0]
|
td.speed_mph = td.speed_kmh * 0.621371
|
||||||
td.fuel = struct.unpack_from("<f", data, 51)[0]
|
|
||||||
|
td.throttle = struct.unpack_from("<f", data, offset + 4)[0]
|
||||||
|
td.steering = struct.unpack_from("<f", data, offset + 8)[0]
|
||||||
|
td.brake = struct.unpack_from("<f", data, offset + 12)[0]
|
||||||
|
td.clutch = struct.unpack_from("<B", data, offset + 16)[0] / 100.0
|
||||||
|
td.gear = struct.unpack_from("<b", data, offset + 17)[0]
|
||||||
|
td.rpm = struct.unpack_from("<H", data, offset + 18)[0]
|
||||||
|
td.raw["drs"] = struct.unpack_from("<B", data, offset + 20)[0]
|
||||||
|
td.raw["rev_lights_percent"] = struct.unpack_from("<B", data, offset + 21)[0]
|
||||||
|
td.raw["rev_lights_bit"] = struct.unpack_from("<H", data, offset + 22)[0]
|
||||||
|
|
||||||
|
for i in range(4):
|
||||||
|
td.raw[f"tyre_surface_temp_{i}"] = struct.unpack_from("<B", data, offset + 30 + i)[0]
|
||||||
|
td.raw[f"tyre_inner_temp_{i}"] = struct.unpack_from("<B", data, offset + 34 + i)[0]
|
||||||
|
|
||||||
|
td.raw["engine_temp"] = struct.unpack_from("<H", data, offset + 38)[0]
|
||||||
|
|
||||||
|
elif packet_id == 0: # Motion Packet (ID=0)
|
||||||
|
offset = self.HEADER_SIZE + player_idx * 64 # sizeof(CarMotionData)
|
||||||
|
|
||||||
|
td.acceleration_x = struct.unpack_from("<f", data, offset + 28)[0]
|
||||||
|
td.acceleration_y = struct.unpack_from("<f", data, offset + 32)[0]
|
||||||
|
td.acceleration_z = struct.unpack_from("<f", data, offset + 36)[0]
|
||||||
|
|
||||||
|
elif packet_id == 2: # Lap Data Packet (ID=2)
|
||||||
|
offset = self.HEADER_SIZE + player_idx * 24 # sizeof(LapData)
|
||||||
|
|
||||||
|
td.last_lap = struct.unpack_from("<f", data, offset)[0]
|
||||||
|
td.lap_time = struct.unpack_from("<f", data, offset + 4)[0]
|
||||||
|
td.best_lap = struct.unpack_from("<f", data, offset + 8)[0]
|
||||||
|
|
||||||
|
elif packet_id == 7: # Car Status Packet (ID=7)
|
||||||
|
offset = self.HEADER_SIZE + player_idx * 41 # sizeof(CarStatusData)
|
||||||
|
|
||||||
|
td.raw["traction_control"] = struct.unpack_from("<B", data, offset)[0]
|
||||||
|
td.raw["anti_lock_brakes"] = struct.unpack_from("<B", data, offset + 1)[0]
|
||||||
|
td.fuel = struct.unpack_from("<f", data, offset + 2)[0] / 110.0 # normalized to 0-1
|
||||||
|
if td.fuel > 1.0:
|
||||||
|
td.fuel = min(1.0, td.fuel / 100.0)
|
||||||
|
td.max_rpm = struct.unpack_from("<H", data, offset + 26)[0]
|
||||||
|
td.raw["ers_deploy_mode"] = struct.unpack_from("<B", data, offset + 34)[0]
|
||||||
|
td.raw["ers_store_energy"] = struct.unpack_from("<f", data, offset + 36)[0]
|
||||||
|
|
||||||
except struct.error:
|
except struct.error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user