Jump to content Jump to content

F1 2020 UDP Specification


Recommended Posts

There is no session UID in final classification header anymore. This way all our applications are useless.

 

{
m_packetFormat: 2020,
m_gameMajorVersion: 1,
m_gameMinorVersion: 7,
m_packetVersion: 1,
m_packetId: 8,
m_sessionUID: 0n,
m_sessionTime: 0,
m_frameIdentifier: 0,
m_playerCarIndex: 0,
m_secondaryPlayerCarIndex: 0
}

 

Edited by Neospin
Link to post
Share on other sites
On 8/2/2020 at 11:22 PM, navarreitor said:

I just race the weekly event and noticed that when you use the multiplayer car, then your car number is the one you choose when you create your profile.
 

Still waiting to know if this behavior (F1 cars: real car numbers, even in online games when you race with your character / Multiplayer Cars: your chosen number) is the right one or is an error and is going to change back to previous versions behavior

With 1.07 we will have the avatar number, not the official one. I test on PC ;)

Link to post
Share on other sites

Hi,

Does anyone know the meaning of the data in these fields ?


    int16         m_worldForwardDirX;         // World space forward X direction (normalised)
    int16         m_worldForwardDirY;         // World space forward Y direction (normalised)
    int16         m_worldForwardDirZ;         // World space forward Z direction (normalised)
    int16         m_worldRightDirX;           // World space right X direction (normalised)
    int16         m_worldRightDirY;           // World space right Y direction (normalised)
    int16         m_worldRightDirZ;           // World space right Z direction (normalised)

Thx ... Andy

Link to post
Share on other sites
11 hours ago, leung55 said:

 Could anyone give me some advise on how to calculate the gap between cars?


There are several ways depending on how often you want to update it, but you can use the session time in the header as a reference time and then compare something between the drivers (lap distance, sector etc)

Link to post
Share on other sites
  • 2 weeks later...

Hi!

After the new patch, the game shows some useful informations related to pit stops in the "Pit Stop" tab of the menu during the races.

Is there any way to get this info out (like we already do for other similar events) now that it has been added?

That would be really useful.

 

Thanks!

Link to post
Share on other sites

This might sound like a basic question but what is the expected range and unit of values for wheelSlip and wheelSpeed? I currently get values like 0.004381676 for wheelSlip and sometimes as low as -29 all the way to 97 for wheelSpeed and those values don't seem to make sense to me. I don't want to rule out that my code is just not decoding the data properly but without it being documented anywhere it is quite hard to tell what realistic values are.

On a side note: it would be super helpful if we could get the ranges and units for each field as well as an example "package" as part of the docs for reference.

Link to post
Share on other sites

Hey there i have a problem! I want to write a python tool for multiplayer sessions. i want to use the names of the players in the game. the problem is, that only the names of the real F1 drivers are appear. The other called everytime "Player" can i get the name on otherwise?

 

 

thanks for help!!

  • Haha 1
Link to post
Share on other sites
  • 3 weeks later...
On 7/20/2020 at 8:12 PM, Hoo said:

Sorry - we have not managed to get to this yet. Unfortunately, there are a couple of other issues that the team has had to look at. We will try and get to this as soon as we can.

@Hoo Are there plans to work on this UPD-issues? For me it is still important to have the correct penalties in seconds. 

 

And here are a lot of other problems written that could be fixed.

 

Kind regards,

Mark

Edited by markundsteffi
Link to post
Share on other sites

Hi guys, I am quite new to this topic, so I hope my questions are easy to be answered for more experienced F1 gamers: I am trying to extract the data elements from the UDP telemetry packages as it is specified  here: 

 

Strange thing is, that I made it to read/extract some elements of the packet header (Packet Format, Major and Minor Version, Packet ID) without any problem, but many many other data elements deliver implausible values, such as Air Temperature, Track ID, Track Length, ... (all part of Session Packet).

I would appreciate if someone could help me with a working example .ino file for Arduino.

Thanks in advance!

P.S.: I will attach my .ino sketch later to this topic

Link to post
Share on other sites
9 hours ago, Reydel46 said:

Hi.

Do you receive continuous packages during a race/qualify etc. session?

Hi, yes, it takes some seconds until the first UDP package is received, but then UDP packages arrive continuously. I can also read the "packetID" and interprete it correctly, but already sessionTime (which is defined to start 9 bytes (8 of sessionUID + 1) after packetId) does not show plausible values.

This is my definition of the PacketHeader (simply copied and pasted from here):


