import struct #####FROZA_DATA_FORMAT = ' 1.0 means loss of grip. "TireSlipRatioFrontLeft": unpackedData[21], "TireSlipRatioFrontRight": unpackedData[22], "TireSlipRatioRearLeft": unpackedData[23], "TireSlipRatioRearRight": unpackedData[24], #// Wheels rotation speed radians/sec. "WheelRotationSpeedFrontLeft": unpackedData[25], "WheelRotationSpeedFrontRight": unpackedData[26], "WheelRotationSpeedRearLeft": unpackedData[27], "WheelRotationSpeedRearRight": unpackedData[28], #// = 1 when wheel is on rumble strip, = 0 when off. "WheelOnRumbleStripFrontLeft": unpackedData[29], "WheelOnRumbleStripFrontRight": unpackedData[30], "WheelOnRumbleStripRearLeft": unpackedData[31], "WheelOnRumbleStripRearRight": unpackedData[32], #// = from 0 to 1, where 1 is the deepest puddle "WheelInPuddleDepthFrontLeft": unpackedData[33], "WheelInPuddleDepthFrontRight": unpackedData[34], "WheelInPuddleDepthRearLeft": unpackedData[35], "WheelInPuddleDepthRearRight": unpackedData[35], #// Non-dimensional surface rumble values passed to controller force feedback "SurfaceRumbleFrontLeft": unpackedData[36], "SurfaceRumbleFrontRight": unpackedData[37], "SurfaceRumbleRearLeft": unpackedData[38], "SurfaceRumbleRearRight": unpackedData[39], #// Tire normalized slip angle, = 0 means 100% grip and |angle| > 1.0 means loss of grip. "TireSlipAngleFrontLeft": unpackedData[40], "TireSlipAngleFrontRight": unpackedData[41], "TireSlipAngleRearLeft": unpackedData[42], "TireSlipAngleRearRight": unpackedData[43], #// Tire normalized combined slip, = 0 means 100% grip and |slip| > 1.0 means loss of grip. "TireCombinedSlipFrontLeft": unpackedData[44], "TireCombinedSlipFrontRight": unpackedData[45], "TireCombinedSlipRearLeft": unpackedData[46], "TireCombinedSlipRearRight": unpackedData[47], #// Actual suspension travel in meters "SuspensionTravelMetersFrontLeft": unpackedData[48], "SuspensionTravelMetersFrontRight": unpackedData[49], "SuspensionTravelMetersRearLeft": unpackedData[50], "SuspensionTravelMetersRearRight": unpackedData[51], #// Unique ID of the car make/model "CarOrdinal": unpackedData[52], #// Between 0 (D -- worst cars) and 7 (X class -- best cars) inclusive "CarClass": unpackedData[53], #// Between 100 (worst car) and 999 (best car) inclusive "CarPerformanceIndex": unpackedData[54], #// 0 = FWD, 1 = RWD, 2 = AWD "DrivetrainType": unpackedData[55], #// Number of cylinders in the engine "NumCylinders": unpackedData[56], "PositionX": unpackedData[57], "PositionY": unpackedData[58], "PositionZ": unpackedData[59], "Speed": unpackedData[60], "Power": unpackedData[61], "Torque": unpackedData[62], "TireTempFrontLeft": unpackedData[63], "TireTempFrontRight": unpackedData[64], "TireTempRearLeft": unpackedData[65], "TireTempRearRight": unpackedData[66], "Boost": unpackedData[67], "Fuel": unpackedData[68], "DistanceTraveled": unpackedData[69], "BestLap": unpackedData[70], "LastLap": unpackedData[71], "CurrentLap": unpackedData[72], "CurrentRaceTime": unpackedData[73], "LapNumber": unpackedData[74], "RacePosition": unpackedData[75], "Accel": unpackedData[76], "Brake": unpackedData[77], "Clutch": unpackedData[78], "HandBrake": unpackedData[79], "Gear": unpackedData[80], "Steer": unpackedData[81], "NormalizedDrivingLine": unpackedData[82], "NormalizedAIBrakeDifference": unpackedData[83], "TireWearFrontLeft": unpackedData[84], "TireWearFrontRight": unpackedData[85], "TireWearRearLeft": unpackedData[86], "TireWearRearRight": unpackedData[87], #// ID for track "TrackOrdinal": unpackedData[88] } return carData data_types = {} with open('data_format.txt', 'r') as f: lines = f.read().split('\n') for line in lines: data_types[line.split()[1]] = line.split()[0] #assigning sizes in bytes to each variable type jumps={ 's32': 4, #Signed 32bit int, 4 bytes of size 'u32': 4, #Unsigned 32bit int 'f32': 4, #Floating point 32bit 'u16': 2, #Unsigned 16bit int 'u8': 1, #Unsigned 8bit int 's8': 1, #Signed 8bit int 'hzn': 12 #Unknown, 12 bytes of.. something } def get_data(data): return_dict={} #additional var passed_data = data for i in data_types: d_type = data_types[i]#checks data type (s32, u32 etc.) jump=jumps[d_type]#gets size of data current = passed_data[:jump]#gets data decoded = 0 #complicated decoding for each type of data if d_type == 's32': decoded = int.from_bytes(current, byteorder='little', signed = True) elif d_type == 'u32': decoded = int.from_bytes(current, byteorder='little', signed=False) elif d_type == 'f32': decoded = struct.unpack('f', current)[0] elif d_type == 'u16': decoded = struct.unpack('H', current)[0] elif d_type == 'u8': decoded = struct.unpack('B', current)[0] elif d_type == 's8': decoded = struct.unpack('b', current)[0] #adds decoded data to the dict return_dict[i] = decoded #removes already read bytes from the variable passed_data = passed_data[jump:] #returns the dict return return_dict