Jump to content
Want to report an issue? Have a bug to report? Please look here first!!!! Read more... ×

F1 2019 UDP Specification

Recommended Posts

35 minutes ago, RichardWh said:

If Packets can contain multiple types, then what is the point in the packet identifier?

I used to check on the byte size, but now Lap Data and Car Setup are both 843.
I can't check on the packet id, as packet id 6 is very often a different type.

Am I missing something here?

Maybe i am missing your point, but your aproach about the packet size couldn't have worked last year as well, since Lap Data and Car Setups had the same size last year as well.
I am checking the packets, by taking the first few bytes, the first 21 to be precise, and convert them to the PacketHeader struct. this way, i can use the m_packetId to check, which packet i am receiving. 

and why can't you check packet id 6? car telemetry is always the same structure

 

edit: by the way, is there a way to set the sorting in topics to "sort by date" to default?

Edited by Bannish

Share this post


Link to post
Share on other sites
2 hours ago, Bannish said:

Maybe i am missing your point, but your aproach about the packet size couldn't have worked last year as well, since Lap Data and Car Setups had the same size last year as well.
I am checking the packets, by taking the first few bytes, the first 21 to be precise, and convert them to the PacketHeader struct. this way, i can use the m_packetId to check, which packet i am receiving. 

and why can't you check packet id 6? car telemetry is always the same structure

 

edit: by the way, is there a way to set the sorting in topics to "sort by date" to default?

Turns out, the reason why it was always coming out as 6 is because I'd forgotten to add game Major and minor version in the header, so it was messing that up!

Edited by RichardWh

Share this post


Link to post
Share on other sites

Hello Guys, I just tried to catch the Event Packets and it seems, i did a good job with that. every event is recognized, but i have a problem with the "fastest lap" event. I am writing my program in c#.

for the lap time, i am using the TimeSpan datatype and this is how i try to debug the info right now (using log4net)

case "ftlp":
	log.Info("Fastest Lap");
	log.Info(evnt.m_eventDetails.ftlp.vehicleIdx);
	TimeSpan laptime = TimeSpan.FromSeconds((double)evnt.m_eventDetails.ftlp.lapTime);
	log.Info(evnt.m_eventDetails.ftlp.lapTime);
	log.Info(laptime.ToString("mm':'ss'.'fff"));
	break;
<...>

This is the log output i am getting from this:
 

00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - Fastest Lap - method SelectEventType - line 158
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 17 - method SelectEventType - line 159
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 9,24857E-44 - method SelectEventType - line 161
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 00:00:00 - method SelectEventType - line 162

Even when i try to leave the formatting in the ToString method empty, i am still getting the 00:00:00 reading. I have a feeling, that I am missing something very obvious.

Share this post


Link to post
Share on other sites

