How do I decrypt a UDP-Packet?

Hallo everyone,
i'm an absolute beginner to the world of Arduino and haven't any knowledge about programming. Because of my interest in SimRacing and DIY Stuff, I came up with the Idea of making my own Steeringwheel with a Display that monitors the telemetry of the Car. For now I just want to get it to work with the telemetry send via UDP from the game F1 2021 . The Arduino I am using is the WiFi uno Rev 2

With the Example "WiFi UDP Send and Receive String" from the WiFiNINA lib, I was able to wrote my first Sketch that is able to receive UDP. It receives the Packages from the game too. But I know, that I still have to decode/decrypt the Packages. And that's the point where I am stuck. I already searched for some examples and found a few helpful things but did not found any tutorial or explanation for the decoding of incoming UDP.

This is the Sketch I wrote, to receive the UDP-Packages. I already found some things for improvement, but for the beginn it's enough:

#include <WiFiNINA.h>
#include <WiFiUDP.h>

// Daten für Verbindung mit WLAN
int status = WL_IDLE_STATUS;
#include "arduino_secrets.h"                                  // Eingabe von SSID und Passwort in tab/arduino_secrets.h
char ssid[] = SECRET_SSID;                                    // Netzwerk SSID (name)
char pass[] = SECRET_PASS;                                    // Passwort 

WiFiUDP Udp;                                                  // Festlegen von UDP Objekt
unsigned int localPort = 20777;                               // Sendender Port/Local Port (hier Xbox F1 21)
char packetBuffer[255];                                       // Speicherplatz (Buffer) für erhaltene Pakete

void setup() 
{
  Serial.begin(9600);                                          // Startet den Seriellen Monitor
                                                               // Mit WiFi verbinden
  WiFi.begin(ssid, pass);                                      // WiFi initialisieren
  while (status != WL_CONNECTED)                               // While-Schleife läuft so lange bis verbunden (WL_CONNECTED)
    {
    Serial.print("Verbindet mit SSID: ");                      // Status in Seriel zeigen
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);                                              // Warten auf verbindung (10Sek.)
    }
  Serial.println("Mit WiFi verbunden");                        // Gibt im Seriellen Monitor aus ob verbunden ist
  printWifiStatus();
  
  Serial.println("Verbindet mit Local UDP Port ...");          // Gibt im S.M. aus, dass verbindung zu UPD Port beginnt
  Udp.begin(localPort);                                        // Initialisiert das empfangen von UDP 
  Serial.println("Verbunden");
}

void printWifiStatus()                                        // Gibt im S.M. die genutzte IP Adresse und SSID aus
{
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Adresse: ");
  Serial.println(ip);
}

void loop() 
{
  int packetSize = Udp.parsePacket();                           // Empfängt das Paket und gibt im S.M. Größe, SenderIP und Senderport aus
  if (packetSize)
    {
      Serial.print("Erhalt eines UDP-Pakets mit der Größe ");
      Serial.println(packetSize);
      Serial.print("von ");
      IPAddress remoteIp = Udp.remoteIP();
      Serial.print(remoteIp);
      Serial.print(", port ");
      Serial.println(Udp.remotePort());
    }

  int len = Udp.read(packetBuffer, 255);                        // Überführt UDP-Paket in den Buffer und ließst es aus
  if (len > 0)
    {
      packetBuffer[len] = 0;
    }
  Serial.print("Inhalt: ");
  Serial.println(packetBuffer);
}

This is a parser I found on GitHub, but its in TypeScript and I don't how to use it properly for the Arduino:
https://github.com/raweceek-temeletry/f1-2021-udp
The other Parser I found (https://github.com/thealexinator2904/Arduino_F1_UDP_Parser) is written for the Arduino. But when I try to compile it, the IDE gives me various errors. I know, that the Sketch was written for the ESP32, but another search said, that I just need to replace WiFi.h with the WiFiNINA.h lib. After this, it still gives out another error.

This is the example sketch where I switch the WiFi.h with the WiFiNINA.h:

#include <Arduino.h>
#include <WiFiNINA.h>
#include <WiFiUdp.h>
#include <F1_UDP_Parser.h>

const char *SSID = "Your SSID";
const char *WiFiPassword = "YOur PW";

void ConnectToWiFi();
 
//The IP address that this arduino has requested to be assigned to.
IPAddress ip();
WiFiUDP Udp;
int flag = 0;

unsigned int localPort = 8888; 

F1_UDP_Parser* parser;

void setup() 
{ 
  parser = new F1_UDP_Parser();
  Serial.begin(115200);
  ConnectToWiFi();
  Udp.begin(localPort);
}

void loop()
{
  int packetSize = Udp.parsePacket(); 
    if(packetSize) 
    {
       char packetBuffer[packetSize];
       while(Udp.available())
       {
        Udp.read(packetBuffer, packetSize);
       }
       parser->push(packetBuffer);
       Serial.print("Speed: ");
       Serial.println(parser->packetCarTelemetryData()->m_carTelemetryData(0).m_speed);
  }
}
void ConnectToWiFi()
{
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, WiFiPassword);
  Serial.print("Connecting to "); Serial.println(SSID);
 
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print('.');
    delay(500);
 
    if ((++i % 16) == 0)
    {
      Serial.println(F(" still trying to connect"));
    }
  }
 
  Serial.print(F("Connected. My IP address is: "));
  Serial.println(WiFi.localIP());
}

