PDA

View Full Version : C# Udp V2 library



Zeratall
26-05-2018, 02:55
For those of you who don't know I'm the developer of PC2Tuner at RacingSimTools.com, I'm currently building a UDP library in c# for the pcars2 udp structure. I've contemplated releasing the library for free so developers that don't understand udp can just use the library to use in their functions.

Would there be much interest in this? If so, i'll look into making it mkre out of the box ready for developers.

Maskmagog
26-05-2018, 08:28
I think this would be very much appreciated! I would love it. I'm building a buttonbox, and could use UDP to control leds, for example. But programming the UDP receiving part is way out of my league.

Zeratall
26-05-2018, 18:28
I think this would be very much appreciated! I would love it. I'm building a buttonbox, and could use UDP to control leds, for example. But programming the UDP receiving part is way out of my league.

I kinda figured, every-time I see someone post, people ask for help. Anyways I'm creating the library, its going to make UDP super easy, below is a picture of working usage of the new library.

255127

ermo
28-05-2018, 15:53
@Zeratall:

If you do release it, maybe consider using either a MIT, Apache 2.0 or LGPL/GPL license? That way, if you lose interest in it, other people can fork it and carry on the development (if you're comfortable with such a setup, that is).

Zeratall
28-05-2018, 16:31
Yeah for sure, that's what I was thinking.

AndrewTurner
17-06-2018, 04:35
I would be very appreciative of such a library Zeratall.

Zeratall
17-06-2018, 23:39
I have it created already, let me make an example and I can give it out tonight!

SimssmiS
21-06-2018, 19:35
Hey Zeratall any Update?

Zeratall
22-06-2018, 00:35
Yep, I keep getting pulled away I'll upload it tonight I promise.

Zeratall
22-06-2018, 03:52
As promised here is a UDP library for the car data in the UDP packet for Version 2 UDP structure, I will be updating this as I pull in the timing and session info, but this should get people started. the "PCars2_UDP.cs" Is the C# class where you can import into your projects.

To help you see how to use the library refer to the example folder "UDP_Example" this is a C# project to show you what you need to do to use the library.

https://github.com/Zdetier/RST_UDP

Maskmagog
23-06-2018, 13:31
In the words of Montgomery C. Burns: Excellent!

I had some issues at first, all because I'm a total noob at this. Here's what I did, in case someone else has the same problem:
I installed Microsoft Visual Studio Community, the free version of Visual Studio. It threw an error when I tried to open the UDP example, something about missing .NET,Version 4.6.1, Targeted Pack or something like that. In Visual Studio, I went to Tools->Get tools and features. There I selected .NET Desktop Development, and then pressed Modify-button to install it. After this, I could open, and run the example which worked like a charm! Thanks Zeratall, time to start googling C# tutorials :)

Maskmagog
23-06-2018, 15:19
Hi again :)
Not sure if I managed to break something, but uDP.Speed shows roughly a quarter of my speed in km/h. So I if I drive in 80 km/h, uDP.Speed shows around 20?
Other values such as Tyre Temp, Brake Temp seem fine.

cpcdem
23-06-2018, 16:04
Hi again :)
Not sure if I managed to break something, but uDP.Speed shows roughly a quarter of my speed in km/h. So I if I drive in 80 km/h, uDP.Speed shows around 20?
Other values such as Tyre Temp, Brake Temp seem fine.

It's in m/sec :)

Maskmagog
23-06-2018, 16:37
It's in m/sec :)
Aaah that makes sense! Should have figured. Thanks!

Zeratall
24-06-2018, 01:34
Yeah the documentation that sms gave out for udp had little to no explanation of units, typically what I do is refer to the sms shared memory documentation as that one does, and a lot of the udp variables have the exact same name in the shared memory so should be similar.

If you guys have any questions let me know!

Maskmagog
25-06-2018, 19:52
If you guys have any questions let me know!

You might regret that :)
I've been trying to add more variables to the library, but I'm stabbing in the dark most of the time. I'd like to add the rest from TelemetryData, and then RaceData. That would keep me busy for a while :) But this byte[], char, binaryReader etc is Greek to me. I realize that at least parts of this is simple for a programmer, but I have googled a lot, and learned a lot, and failed.
This is what I've added in TelemetryData:

private byte _Handbrake;
private byte _AeroDamage;
private byte _EngineDamage;
private UInt32 _Joypad0;
private byte _DPad;
private char[] _TyreCompound[TYRE_NAME_LENGTH_MAX] = new byte [4];
private float _TurboBoostPressure;
private float _FullPosition;
private byte _BrakeBias;
private UInt32 _TickCount;

I've tried to copy settings from other, working variables, but TyreCompound for example is char, which has not been in use before.
Also, I don't have a clue what to do with the #define from SMS UDP definitions (from here (https://www.projectcarsgame.com/wp-content/uploads/2018/03/sms_udp_definitions_v2.zip)). For example these two for TelemetryData stream:
#define UDP_STREAMER_CAR_PHYSICS_HANDLER_VERSION 2
#define TYRE_NAME_LENGTH_MAX 40