So for a league we want to use an overlay standings thing while spectating, so we can get the penalties on there. (or, you know, please add it to the game already 🧐
Just the thing of the left. 

Now this would have worked perfectly in the last game but in a continuing effort to make it impossible for us to spectate league races effectively, we've now been denied multiplayer names in the telemetry. While there is of course no reason for that cause we get all those names anyway by just looking at the game, it is very unfortunate cause it would make the overlay rather useless. 

Now my question is, apart from the obvious please make those overlays obsolete and add penalties (and tire wear/wing damage) to the spectate menu, 

Is there a way to edit the telemetry send by the game so we can, in advance, for league races (where we know in advance who is gonna participate) enter the names that the telemetry is gonna export?
That way the streamers can use that and not be handicapped and reliant on the race engineers (who now use the telemetry without names btw because **** us right?) to give them frequent penalty updates during the race. 
 

F1_2019_TT_Austria_Race_2_20190725.png

Share this post


Link to post
Share on other sites
19 hours ago, Bannish said:

Hello Guys, I just tried to catch the Event Packets and it seems, i did a good job with that. every event is recognized, but i have a problem with the "fastest lap" event. I am writing my program in c#.

for the lap time, i am using the TimeSpan datatype and this is how i try to debug the info right now (using log4net)


case "ftlp":
	log.Info("Fastest Lap");
	log.Info(evnt.m_eventDetails.ftlp.vehicleIdx);
	TimeSpan laptime = TimeSpan.FromSeconds((double)evnt.m_eventDetails.ftlp.lapTime);
	log.Info(evnt.m_eventDetails.ftlp.lapTime);
	log.Info(laptime.ToString("mm':'ss'.'fff"));
	break;
<...>

This is the log output i am getting from this:
 


00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - Fastest Lap - method SelectEventType - line 158
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 17 - method SelectEventType - line 159
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 9,24857E-44 - method SelectEventType - line 161
00:01:14,891 [F1Telemetry.DataCollector] [9] INFO - 00:00:00 - method SelectEventType - line 162

Even when i try to leave the formatting in the ToString method empty, i am still getting the 00:00:00 reading. I have a feeling, that I am missing something very obvious.

Hey @Bannish, it's been a while since I wrote my last line of C#, but looking at your code, is it normal that you cast the fastes lap time into a double (line 160)? As far as I remember, a float is 32 bits in size whereas double is 64 bits. From the UDP specs in this topic, it looks like the lap time is expressed in 32 bits-precision, so float would be the way to go here?

Share this post


Link to post
Share on other sites
1 hour ago, Poulpus said:

Hey @Bannish, it's been a while since I wrote my last line of C#, but looking at your code, is it normal that you cast the fastes lap time into a double (line 160)? As far as I remember, a float is 32 bits in size whereas double is 64 bits. From the UDP specs in this topic, it looks like the lap time is expressed in 32 bits-precision, so float would be the way to go here?

Yeah @Poulpus is exactly right @Bannish.

In C#, I've used the following conversions from the feed:

float=float
uint16=ushort
uint8=byte
int8=sbyte
uint64=ulong
int16=short

Edited by RichardWh

Share this post


Link to post
Share on other sites
2 hours ago, Poulpus said:

Hey @Bannish, it's been a while since I wrote my last line of C#, but looking at your code, is it normal that you cast the fastes lap time into a double (line 160)? As far as I remember, a float is 32 bits in size whereas double is 64 bits. From the UDP specs in this topic, it looks like the lap time is expressed in 32 bits-precision, so float would be the way to go here?

 

40 minutes ago, RichardWh said:

Yeah @Poulpus is exactly right @Bannish.

In C#, I've used the following conversions from the feed:

float=float
uint16=ushort
uint8=byte
int8=sbyte
uint64=ulong
int16=short

you guys are both right in that, that a float would be enough. i just saw, that i did forget to remove that cast, but when i last checked, that cast did not make a difference.

case "ftlp":
	log.Info("Fastest Lap");
    log.Info(evnt.m_eventDetails.ftlp.vehicleIdx);
    TimeSpan laptime = TimeSpan.FromSeconds(evnt.m_eventDetails.ftlp.lapTime);
    log.Info(evnt.m_eventDetails.ftlp.lapTime);
    log.Info(laptime.ToString("mm':'ss'.'fff"));

these are the outputs without the cast to doulbe (first and second round on paul ricard, one round withflashback, the second without)

22:17:01,649 [F1Telemetry.DataCollector] [4] INFO - System.Byte[] - method SelectPacket - line 128
22:17:01,649 [F1Telemetry.DataCollector] [4] INFO - Fastest Lap - method SelectEventType - line 158
22:17:01,650 [F1Telemetry.DataCollector] [4] INFO - 19 - method SelectEventType - line 159
22:17:01,669 [F1Telemetry.DataCollector] [4] INFO - 9,24857E-44 - method SelectEventType - line 161
22:17:01,677 [F1Telemetry.DataCollector] [4] INFO - 00:00.000 - method SelectEventType - line 162
22:18:55,861 [F1Telemetry.DataCollector] [5] INFO - System.Byte[] - method SelectPacket - line 128
22:18:55,862 [F1Telemetry.DataCollector] [5] INFO - Fastest Lap - method SelectEventType - line 158
22:18:55,863 [F1Telemetry.DataCollector] [5] INFO - 19 - method SelectEventType - line 159
22:18:55,864 [F1Telemetry.DataCollector] [5] INFO - 9,24857E-44 - method SelectEventType - line 161
22:18:55,868 [F1Telemetry.DataCollector] [5] INFO - 00:00.000 - method SelectEventType - line 162

I would like to note the "9,24857E-44" unformated output. i think, that this number is a bit small, don't you think too? i have a feeling, that i made a mistake in there. this is the code of my EventDataPacket

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct PacketEventData
    {
        public PacketHeader m_header;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] m_eventStringCode;
        public EventDataDetails m_eventDetails;
    }

    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct EventDataDetails
    {
        [FieldOffset(0)]
        public FastestLap ftlp;

        [FieldOffset(0)]
        public Retirement rtmt;

        [FieldOffset(0)]
        public TeamMateInPits tmpt;

        [FieldOffset(0)]
        public RaceWinner rcwn;
    }

    public struct FastestLap
    {
        public byte vehicleIdx; // Vehicle index of car achieving fastest lap
        public float lapTime;    // Lap time is in seconds
    }

    public struct Retirement
    {
        public byte vehicleIdx; // Vehicle index of car retiring
    }

    public struct TeamMateInPits
    {
        public byte vehicleIdx; // Vehicle index of team mate
    } 

    public struct RaceWinner
    {
        public byte vehicleIdx; // Vehicle index of the race winner
    }