struct PacketHeader
{
    uint16_t    m_packetFormat;             // 2020
    uint8_t     m_gameMajorVersion;         // Game major version - "X.00"
    uint8_t     m_gameMinorVersion;         // Game minor version - "1.XX"
    uint8_t     m_packetVersion;            // Version of this packet type, all start from 1
    uint8_t     m_packetId;                 // Identifier for the packet type, see below
    uint64_t    m_sessionUID;               // Unique identifier for the session
    float     m_sessionTime;              // Session timestamp
    uint32_t    m_frameIdentifier;          // Identifier for the frame the data was retrieved on
    uint8_t     m_playerCarIndex;           // Index of player's car in the array

   // ADDED IN BETA 2: 
    uint8_t     m_secondaryPlayerCarIndex;  // Index of secondary player's car in the array (splitscreen)
                                          // 255 if no second player
};

 

And this is how I extract the UDP data:

PacketHeader parseHeader()
{
	unsigned int offset = 0;
	PacketHeader ph;
	unsigned char b0, b1, b2, b3, b4, b5, b6, b7;

    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];

    //Packet Format
    unsigned char b16[] = { b0, b1 };
    memcpy(&ph.m_packetFormat, &b16, sizeof(ph.m_packetFormat));


    //Game Major Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_gameMajorVersion, &b0, sizeof(ph.m_gameMajorVersion));

    //Game Minor Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_gameMinorVersion, &b0, sizeof(ph.m_gameMinorVersion));

    //Packet Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_packetVersion, &b0, sizeof(ph.m_packetVersion));

    //Packet ID
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_packetId, &b0, sizeof(ph.m_packetId));

    //Session UID
    offset++;
    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];
    offset++;
    b2 = packetBuffer[offset];
    offset++;
    b3 = packetBuffer[offset];
    offset++;
    b4 = packetBuffer[offset];
    offset++;
    b5 = packetBuffer[offset];
    offset++;
    b6 = packetBuffer[offset];
    offset++;
    b7 = packetBuffer[offset];
    unsigned char b64[] = { b0, b1, b2, b3, b4, b5, b6, b7 };
    memcpy(&ph.m_sessionUID, &b64, sizeof(ph.m_sessionUID));

    //Session Time
    offset++;
    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];
    offset++;
    b2 = packetBuffer[offset];
    offset++;
    b3 = packetBuffer[offset];
    unsigned char b32[] = { b0, b1, b2, b3 };
    memcpy(&ph.m_sessionTime, &b32, sizeof(ph.m_sessionTime));

	...
}

 

Am I doing something wrong in the code?

 

Link to post
Share on other sites
16 hours ago, Reydel46 said:

It doesn't seem like there's something wrong.

Can you attach the .ino so I test it in local?

Hi, sure, here's the complete code: (.ino file attached, too)

/*
 Name:		ButtonBoxII_F1_2020_2.ino
 Created:	19.10.2020 07:19:00
 Author:	gamer_local
*/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

#define DEBUG

// PIN Settings
#define LED_YELLOWFLAG 7

// Network Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 10, 10, 178);
IPAddress gateway(10, 10, 10, 99);
IPAddress subnet(255, 255, 255, 0);

// Local UDP port to listen on
unsigned int localPort = 9000;

// Recipient IP
IPAddress RecipientIP(10, 10, 10, 48);

// Recipient UDP Port
unsigned int RecipientPort = 55056;

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char sessionPacket[UDP_TX_PACKET_MAX_SIZE];
bool udpReceived=false;

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

const int PT_MOTION = 0; //Contains all motion data for player�s car � only sent while player is in control
const int PT_SESSION = 1; //Data about the session � track, time left
const int PT_LAPDATA = 2; //Data about all the lap times of cars in the session
const int PT_EVENT = 3; //Various notable events that happen during a session
const int PT_PARTICIPANTS = 4; //List of participants in the session, mostly relevant for multiplayer
const int PT_CARSETUPS = 5; //Packet detailing car setups for cars in the race
const int PT_CARTELEMETRY = 6; //Telemetry data for all cars
const int PT_CARSTATUS = 7; //Status data for all cars such as damage
const int PT_FINALCLASSIFICATION = 8; //Final classification confirmation at the end of a race
const int PT_LOBBYINFO = 9; //Information about players in a multiplayer lobby