Following is my addition to public void ReadTelemetryData:

Handbrake = binaryReader.ReadByte();
AeroDamage = binaryReader.ReadByte();
EngineDamage = binaryReader.ReadByte();
Joypad0 = binaryReader.ReadUInt32();
DPad = binaryReader.ReadByte();
TyreCompound[0] = binaryReader.ReadChar();
TyreCompound[1] = binaryReader.ReadChar();
TyreCompound[2] = binaryReader.ReadChar();
TyreCompound[3] = binaryReader.ReadChar();
TurboBoostPressure = binaryReader.ReadSingle();
FullPosition = binaryReader.ReadSingle();
BrakeBias = binaryReader.ReadByte();
TickCount = binaryReader.ReadUInt32();

I've also added following at the end for each variable. Byte for Handbrake, AeroDamage, EngineDamage, DPad, BrakeBias. UInt32 for Joypad0 and TickCount. Char[] for TyreCompound and float for TurboBoostPressure and FullPosition. All same as above.

public byte AeroDamage
{
get
{
return _AeroDamage;
}
set
{
_AeroDamage = value;
}
}


I think that EngineDamage is working, but I can't get something I understand from AeroDamage or BrakeBias, for example. And I can't get TyreCompound to even compile.
Any help's much appreciated! Or if someone else with the needed skills should find the time and motivation to do it, that would work too :)

cpcdem
25-06-2018, 21:13
Well, that looks Greek to me, too, but I am actually Greek, so that helps :)

You are also doing fine in your translation, too, only problem as you have already found out is the sTyreCompound. First of all though, about UDP_STREAMER_CAR_PHYSICS_HANDLER_VERSION and TYRE_NAME_LENGTH_MAX, those are c++ directives, for the c# code you can define them in the beginning of the PCars2_UDP class as consts:

const int UDP_STREAMER_CAR_PHYSICS_HANDLER_VERSION = 2;
const int TYRE_NAME_LENGTH_MAX = 40;

Now about _TyreCompound, this is a 4 items long array, with each item being another (byte) array, holding the name of each tire. One way to define it is to use

private byte[][] _TyreCompound = new byte[4][];

and then, when reading it, you must use this:

_TyreCompound[0] = binaryReader.ReadBytes(TYRE_NAME_LENGTH_MAX);
_TyreCompound[1] = binaryReader.ReadBytes(TYRE_NAME_LENGTH_MAX);
_TyreCompound[2] = binaryReader.ReadBytes(TYRE_NAME_LENGTH_MAX);
_TyreCompound[3] = binaryReader.ReadBytes(TYRE_NAME_LENGTH_MAX);

Finally, in order to convert each tire name to a string, you must use something like

tireName = System.Text.Encoding.UTF8.GetString(_TyreCompound[0]);

for the front left tire, _TyreCompound[1] for the front right etc.

I made sure that the above compiles, but have not tested it if it really works correctly, too. I assume it does, unless I have made some stupid mistake! Please try it and if it doesn't, I or someone else will look further into it.

Maskmagog
25-06-2018, 21:23
Thanks cpcdem! Too tired to try this now, but I'll give it a go tomorrow.

Sampo
25-06-2018, 23:50
In C, your _AeroDamage and _EngineDamage are unsigned chars (so unsigned bytes) (with values between 0-255) and represent the percentage of damage with 255 being 100%. I convert those to float and then divide by 2.55 to get the percentage easily. With BrakeBias you have to do (255-BrakeBias)/2.55 to get the front break bias percentage (again, converting BrakeBias to float helps with accuracy). I'm not familiar with C#, so can't give the straight answer.

Zeratall
26-06-2018, 01:34
So to understand a binary reader you need to understand the structure of udp. A udp is a message that broadcasts a message in binary. The size of the binary message depends on how much data is sent. Let's say we want to receive a udp message with two ints. We know the message would be 8 bytes long. Because an int is 4 bytes long and 2x4 =8. We can remove bytes 0-3 and save into variable 1 and then save bytes 4-8 in variable 2.

In the code where you see stream.index = 12 we are telling the code for the message we want to start at byte 12 ( base packet are bytes 0-12 which we don't care about) then when you see binaryReader.convertTo. It's take our current stream position and moving the index over the amount the data type used in the convert and saving those bytes to a variable. Basically your dissecting the message in chunks.

Sampo
26-06-2018, 03:30
Remember that the PacketBase contains 3 important values. mPartialPacketIndex, mPartialPacketNumber, mPacketType. Without those you can't decipher the udp packets correctly. Unless your library does that for the user, of course.

Maskmagog
26-06-2018, 08:26
Thanks, it makes more and more sense to me. I enjoy tampering with things like this, but sometimes it's a bit overwhelming.

Zeratall
26-06-2018, 12:02
Remember that the PacketBase contains 3 important values. mPartialPacketIndex, mPartialPacketNumber, mPacketType. Without those you can't decipher the udp packets correctly. Unless your library does that for the user, of course.

It does that for them currently in the object definition.

Maskmagog
26-06-2018, 16:13
Thanks @cpcdem, I could actually get it to work! My understanding of arrays has gone from 3% to at least 12% :)