sorry for the long post guys. but i hope, that you can make some sense out of this

Share this post


Link to post
Share on other sites
39 minutes ago, Bannish said:

sorry for the long post guys. but i hope, that you can make some sense out of this

OK, it goes beyond my remaining knowledge of C# 🙂

Maybe just one suggestion: you are using struct annotations for PacketEventData and EventDataDetails, but not for the FastestLap struct. Could it be that the compiler arranges things on its own without any instructions, and messes it up? Maybe you could try to add StructLayout annotations to the FastestLap struct and see if it changes anything?

Otherwise I would also advise to debug-print bit-by-bit what you receive in UDP and make sure you did not shift an index or two and read the wrong data at the wrong place (I had that kind of problems in Swift, and it can happen pretty quickly when you do things too fast...).

  • Thanks 1

Share this post


Link to post
Share on other sites
10 minutes ago, Poulpus said:

OK, it goes beyond my remaining knowledge of C# 🙂

Maybe just one suggestion: you are using struct annotations for PacketEventData and EventDataDetails, but not for the FastestLap struct. Could it be that the compiler arranges things on its own without any instructions, and messes it up? Maybe you could try to add StructLayout annotations to the FastestLap struct and see if it changes anything?

Otherwise I would also advise to debug-print bit-by-bit what you receive in UDP and make sure you did not shift an index or two and read the wrong data at the wrong place (I had that kind of problems in Swift, and it can happen pretty quickly when you do things too fast...).

you are my hero: i hadn't noticed, that i forgot to add the sequential StructLayout to those structs. after adding them, these are my outputs for the first lap on paul ricard on rain

23:18:10,974 [F1Telemetry.DataCollector] [15] INFO - 121,696 - method SelectEventType - line 161
23:18:10,975 [F1Telemetry.DataCollector] [15] INFO - 02:01.696 - method SelectEventType - line 162

thank you again, it works like a charm now. sometimes i am so blind when i work with my own code 😂

  • Like 1

Share this post


Link to post
Share on other sites
45 minutes ago, Bannish said:

you are my hero

Glad I could help 🤓

Keep us updated of what you do with your app 🙂

Share this post


Link to post
Share on other sites

I have build an app using C# and I am trying to store results once a multiplayer race is completed. The only reasonable way I can think of is to capture the EventStringCode 'SEND' which should be received when the race is over. Saying this, it seems that I am having issues receiving EventPackets and I am not sure what I am doing wrong. 

To explain better I have created the PacketEventData struct as follows:

/* Sent when an event occurs */
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct PacketEventData
        {
            [MarshalAs(UnmanagedType.Struct)]
            public PacketHeader m_header;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] m_eventStringCode;
            EventDataDetails m_eventDetails;
        }

Some events are actually received but this does not apply for all. For example: SSTA is received for all races, same applies for DRSE. BUT, the FTLP is not always received. In a whole race where there are numerous changes in the fastest lap I am only receiving this event once! Furthermore I do not receive any of the other events like team mate in pits, chequered flag or session ended.

Any ideas on what could be causing such issues? I do not have any other issues with other packets.

Share this post


Link to post
Share on other sites

Can someone please make a quick sum up of the main differences between F1 2018/2019 UDP packets?