struct PacketHeader
{
    uint16_t    m_packetFormat;             // 2020
    uint8_t     m_gameMajorVersion;         // Game major version - "X.00"
    uint8_t     m_gameMinorVersion;         // Game minor version - "1.XX"
    uint8_t     m_packetVersion;            // Version of this packet type, all start from 1
    uint8_t     m_packetId;                 // Identifier for the packet type, see below
    uint64_t    m_sessionUID;               // Unique identifier for the session
    float     m_sessionTime;              // Session timestamp
    uint32_t    m_frameIdentifier;          // Identifier for the frame the data was retrieved on
    uint8_t     m_playerCarIndex;           // Index of player's car in the array

   // ADDED IN BETA 2: 
    uint8_t     m_secondaryPlayerCarIndex;  // Index of secondary player's car in the array (splitscreen)
                                          // 255 if no second player
};

struct MarshalZone
{
    float  m_zoneStart;   // Fraction (0..1) of way through the lap the marshal zone starts
    int8_t   m_zoneFlag;    // -1 = invalid/unknown, 0 = none, 1 = green, 2 = blue, 3 = yellow, 4 = red
};

enum eZoneFlags : int
{
    invalid = -1,
    none = 0,
    green = 1,
    blue = 2,
    yellow = 3,
    red = 4
};

struct WeatherForecastSample
{
    uint8_t     m_sessionType;                     // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P, 5 = Q1
                                                 // 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ, 10 = R, 11 = R2
                                                 // 12 = Time Trial
    uint8_t     m_timeOffset;                      // Time in minutes the forecast is for
    uint8_t     m_weather;                         // Weather - 0 = clear, 1 = light cloud, 2 = overcast
                                                 // 3 = light rain, 4 = heavy rain, 5 = storm
    int8_t      m_trackTemperature;                // Track temp. in degrees celsius
    int8_t      m_airTemperature;                  // Air temp. in degrees celsius
};

struct PacketSessionData
{
    PacketHeader      m_header;                    // Header

    uint8_t           m_weather;                   // Weather - 0 = clear, 1 = light cloud, 2 = overcast
                                                 // 3 = light rain, 4 = heavy rain, 5 = storm
    int8_t            m_trackTemperature;          // Track temp. in degrees celsius
    int8_t            m_airTemperature;            // Air temp. in degrees celsius
    uint8_t           m_totalLaps;                 // Total number of laps in this race
    uint16_t          m_trackLength;               // Track length in metres
    uint8_t           m_sessionType;               // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P
                                                 // 5 = Q1, 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ
                                                 // 10 = R, 11 = R2, 12 = Time Trial
    int8_t            m_trackId;                   // -1 for unknown, 0-21 for tracks, see appendix
    uint8_t           m_formula;                   // Formula, 0 = F1 Modern, 1 = F1 Classic, 2 = F2,
                                                 // 3 = F1 Generic
    uint16_t          m_sessionTimeLeft;           // Time left in session in seconds
    uint16_t          m_sessionDuration;           // Session duration in seconds
    uint8_t           m_pitSpeedLimit;             // Pit speed limit in kilometres per hour
    uint8_t           m_gamePaused;                // Whether the game is paused
    uint8_t           m_isSpectating;              // Whether the player is spectating
    uint8_t           m_spectatorCarIndex;         // Index of the car being spectated
    uint8_t           m_sliProNativeSupport;   // SLI Pro support, 0 = inactive, 1 = active
    uint8_t           m_numMarshalZones;           // Number of marshal zones to follow
    MarshalZone       m_marshalZones[21];          // List of marshal zones � max 21
    uint8_t           m_safetyCarStatus;           // 0 = no safety car, 1 = full safety car
                                                   // 2 = virtual safety car
    uint8_t           m_networkGame;               // 0 = offline, 1 = online
    uint8_t           m_numWeatherForecastSamples; // Number of weather samples to follow
    WeatherForecastSample m_weatherForecastSamples[20];   // Array of weather forecast samples
};



void parseUDPPacket()
{
    //out("Test", "222");    
    if (udpReceived == true)
    {
    out("===========================================");
    PacketHeader ph;
    unsigned int offset = 0;
    ph = parseF12020Header(offset);
    out("Packet Format", ph.m_packetFormat);
    out("Game Major Ver.", ph.m_gameMajorVersion);
    out("Game Minor Ver.", ph.m_gameMinorVersion);
    out("Packet Format", ph.m_packetFormat);
    out("Packet ID", ph.m_packetId);
    if (ph.m_packetId == PT_SESSION)
    {
        offset++;
        out("Start parsing session packet at index");
        PacketSessionData sd = parseSessionData(offset);
        out("Session data parsed.");
        //
        //output of selected session props and values
        out("Weather", sd.m_weather);
        out("Track ID", sd.m_trackId);
        out("Air Temp.", sd.m_airTemperature);
        out("Track Temp.: ", sd.m_trackTemperature);
        out("Total laps: ", sd.m_totalLaps);
        out("Track length: ", (uint16_t)sd.m_trackLength);
        out("Num MZ: ", sd.m_numMarshalZones);
    }
}
    else
    {
        out("No Data");
    }
}