And this is the error I get:

Arduino: 1.8.19 (Mac OS X), Board: "Arduino Uno WiFi Rev2, None (ATMEGA4809)"

In file included from /Users/------------/Documents/Arduino/libraries/Arduino_F1_UDP_Parser-main/src/F1_UDP_Parser.h:21:0,
                 from /Users/----------/Desktop/F1_2021_parser2/F1_2021_parser2.ino:4:
/Users/---------/Documents/Arduino/libraries/Arduino_F1_UDP_Parser-main/src/PacketEventData.h:18:9: fatal error: string: No such file or directory
 #include<string>
         ^~~~~~~~
compilation terminated.
exit status 1

So, this is the Problem I have. I know, that this is a pretty deep dive into the topic without any knowledge. I am just asking for a hint or maybe some literature about the encoding of UDP. It would make me very happy, if there's someone, who could help me with this! Thank you all!

I don't think your issue is with encoding/decoding UDP per-se.

UDP packets have a simple header which is used for getting the packet from the sender to the receiver: this is usually parsed for you by the OS or underlying libraries, and you probably don't really care about it.

What you actually care about is the data payload of the UDP packet since that's where all the game state information lives; and UDP doesn't say anything about the data payload: it's just an arbitrary bunch of bytes from the perspective of the network.

So the real question is: how to decode the data payload that the game is sending?

Unfortunately, it's hard to give generic advice on how to handle this, because there is no standard for such things. Maybe the playload is a json string. Maybe it's a special binary format. Maybe it is being serialised using a common library such as protbuf. Maybe it has layers of encryption on it. Who knows?

The answers to these questions should come from the makers of the game -- and it looks as though the github project you posted does describe the data stream here: GitHub - raweceek-temeletry/f1-2021-udp: UDP telemetry parser for the Codemasters F1 2021 game

Does the documentation at that link make sense to you?

Thanks for the fast answer!

Thats exactly what I meant. Sorry, if I used the wrong words. But isn't a parser for this? It defines all "random" bytes and works like a translator, right? If so, then I do understand the documentation. Each packet comes with the same Header but contains different parts of the telemetry. In wich frequency they come and how they are structured is described also there. I also know, that the encoding format is little endian and just the "Event Packet" uses strings.
I just don't know how to implement it into an Arduino Sketch and make use of it. I'm searching now for a few weeks and have two books with each 500 pages about the Arduino and his IDE but can't find anything about this topic.

My guess is that you won't. Probably a matter of learning how to program in C++ and writing the code yourself.

OK, well what you said already was a good start -- the documentation explains the structure of the payload data; and, yes, a parser is for reading that data into representations that a program can make use of.

When I say "representations that a program can make use of", that's really translating an array of bytes into things like strings, integers, floats, and so forth.

To take a really simple example, lets imagine that you and I want to exchange an integer using a UDP packet. We might agree that the integer will be sent as 4 bytes in network byte order (big endian). So a program to handle that packet would need to treat that array of 4 bytes as an integer, and possibly swap endianess (C functions like ntohl are your friend here). The program could then do whatever it wanted with that integer: write it to screen, use it in a calculation, it's up to you.

In terms of getting going with your project I think you can either try to get the parser code you have building, or use it as a reference to re-implement yourself. It depends a bit on the scope of the parser as to what is easier.

Definitely! Everything, wich goes further than the introducing Literature, seems to be knowledge, that one can only build by actually writing and working.

Thanks for the feedback!
Your example gave me indubitably a better understanding and shows me, that I wasn't so wrong about it.

But what does the error mean? Is it a missing library?

In file included from /Users/------------/Documents/Arduino/libraries/Arduino_F1_UDP_Parser-main/src/F1_UDP_Parser.h:21:0,
                 from /Users/----------/Desktop/F1_2021_parser2/F1_2021_parser2.ino:4:
/Users/---------/Documents/Arduino/libraries/Arduino_F1_UDP_Parser-main/src/PacketEventData.h:18:9: fatal error: string: No such file or directory
 #include<string>

I red that string.h isn't necessary because Arduino.h can do the job too, is that true? Even when I include it, the IDE can't find it. Since there will be a part where I have to handle strings.

Did you mention which Arduino you're using?

I'm not sure whether this forum question might give you a steer?

The error is telling you that the compiler is unable to find the specified include file.

To diagnose this, if you can get your compilation environment to give verbose output you should be able to see what the include paths are (they will be specified as -Imy/include/path), and the toolchain itself has some default inbuilt search paths.

I'm using the Arduino uno WiFi Rev 2.

It is definitely the same error. Thanks for searching, it does give me some hints. Pretty sure, I'm going to find more about it.

Yes, found the option. This is really useful and it also points out, that seemingly the <F1_UDP_Parser.h> works. The compiler says now, that specifically the "event packet" is causing the #include error.

Thank you so much! Even though it wasn't a solution (I wasn't expanding one), you gave me a better understanding and showed me, that I'm on the right way. Now I know, I have everything I need and "just" have to understand the code with its commands.

Awesome :smiley:

I think if you've got code that's written for the ESP8266 and you want to build for the Uno you might have a bit of work to do to get it going. Hopefully it won't be insurmountable: at the end of the day, the parser code is not going to be doing anything very hardware-specific, but you might have some build errors to address.

Anyway -- good luck with your project!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.