As i can see there should be a change in some fields (car tyre compounds, exhaust damage, yourTelemetry) and in the maximum size of the packet (from 1341 to 1347 if i'm not wrong). Something else big to add something usefull?

Did i forgot some field who has changed since last year structure?

Share this post


Link to post
Share on other sites
On 6/20/2019 at 5:29 PM, Faya said:

m_totalLaps

 

Con someone please explain me how this field works?

Reading this field as stated just wreaks the sequence, wrecking out all next read data.

I made a try with a field size of 4bytes (float) and this ust made all next data came out corrrectly, but still have a wrong read value in this field.

 

I noticed also that the session packet is reported with a size of size: 149 bytes , but looking at the documentation you provided i find it out of 146 bytes.

 

Can someone tell me what is wrong in the struct or in my tests? Thank you.. :classic_blink:

Edited by Lopensky

Share this post


Link to post
Share on other sites
28 minutes ago, Lopensky said:

 

Con someone please explain me how this field works?

Reading this field as stated just wreaks the sequence, wrecking out all next read data.

I made a try with a field size of 4bytes (float) and this ust made all next data came out corrrectly, but still have a wrong read value in this field.

 

I noticed also that the session packet is reported with a size of size: 149 bytes , but looking at the documentation you provided i find it out of 146 bytes.

 

Can someone tell me what is wrong in the struct or in my tests? Thank you.. :classic_blink:

So, m_totalLaps is a 1 byte whole number. in C# it would correspond to the "byte" data type. notice, that it's an unsigned type 😉 

about your packet size, you must have an calculation error somewhere.

the MarshalZone struct has a size of 5, and the array has a size of 21, so you have 105 bytes there alone. the rest of the session struct, i counted 44 bytes, so with my math, the 149 bytes are correct 😉 maybe you forgot to add the additional bytes of the header struct 😉

 

Edit, just for clarification

 

struct MarshalZone // 5 bytes in total
{
    float  m_zoneStart;   // 4 bytes
    int8   m_zoneFlag;    // 1 byte
};

struct PacketSessionData
{
    PacketHeader    m_header;               	// 23 bytes

    uint8           m_weather;              	// 1 byte - 24 total
    int8	    m_trackTemperature;    	// 1 byte - 25 total
    int8	    m_airTemperature;      	// 1 byte - 26 total
    uint8           m_totalLaps;           	// 1 byte - 27 total
    uint16          m_trackLength;           	// 2 bytes - 29 total
    uint8           m_sessionType;         	// 1 byte - 30 total
    int8            m_trackId;         		// 1 byte - 31 total
    uint8           m_formula;                  // 1 byte - 32 total
    uint16          m_sessionTimeLeft;    	// 2 bytes - 34 total
    uint16          m_sessionDuration;     	// 2 bytes - 36 total
    uint8           m_pitSpeedLimit;      	// 1 byte - 37 total
    uint8           m_gamePaused;               // 1 byte - 38 total
    uint8           m_isSpectating;        	// 1 byte - 39 total
    uint8           m_spectatorCarIndex;  	// 1 byte - 40 total
    uint8           m_sliProNativeSupport;	// 1 byte - 41 total
    uint8           m_numMarshalZones;         	// 1 byte - 42 total
    MarshalZone     m_marshalZones[21];         // 5 bytes * 21 = 105 bytes - 147 total
    uint8           m_safetyCarStatus;          // 1 byte - 148 total
    uint8           m_networkGame;              // 1 byte - 149 total
Edited by Bannish
some clarification

Share this post


Link to post
Share on other sites
3 minutes ago, Bannish said:

So, m_totalLaps is a 1 byte whole number. in C# it would correspond to the "byte" data type. notice, that it's an unsigned type 😉 

Really sorry man, i was taling about the trackLength field, but copied the wrong one. Is this a  2 bytes data? Cause i have some problems reading the data.

 

About the calculation i have this:

20 bytes Header +

21 bytes (other data in Session Packet) +

21 * 5 = 105 bytes (marshal zones)

= 146 bytes

 

I'm quite sure thre is something i'm missing.. but can't sort it out.

 

Share this post


Link to post
Share on other sites
15 minutes ago, Lopensky said:

Really sorry man, i was taling about the trackLength field, but copied the wrong one. Is this a  2 bytes data? Cause i have some problems reading the data.

About the calculation i have this:

20 bytes Header +

21 bytes (other data in Session Packet) +

21 * 5 = 105 bytes (marshal zones)

= 146 bytes

 

I'm quite sure thre is something i'm missing.. but can't sort it out.

 

trackLengh is in fact a 2 byte data. your problem is your Header size. The Header struct has 23 bytes in total.

 

struct PacketHeader
{
    uint16    m_packetFormat;         // 2 bytes
    uint8     m_gameMajorVersion;     // 1 byte
    uint8     m_gameMinorVersion;     // 1 byte
    uint8     m_packetVersion;        // 1 byte
    uint8     m_packetId;             // 1 byte
    uint64    m_sessionUID;           // 8 bytes
    float     m_sessionTime;          // 4 bytes
    uint      m_frameIdentifier;      // 4 bytes (a normal int or uint are always 32 bits 😉 )
    uint8     m_playerCarIndex;       // 1 byte
}; // Total 23 bytes

Adding these 3 bytes to the size you calculated, we have 149 bytes in total for the package 😉 

Edited by Bannish

Share this post


Link to post
Share on other sites

EDIT

 

Sooooo THAT is the problem.

 uint 

is 4 byte and not 1.... THANK YOU. I'll try this right now! :classic_biggrin:

Edited by Lopensky

Share this post


Link to post
Share on other sites
2 minutes ago, Lopensky said:

So maybe the problem is here since i count just 20 bytes for the header.

my guess would be, that you counted uint m_frameIdentifier as 1 byte, but it is in fact 4 bytes 😉 

Share this post


Link to post
Share on other sites

Yup, now it finally works! Thank you for the help, you saved me really a lot of time!  ❤️❤️❤️❤️

Share this post


Link to post
Share on other sites
17 minutes ago, Lopensky said:

Yup, now it finally works! Thank you for the help, you saved me really a lot of time!  ❤️❤️❤️❤️

No problem, I am always glad when I can help 🙂 

  • Like 1

Share this post


Link to post
Share on other sites
On 1.8.2019 at 15:48, Hoo said:

Entschuldigung - Ich habe im Moment keine alternativen Vorschläge. Einige der anderen App-Entwickler haben möglicherweise einige Problemumgehungen?

hello @Hoo, are there any new considerations or insights for displaying multiplayer names? We miss this information very much in our league ... Please tell us why the names are not transferred so that we can understand and respond ...

many thanks

Share this post


Link to post
Share on other sites

@Hoo: In multiplayer games the race numbers (visually and via UDP-stream) of the drivers occurs sometimes twice  That should not happen, right?

Share this post


Link to post
Share on other sites
On 8/7/2019 at 1:23 PM, nlocnil said:

I have build an app using C# and I am trying to store results once a multiplayer race is completed. The only reasonable way I can think of is to capture the EventStringCode 'SEND' which should be received when the race is over. Saying this, it seems that I am having issues receiving EventPackets and I am not sure what I am doing wrong. 

To explain better I have created the PacketEventData struct as follows:

/* Sent when an event occurs */
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct PacketEventData
        {
            [MarshalAs(UnmanagedType.Struct)]
            public PacketHeader m_header;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] m_eventStringCode;
            EventDataDetails m_eventDetails;
        }

Some events are actually received but this does not apply for all. For example: SSTA is received for all races, same applies for DRSE. BUT, the FTLP is not always received. In a whole race where there are numerous changes in the fastest lap I am only receiving this event once! Furthermore I do not receive any of the other events like team mate in pits, chequered flag or session ended.

Any ideas on what could be causing such issues? I do not have any other issues with other packets.

Where are you trying to send the data? It's been awhile since I've wrote C# but I don't see a log. As in txt. or database. You have the pack to catch the data, send it but where is it going? To keep the data from the event pack you must save it somewhere within the app or a database. 

Share this post


Link to post
Share on other sites

Hi @Hoo @Faya

If my friends don't lie to me, Public Telemetry is not working and the game is sending all values like if it were Restricted

Please,  can you check this? 

 

Regards

Fernando

Edited by navarreitor

Share this post


Link to post
Share on other sites

@Hoo: And why is the session uid different for players in the same session? - Sorry but this is also a bug.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×