//=== Parse UDP Header of F1 2020
///
PacketHeader parseF12020Header(unsigned int& offset)
{
    PacketHeader ph;

    unsigned char b0, b1, b2, b3, b4, b5, b6, b7;

    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];

    //Packet Format
    unsigned char b16[] = { b0, b1 };
    memcpy(&ph.m_packetFormat, &b16, sizeof(ph.m_packetFormat));


    //Game Major Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_gameMajorVersion, &b0, sizeof(ph.m_gameMajorVersion));

    //Game Minor Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_gameMinorVersion, &b0, sizeof(ph.m_gameMinorVersion));

    //Packet Version
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_packetVersion, &b0, sizeof(ph.m_packetVersion));

    //Packet ID
    offset++;
    b0 = packetBuffer[offset];
    memcpy(&ph.m_packetId, &b0, sizeof(ph.m_packetId));

    //Session UID
    offset++;
    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];
    offset++;
    b2 = packetBuffer[offset];
    offset++;
    b3 = packetBuffer[offset];
    offset++;
    b4 = packetBuffer[offset];
    offset++;
    b5 = packetBuffer[offset];
    offset++;
    b6 = packetBuffer[offset];
    offset++;
    b7 = packetBuffer[offset];
    unsigned char b64[] = { b0, b1, b2, b3, b4, b5, b6, b7 };
    memcpy(&ph.m_sessionUID, &b64, sizeof(ph.m_sessionUID));

    //Session Time
    offset++;
    b0 = packetBuffer[offset];
    offset++;
    b1 = packetBuffer[offset];
    offset++;
    b2 = packetBuffer[offset];
    offset++;
    b3 = packetBuffer[offset];
    unsigned char b32[] = { b0, b1, b2, b3 };
    memcpy(&ph.m_sessionTime, &b32, sizeof(ph.m_sessionTime));

    //Frame identifier
    offset++;
    b0 == packetBuffer[offset];
    offset++;
    b1 == packetBuffer[offset];
    offset++;
    b2 == packetBuffer[offset];
    offset++;
    b3 == packetBuffer[offset];
    b32[0] = b0;
    b32[1] = b1;
    b32[2] = b2;
    b32[3] = b3;
    memcpy(&ph.m_frameIdentifier, &b32, sizeof(ph.m_frameIdentifier));

    //Player Car Index
    offset++;
    b0 == packetBuffer[offset];
    memcpy(&ph.m_playerCarIndex, &b0, sizeof(ph.m_playerCarIndex));

    //Secondary Car Index
    offset++;
    b0 == packetBuffer[offset];
    memcpy(&ph.m_secondaryPlayerCarIndex, &b0, sizeof(ph.m_secondaryPlayerCarIndex));
    return ph;
}