Zeratall
29-06-2018, 22:14
Updated the library added, timing (split times) and then participant info, so you can get the following attributes now.

for (int i = 0; i < 32; i++)
{
ParticipantInfo[i, 0] = Convert.ToDouble(binaryReader.ReadInt16()); //WorldPosition
ParticipantInfo[i, 1] = Convert.ToDouble(binaryReader.ReadInt16()); //WorldPosition
ParticipantInfo[i, 2] = Convert.ToDouble(binaryReader.ReadInt16()); //WorldPosition
ParticipantInfo[i, 3] = Convert.ToDouble(binaryReader.ReadInt16()); //Orientation
ParticipantInfo[i, 4] = Convert.ToDouble(binaryReader.ReadInt16()); //Orientation
ParticipantInfo[i, 5] = Convert.ToDouble(binaryReader.ReadInt16()); //Orientation
ParticipantInfo[i, 6] = Convert.ToDouble(binaryReader.ReadUInt16()); //sCurrentLapDistance
ParticipantInfo[i, 7] = Convert.ToDouble(binaryReader.ReadByte()) - 128; //sRacePosition
byte Sector_ALL = binaryReader.ReadByte();
var Sector_Extracted = Sector_ALL & 0x0F;
ParticipantInfo[i, 8] = Convert.ToDouble(Sector_Extracted+1); //sSector
ParticipantInfo[i, 9] = Convert.ToDouble(binaryReader.ReadByte()); //sHighestFlag
ParticipantInfo[i, 10] = Convert.ToDouble(binaryReader.ReadByte()); //sPitModeSchedule
ParticipantInfo[i, 11] = Convert.ToDouble(binaryReader.ReadUInt16());//sCarIndex
ParticipantInfo[i, 12] = Convert.ToDouble(binaryReader.ReadByte()); //sRaceState
ParticipantInfo[i, 13] = Convert.ToDouble(binaryReader.ReadByte()); //sCurrentLap
ParticipantInfo[i, 14] = Convert.ToDouble(binaryReader.ReadSingle()); //sCurrentTime
ParticipantInfo[i, 15] = Convert.ToDouble(binaryReader.ReadSingle()); //sCurrentSectorTime
}

Just keep in mind the index is not equal to race position. however if you just want the data for yourself (lets say your "Current Sector Time" for your car your object called would look like this . MyCurrentSectorTime = uDP.ParticipantInfo[uDP.ViewedPlayerIndex,15].

cpcdem
30-06-2018, 01:21
Just keep in mind the index is not equal to race position. however if you just want the data for yourself (lets say your "Current Sector Time" for your car your object called would look like this . MyCurrentSectorTime = uDP.ParticipantInfo[uDP.ViewedPlayerIndex,15].

Thanks, that's very helpful information!

Maskmagog
29-10-2018, 18:42
Hey Zeratall and other smart people: I would like some help decoding TrackLocation. My current project is a grand plan, with the final goal to get proper leaderboards to the console people! :) But one thing at the time. I have almost all UDP data I need through this library, except Track Location and Track Variation. I'll be really happy if someone could help me. Here's my best attempt:

In PCars2_UDP.cs I have the following:


const int TRACKNAME_LENGTH_MAX = 64;



private char[] _TrackLocation;


Later in same file:


TrackLocation = binaryReader.ReadChars(TRACKNAME_LENGTH_MAX);


And further down in the same file:


public char[] TrackLocation
{
get
{
return _TrackLocation;
}
set
{
_TrackLocation = value;
}
}



In program.cs file I try to retrieve it like this:


Console.WriteLine("Track is " + uDP.TrackLocation);


Running this a get something about "Exception: Can't read beyond end of stream" or similar.

Killg0re NL
23-03-2019, 19:41
Remember that the PacketBase contains 3 important values. mPartialPacketIndex, mPartialPacketNumber, mPacketType. Without those you can't decipher the udp packets correctly. Unless your library does that for the user, of course.

When i am using protocol version 1 (UDP size 1367), and i turn off/on the headlight in game, the carFlags the light flag is set instantly.

So when i am using the version 2 protocol, (UDP size 559) it takes a while before the carFlags (cfLight flag) is set. (about 4 sec)
Could it be that i am missing what 559 packet it is?

Sampo
27-03-2019, 22:51
I'm not sure what you mean. If the PacketBase struct at the start of the packet (sBase) has mPacketType of eCarPhysics (0), it should give you the current light state in sCarFlags. The length of the eCarPhysics struct type (sTelemetryData) is 556, btw. Have you tried changing the PC2 protocol update speed in the game settings?

Ouch. Just noticed that this thread is about the C# lib from Zeratall.