/// <summary>
/// Parse SESSION Packet
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
PacketSessionData parseSessionData(unsigned int& offset)
{
    PacketSessionData sd;
    unsigned int c = offset;

    unsigned char b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10;
    //
    //Weather 
    b0 = packetBuffer[c];
    memcpy(&sd.m_weather, &b0, sizeof(sd.m_weather));

    //
    //Track Temperature
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_trackTemperature, &b0, sizeof(sd.m_trackTemperature));

    //
    //Air Temperature
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_airTemperature, &b0, sizeof(sd.m_airTemperature));

    //
    //Total Laps
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_totalLaps, &b0, sizeof(sd.m_totalLaps));

    //
    //Track Length
    c++;
    b0 = packetBuffer[c];
    c++;
    b1 = packetBuffer[c];
    unsigned char b160[] = { b0, b1 };
    memcpy(&sd.m_trackLength, &b0, sizeof(sd.m_trackLength));

    //
    //Session Type
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_sessionType, &b0, sizeof(sd.m_sessionType));

    //
    //Track ID
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_trackId, &b0, sizeof(sd.m_trackId));

    //
    //Formula
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_formula, &b0, sizeof(sd.m_formula));

    //
    //Session Time Left
    c++;
    b0 = packetBuffer[c];
    c++;
    b1 = packetBuffer[c];
    unsigned char b161[] = { b0, b1 };
    memcpy(&sd.m_sessionTimeLeft, &b161, sizeof(sd.m_sessionTimeLeft));

    //
    //Session Duration
    c++;
    b0 = packetBuffer[c];
    c++;
    b1 = packetBuffer[c];
    unsigned char b162[] = { b0, b1 };
    memcpy(&sd.m_sessionDuration, &b162, sizeof(sd.m_sessionDuration));

    //
    //Pit Speed Limit
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_pitSpeedLimit, &b0, sizeof(sd.m_pitSpeedLimit));

    //
    //Game paused
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_gamePaused, &b0, sizeof(sd.m_gamePaused));

    //
    //Is spectating
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_isSpectating, &b0, sizeof(sd.m_isSpectating));

    //
    //Spectator car index
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_spectatorCarIndex, &b0, sizeof(sd.m_spectatorCarIndex));

    //
    //SLI
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_sliProNativeSupport, &b0, sizeof(sd.m_sliProNativeSupport));

    //
    //no of marshal zones
    c++;
    b0 = packetBuffer[c];
    int numOfMZ = (int)b0;
    memcpy(&sd.m_numMarshalZones, &b0, sizeof(sd.m_numMarshalZones));

    for (int i = 0; i < numOfMZ; i++)
    {
        //Zone Start
        c++;
        b0 = packetBuffer[c];
        c++;
        b1 = packetBuffer[c];
        c++;
        b2 = packetBuffer[c];
        c++;
        b3 = packetBuffer[c];
        c++;
        unsigned char b32[] = { b0, b1, b2, b3 };
        memcpy(&sd.m_marshalZones[i].m_zoneStart, &b32, sizeof(sd.m_marshalZones[i].m_zoneStart));

        //
        //no of marshal zones
        c++;
        b0 = packetBuffer[c];
        memcpy(&sd.m_marshalZones[i].m_zoneFlag, &b0, sizeof(sd.m_marshalZones[i].m_zoneFlag));
        Serial.print(i);
        Serial.print(" - Flags: ");
        Serial.print(b0);
        if (b0 == 3) //todo: use enum value
        {
            Serial.println("YELLOW!");
        }
    }

    //
    //Safety Car
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_safetyCarStatus, &b0, sizeof(sd.m_safetyCarStatus));

    //
    //Network Game
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_networkGame, &b0, sizeof(sd.m_networkGame));

    //
    //Number of weather forecast samples to follow
    c++;
    b0 = packetBuffer[c];
    memcpy(&sd.m_numWeatherForecastSamples, &b0, sizeof(sd.m_numWeatherForecastSamples));

    offset = c;
    return sd;
}


//=============================================================
// Check for new UDP packets
//=============================================================
void checkUDP()
{
    // if there's data available, read a packet
    int packetSize = Udp.parsePacket();
    if (packetSize)
    {
        //Serial.print("Packet Size: ");
        //Serial.println(packetSize);
        // read the packet into packetBufffer
        Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);

        // for debug only
        // write packetBuffer to serial
        //Serial.print("Packet Content: ");
        //Serial.println(packetBuffer);

        // send "ACK" as reply
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write("ACK");
        Udp.endPacket();
    }
    udpReceived = packetSize > 0;
    delay(10);
}








//========================================================================================================
// Send UDP packets
//========================================================================================================
void sendUDP(String text)
{
    Udp.beginPacket(RecipientIP, RecipientPort);
    // Udp.write("Test");
    Udp.print(text);
    Udp.endPacket();
    //delay(10);
    delay(1000);
}


//==========================================================================================================
// SETUP
//==========================================================================================================
void setup() {
    // for debug only
    Serial.begin(9600);

    out("UDP setup...");

    // start Ethernet
    Ethernet.begin(mac, ip);

    // Start UDP
    Udp.begin(localPort);


    pinMode(LED_YELLOWFLAG, OUTPUT);   // LED an Pin7 

    // send UDP Ready 
    sendUDP("UDP Ready");

    out("UDP ready");

}


//==========================================================================================================
// LOOP
//==========================================================================================================
void loop()
{
    checkUDP();
    parseUDPPacket();
}


/// <summary>
/// Convert decimal string to an unsigned integer.
/// The string must be null-terminated!
/// </summary>
/// <param name="numStr"></param>
/// <returns></returns>
//unsigned long stringToUInt(char numStr[])
//{
//
//    // Convert decimal string in numStr to an unsigned integer in num.
//    // The string must be null-terminated!
//    unsigned long num;
//    num = atol(numStr);
//
//    Serial.println(num);
//    return num;
//}

//unsigned long stringToUInt2(int numBufSize, char numStr[UDP_TX_PACKET_MAX_SIZE])
//{
//    // Convert decimal string in numStr to an unsigned integer in num.
//    // The string is in a fixed size buffer.
//    // There is no checking for invalid digit characters or number too large.
//    unsigned long num = 0;
//    for (int i = 0; i < numBufSize; i++) {
//        num = num * 10 + (numStr[i] - '0');
//    }
//    return num;
//}

void timestamp()
{
    unsigned long time;
    time = millis();
    Serial.print(time);
    Serial.print(" - ");
}

void out(char text[])
{    
    timestamp();
    Serial.println(text);
}


void out(char attName[], char attValue[])
{
    timestamp();
    Serial.print(attName);
    Serial.print(" = ");
    Serial.println(attValue);
}

void out(char attName[], int16_t attValue)
{
    timestamp();
    Serial.print(attName);
    Serial.print(" = ");
    char buffer[17];
    itoa(attValue, buffer, 10);
    Serial.println(buffer);
}

//}

I am looking forward to seeing your test results!

 

ButtonBoxII_F1-2020_2.ino

Link to post
Share on other sites

Hi.
I've tried your code and same result.

I also tried with another approach (in this case i tried the telemetry data but it's the same)

void loop() {

  int packetSize = Udp.parsePacket();

if(packetSize == 1307){
	char packetBuffer[packetSize];
	Udp.read(packetBuffer, packetSize);
	PacketCarTelemetryData* recv_data;
	recv_data = (struct PacketCarTelemetryData *) &packetBuffer[0];
 	Serial.println(recv_data->m_carTelemetryData.m_gear);
	}
}

If i try to read the header data inside the TelemetryCarPacket, i can read it without problem like you. When i try to read data inside the TelemetryCar struct (in this example "m.gear") it gives me invalid numbers. 

Anyway i'm still trying to solve this, i'll let you know if i have any news.

Edited by Reydel46
Link to post
Share on other sites
On 9/8/2020 at 3:56 AM, relihimas said:

can anyone help me how I can get the data using python?

Someone wrote a python tool here, maybe you can use this as an example.

On 9/18/2020 at 9:45 PM, xNachtelf said:

Hey there i have a problem! I want to write a python tool for multiplayer sessions. i want to use the names of the players in the game. the problem is, that only the names of the real F1 drivers are appear. The other called everytime "Player" can i get the name on otherwise?

This has been discussed multiple times already. Codemasters claim they can't send the username because of data protection rules (which is ridiculous). As a workaround I use "Player" and the Driver ID in the ParticipantsData packet.

I thought after two months there would be some updates here, but it looks like telemetry isn't important enough compared to all the other bugs that need fixing. Maybe there'll be some updates in F1 2021.

Link to post
Share on other sites

I have encountered a few issues with the telemetry data over the past few months which causes erroneous data to be displayed in my app (https://apps.apple.com/gb/app/race-engineer-2020/id1522782768):

Currently running v1.12 on PS4
1. During a session, if a driver pits, their `m_driverStatus` is stick at 2 (in lap) for the rest of the session

2. The visual and actual tire compounds for F2 and classic events seem to be wrong (or swapped around). For example, I am reading values of 22 and 14 for visual and actual respectively which currently out of bounds according to the telemetry spec. Also, in the spec, it is not clear what "Same as above" means. Are you referring to the same as the actual tyre compound? Or the same as the F1 tyre compound?

3. When a driver invalidates "this and the next lap", the `m_currentLapInvalid` value for the next lap is 0, but it should be 1

4. All event packets are sent twice

5.  The final classification data packets are sent twice

 

Edited by devvydevdev
Link to post
Share on other sites
  • 2 weeks later...

Hello

I am a player from China. I like F1 series games very much. I am making a Dashborad to display the speed and gear of the vehicle, I use QT to develop a UDP tool to receive game data,but there is a garbled situation,I found that the F1 Telemetry software you developed is also based on QT, so I would like to ask you how to do it. I can pay for your help. If possible, please entrust you to develop a tool similar to simcube to get more information. Data for multiple games.
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...