diff --git a/WpfApp1/DataHandle/DataAdapter.cs b/WpfApp1/DataHandle/DataAdapter.cs
new file mode 100644
index 0000000..80711b6
--- /dev/null
+++ b/WpfApp1/DataHandle/DataAdapter.cs
@@ -0,0 +1,110 @@
+using System;
+
+namespace F1Tools
+{
+ internal static class DataAdapter
+ {
+ public static LocalData AsLocalData(this Codemasters.F1_2019.Packet packet)
+ {
+ if (packet == null)
+ return null;
+
+ var result = new LocalData();
+ if (packet.PacketType == Codemasters.F1_2019.PacketType.CarTelemetry)
+ {
+ var curPack = packet as Codemasters.F1_2019.TelemetryPacket;
+ var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
+
+ result.Brake = data.Brake;
+ result.Throttle = data.Throttle;
+ result.SpeedKph = data.SpeedKph;
+ result.EngineRpm = data.EngineRpm;
+ result.Gear = data.Gear;
+ result.DrsActive = data.DrsActive;
+ }
+ else if (packet.PacketType == Codemasters.F1_2019.PacketType.CarStatus)
+ {
+ var curPack = packet as Codemasters.F1_2019.CarStatusPacket;
+ var data = curPack.FieldCarStatusData[0];
+
+ result.DrsAllowed = data.DrsAllowed;
+ }
+ return result;
+ }
+
+ public static LocalData AsLocalData(this Codemasters.F1_2020.Packet packet)
+ {
+ if (packet == null)
+ return null;
+
+ var result = new LocalData();
+ if (packet.PacketType == Codemasters.F1_2020.PacketType.CarTelemetry)
+ {
+ var curPack = packet as Codemasters.F1_2020.TelemetryPacket;
+ var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
+
+ result.Brake = data.Brake;
+ result.Throttle = data.Throttle;
+ result.SpeedKph = data.SpeedKph;
+ result.EngineRpm = data.EngineRpm;
+ result.Gear = data.Gear;
+ result.DrsActive = data.DrsActive;
+ }
+ else if (packet.PacketType == Codemasters.F1_2020.PacketType.CarStatus)
+ {
+ var curPack = packet as Codemasters.F1_2020.CarStatusPacket;
+ var data = curPack.FieldCarStatusData[0];
+
+ result.DrsAllowed = data.DrsAllowed;
+ result.DrsFailure = data.DrsFailure;
+ }
+ return result;
+ }
+
+ public static LocalData AsLocalData(this Codemasters.F1_2021.Packet packet)
+ {
+ if (packet == null)
+ return null;
+
+ var result = new LocalData();
+ if (packet.PacketType == Codemasters.F1_2021.PacketType.CarTelemetry)
+ {
+ var curPack = packet as Codemasters.F1_2021.TelemetryPacket;
+ var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
+
+ result.Brake = data.Brake;
+ result.Throttle = data.Throttle;
+ result.SpeedKph = data.SpeedKph;
+ result.EngineRpm = data.EngineRpm;
+ result.Gear = data.Gear;
+ result.DrsActive = data.DrsActive;
+ }
+ else if (packet.PacketType == Codemasters.F1_2021.PacketType.CarStatus)
+ {
+ var curPack = packet as Codemasters.F1_2021.CarStatusPacket;
+ var data = curPack.FieldCarStatusData[0];
+
+ result.DrsAllowed = data.DrsAllowed;
+ }
+ return result;
+ }
+
+ public static LocalData AsLocalData(this float[] fh5Data)
+ {
+ var result = new LocalData
+ {
+ Throttle = fh5Data[80] / 255F,
+ Brake = fh5Data[81] / 255F,
+ Clutch = fh5Data[82] / 255F,
+ Gear = (int)fh5Data[84],
+ EngineRpm = fh5Data[4],
+ SpeedKph = fh5Data[64] * 3.6F,
+ };
+ if (result.Gear == 0)
+ result.Gear = -1;
+ else if (result.Gear == 11)
+ result.Gear = 0;
+ return result;
+ }
+ }
+}
diff --git a/WpfApp1/DataHandle/DataReciver.cs b/WpfApp1/DataHandle/DataReciver.cs
index c10a500..e5e59a7 100644
--- a/WpfApp1/DataHandle/DataReciver.cs
+++ b/WpfApp1/DataHandle/DataReciver.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Sockets;
using static F1Tools.TypeFactory;
@@ -28,10 +29,11 @@ private static void MicroTimer_OnRunningCallback(int id, int msg, int user, int
var bytes = UDP.Receive(ref IP);
if (bytes.Length > 0)
{
- var packet = GetPacket(bytes, _version, out _version);
- if (_version == GameVersion.Unkonwn)
+ var data = GetData(bytes, _version, out _version);
+ if (_version == GameVersion.Unkonwn || data == null)
return;
- ReciveEvent?.Invoke(packet);
+ ReciveEvent?.Invoke(data);
+ //Console.WriteLine($"{data.Throttle} {data.Brake}");
}
}
@@ -56,7 +58,7 @@ public static void Dispose()
UDP.Dispose();
}
- public delegate void ReciverHandler(object packet);
+ public delegate void ReciverHandler(LocalData localData);
public static event ReciverHandler ReciveEvent;
}
}
diff --git a/WpfApp1/DataHandle/ShowDataHandle.cs b/WpfApp1/DataHandle/ShowDataHandle.cs
index a6f73a4..f17eabd 100644
--- a/WpfApp1/DataHandle/ShowDataHandle.cs
+++ b/WpfApp1/DataHandle/ShowDataHandle.cs
@@ -1,98 +1,27 @@
-using static F1Tools.TypeFactory;
-
-namespace F1Tools
+namespace F1Tools
{
public static class ShowDataHandle
{
- public static void F1Handle(F1Instrument f1, dynamic packet)
+ public static void F1Handle(F1Instrument f1, LocalData data)
{
- if (packet == null)
+ if (data == null)
return;
-
- switch (DataReciver.Version)
- {
- case GameVersion.F1_2019:
- Handle19(f1, packet);
- break;
- case GameVersion.F1_2020:
- Handle20(f1, packet);
- break;
- case GameVersion.F1_2021:
- Handle21(f1, packet);
- break;
- default:
- break;
- }
- }
-
- private static void Handle19(F1Instrument f1, Codemasters.F1_2019.Packet packet)
- {
- if (packet.PacketType == Codemasters.F1_2019.PacketType.CarTelemetry)
- {
- var curPack = packet as Codemasters.F1_2019.TelemetryPacket;
- var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
-
- f1.SetBrake(data.Brake);
- f1.SetThrottle(data.Throttle);
- f1.SetSpeed(data.SpeedKph);
- f1.SetRPM(data.EngineRpm);
- f1.SetGear(data.Gear);
- f1.SetDRS(data.DrsActive);
- }
- else if (packet.PacketType == Codemasters.F1_2019.PacketType.CarStatus)
- {
- var curPack = packet as Codemasters.F1_2019.CarStatusPacket;
- var data = curPack.FieldCarStatusData[0];
-
- f1.DRSEnable(data.DrsAllowed);
- }
- }
-
- private static void Handle20(F1Instrument f1, Codemasters.F1_2020.Packet packet)
- {
- if (packet.PacketType == Codemasters.F1_2020.PacketType.CarTelemetry)
- {
- var curPack = packet as Codemasters.F1_2020.TelemetryPacket;
- var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
-
- f1.SetBrake(data.Brake);
- f1.SetThrottle(data.Throttle);
- f1.SetSpeed(data.SpeedKph);
- f1.SetRPM(data.EngineRpm);
- f1.SetGear(data.Gear);
- f1.SetDRS(data.DrsActive);
- }
- else if (packet.PacketType == Codemasters.F1_2020.PacketType.CarStatus)
- {
- var curPack = packet as Codemasters.F1_2020.CarStatusPacket;
- var data = curPack.FieldCarStatusData[0];
-
- f1.DRSEnable(data.DrsAllowed);
- f1.DRSNegative(data.DrsFailure);
- }
- }
-
- private static void Handle21(F1Instrument f1, Codemasters.F1_2021.Packet packet)
- {
- if (packet.PacketType == Codemasters.F1_2021.PacketType.CarTelemetry)
- {
- var curPack = packet as Codemasters.F1_2021.TelemetryPacket;
- var data = curPack.FieldTelemetryData[curPack.PlayerCarIndex];
-
- f1.SetBrake(data.Brake);
- f1.SetThrottle(data.Throttle);
- f1.SetSpeed(data.SpeedKph);
- f1.SetRPM(data.EngineRpm);
- f1.SetGear(data.Gear);
- f1.SetDRS(data.DrsActive);
- }
- else if (packet.PacketType == Codemasters.F1_2021.PacketType.CarStatus)
- {
- var curPack = packet as Codemasters.F1_2021.CarStatusPacket;
- var data = curPack.FieldCarStatusData[0];
-
- f1.DRSEnable(data.DrsAllowed);
- }
+ if (data.Brake.HasValue)
+ f1.SetBrake(data.Brake.Value);
+ if (data.Throttle.HasValue)
+ f1.SetThrottle(data.Throttle.Value);
+ if (data.SpeedKph.HasValue)
+ f1.SetSpeed((int)data.SpeedKph.Value);
+ if (data.EngineRpm.HasValue)
+ f1.SetRPM((int)data.EngineRpm.Value);
+ if (data.Gear.HasValue)
+ f1.SetGear(data.Gear.Value);
+ if (data.DrsActive.HasValue)
+ f1.SetDRS(data.DrsActive.Value);
+ if (data.DrsAllowed.HasValue)
+ f1.DRSEnable(data.DrsAllowed.Value);
+ if (data.DrsFailure.HasValue)
+ f1.DRSNegative(data.DrsFailure.Value);
}
}
}
diff --git a/WpfApp1/DataHandle/TypeFactory.cs b/WpfApp1/DataHandle/TypeFactory.cs
index ed20457..656a54c 100644
--- a/WpfApp1/DataHandle/TypeFactory.cs
+++ b/WpfApp1/DataHandle/TypeFactory.cs
@@ -4,21 +4,24 @@ namespace F1Tools
{
public class TypeFactory
{
- public static object GetPacket(byte[] bytes, GameVersion version, out GameVersion outVersion)
+ public static LocalData GetData(byte[] bytes, GameVersion version, out GameVersion outVersion)
{
if (version != GameVersion.Unkonwn)
{
switch (version)
{
case GameVersion.F1_2019:
- outVersion = GetPacket2019(bytes, out Codemasters.F1_2019.Packet packet19) ? GameVersion.F1_2019 : GameVersion.Unkonwn;
- return packet19;
+ outVersion = F1.GetPacket2019(bytes, out Codemasters.F1_2019.Packet packet19) ? GameVersion.F1_2019 : GameVersion.Unkonwn;
+ return packet19.AsLocalData();
case GameVersion.F1_2020:
- outVersion = GetPacket2020(bytes, out Codemasters.F1_2020.Packet packet20) ? GameVersion.F1_2020 : GameVersion.Unkonwn;
- return packet20;
+ outVersion = F1.GetPacket2020(bytes, out Codemasters.F1_2020.Packet packet20) ? GameVersion.F1_2020 : GameVersion.Unkonwn;
+ return packet20.AsLocalData();
case GameVersion.F1_2021:
- outVersion = GetPacket2021(bytes, out Codemasters.F1_2021.Packet packet21) ? GameVersion.F1_2021 : GameVersion.Unkonwn;
- return packet21;
+ outVersion = F1.GetPacket2021(bytes, out Codemasters.F1_2021.Packet packet21) ? GameVersion.F1_2021 : GameVersion.Unkonwn;
+ return packet21.AsLocalData();
+ case GameVersion.Horizon5:
+ outVersion = FH5.GetFh5Data(bytes, out float[] data) ? GameVersion.Horizon5 : GameVersion.Unkonwn;
+ return data.AsLocalData();
default:
outVersion = GameVersion.Unkonwn;
return null;
@@ -26,172 +29,9 @@ public static object GetPacket(byte[] bytes, GameVersion version, out GameVersio
}
else
{
- if (GetPacket2019(bytes, out Codemasters.F1_2019.Packet packet19))
- {
- outVersion = GameVersion.F1_2019;
- return packet19;
- }
- else if (GetPacket2020(bytes, out Codemasters.F1_2020.Packet packet20))
- {
- outVersion = GameVersion.F1_2020;
- return packet20;
- }
- else if (GetPacket2021(bytes, out Codemasters.F1_2021.Packet packet21))
- {
- outVersion = GameVersion.F1_2021;
- return packet21;
- }
- else
- {
- outVersion = GameVersion.Unkonwn;
- return null;
- }
- }
- }
-
- public static bool GetPacket2019(byte[] bytes, out Codemasters.F1_2019.Packet packet)
- {
- packet = null;
- try
- {
- var type = Codemasters.F1_2019.CodemastersToolkit.GetPacketType(bytes);
-
- switch (type)
- {
- case Codemasters.F1_2019.PacketType.CarStatus:
- packet = new Codemasters.F1_2019.CarStatusPacket();
- break;
- case Codemasters.F1_2019.PacketType.CarTelemetry:
- packet = new Codemasters.F1_2019.TelemetryPacket();
- break;
- //case PacketType.FinalClassification:
- // pack = new FinalClassificationPacket();
- // break;
- //case PacketType.Lap:
- // pack = new LapPacket();
- // break;
- //case PacketType.LobbyInfo:
- // pack = new LobbyInfoPacket();
- // break;
- //case PacketType.Motion:
- // pack = new MotionPacket();
- // break;
- case Codemasters.F1_2019.PacketType.Participants:
- packet = new Codemasters.F1_2019.ParticipantPacket();
- break;
- //case Codemasters.F1_2019.PacketType.Session:
- // pack = new SessionPacket();
- // break;
- default: break;
- }
-
- if (packet != null)
- packet.LoadBytes(bytes);
-
- return true;
- }
- catch (Exception ex)
- {
- return false;
- }
- }
-
- public static bool GetPacket2020(byte[] bytes, out Codemasters.F1_2020.Packet packet)
- {
- packet = null;
- try
- {
- var type = Codemasters.F1_2020.CodemastersToolkit.GetPacketType(bytes);
-
- switch (type)
- {
- case Codemasters.F1_2020.PacketType.CarStatus:
- packet = new Codemasters.F1_2020.CarStatusPacket();
- break;
- case Codemasters.F1_2020.PacketType.CarTelemetry:
- packet = new Codemasters.F1_2020.TelemetryPacket();
- break;
- //case PacketType.FinalClassification:
- // pack = new FinalClassificationPacket();
- // break;
- //case PacketType.Lap:
- // pack = new LapPacket();
- // break;
- //case PacketType.LobbyInfo:
- // pack = new LobbyInfoPacket();
- // break;
- //case PacketType.Motion:
- // pack = new MotionPacket();
- // break;
- case Codemasters.F1_2020.PacketType.Participants:
- packet = new Codemasters.F1_2020.ParticipantPacket();
- break;
- //case PacketType.Session:
- // pack = new SessionPacket();
- // break;
- default: break;
- }
-
- if (packet != null)
- packet.LoadBytes(bytes);
- return true;
+ outVersion = Helper.GetGameVersion(bytes);
+ return null;
}
- catch (Exception ex)
- {
- return false;
- }
- }
-
- public static bool GetPacket2021(byte[] bytes, out Codemasters.F1_2021.Packet packet)
- {
- packet = null;
- try
- {
- var type = Codemasters.F1_2021.CodemastersToolkit.GetPacketType(bytes);
-
- switch (type)
- {
- case Codemasters.F1_2021.PacketType.CarStatus:
- packet = new Codemasters.F1_2021.CarStatusPacket();
- break;
- case Codemasters.F1_2021.PacketType.CarTelemetry:
- packet = new Codemasters.F1_2021.TelemetryPacket();
- break;
- //case PacketType.FinalClassification:
- // pack = new FinalClassificationPacket();
- // break;
- //case PacketType.Lap:
- // pack = new LapPacket();
- // break;
- //case PacketType.LobbyInfo:
- // pack = new LobbyInfoPacket();
- // break;
- //case PacketType.Motion:
- // pack = new MotionPacket();
- // break;
- case Codemasters.F1_2021.PacketType.Participants:
- packet = new Codemasters.F1_2021.ParticipantPacket();
- break;
- //case PacketType.Session:
- // pack = new SessionPacket();
- // break;
- default: break;
- }
-
- if (packet != null)
- packet.LoadBytes(bytes);
-
- return true;
- }
- catch (Exception ex)
- {
- return false;
- }
- }
-
- public enum GameVersion
- {
- F1_2019, F1_2020, F1_2021, Unkonwn
}
}
}
diff --git a/WpfApp1/F1/F1.cs b/WpfApp1/F1/F1.cs
new file mode 100644
index 0000000..0c9d67e
--- /dev/null
+++ b/WpfApp1/F1/F1.cs
@@ -0,0 +1,149 @@
+using System;
+
+namespace F1Tools
+{
+ public static class F1
+ {
+
+
+ public static bool GetPacket2019(byte[] bytes, out Codemasters.F1_2019.Packet packet)
+ {
+ packet = null;
+ try
+ {
+ var type = Codemasters.F1_2019.CodemastersToolkit.GetPacketType(bytes);
+
+ switch (type)
+ {
+ case Codemasters.F1_2019.PacketType.CarStatus:
+ packet = new Codemasters.F1_2019.CarStatusPacket();
+ break;
+ case Codemasters.F1_2019.PacketType.CarTelemetry:
+ packet = new Codemasters.F1_2019.TelemetryPacket();
+ break;
+ //case PacketType.FinalClassification:
+ // pack = new FinalClassificationPacket();
+ // break;
+ //case PacketType.Lap:
+ // pack = new LapPacket();
+ // break;
+ //case PacketType.LobbyInfo:
+ // pack = new LobbyInfoPacket();
+ // break;
+ //case PacketType.Motion:
+ // pack = new MotionPacket();
+ // break;
+ //case Codemasters.F1_2019.PacketType.Participants:
+ // packet = new Codemasters.F1_2019.ParticipantPacket();
+ // break;
+ //case Codemasters.F1_2019.PacketType.Session:
+ // pack = new SessionPacket();
+ // break;
+ default: break;
+ }
+
+ if (packet != null)
+ packet.LoadBytes(bytes);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ public static bool GetPacket2020(byte[] bytes, out Codemasters.F1_2020.Packet packet)
+ {
+ packet = null;
+ try
+ {
+ var type = Codemasters.F1_2020.CodemastersToolkit.GetPacketType(bytes);
+
+ switch (type)
+ {
+ case Codemasters.F1_2020.PacketType.CarStatus:
+ packet = new Codemasters.F1_2020.CarStatusPacket();
+ break;
+ case Codemasters.F1_2020.PacketType.CarTelemetry:
+ packet = new Codemasters.F1_2020.TelemetryPacket();
+ break;
+ //case PacketType.FinalClassification:
+ // pack = new FinalClassificationPacket();
+ // break;
+ //case PacketType.Lap:
+ // pack = new LapPacket();
+ // break;
+ //case PacketType.LobbyInfo:
+ // pack = new LobbyInfoPacket();
+ // break;
+ //case PacketType.Motion:
+ // pack = new MotionPacket();
+ // break;
+ //case Codemasters.F1_2020.PacketType.Participants:
+ // packet = new Codemasters.F1_2020.ParticipantPacket();
+ // break;
+ //case PacketType.Session:
+ // pack = new SessionPacket();
+ // break;
+ default: break;
+ }
+
+ if (packet != null)
+ packet.LoadBytes(bytes);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ public static bool GetPacket2021(byte[] bytes, out Codemasters.F1_2021.Packet packet)
+ {
+ packet = null;
+ try
+ {
+ var type = Codemasters.F1_2021.CodemastersToolkit.GetPacketType(bytes);
+
+ switch (type)
+ {
+ case Codemasters.F1_2021.PacketType.CarStatus:
+ packet = new Codemasters.F1_2021.CarStatusPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.CarTelemetry:
+ packet = new Codemasters.F1_2021.TelemetryPacket();
+ break;
+ //case PacketType.FinalClassification:
+ // pack = new FinalClassificationPacket();
+ // break;
+ //case PacketType.Lap:
+ // pack = new LapPacket();
+ // break;
+ //case PacketType.LobbyInfo:
+ // pack = new LobbyInfoPacket();
+ // break;
+ //case PacketType.Motion:
+ // pack = new MotionPacket();
+ // break;
+ //case Codemasters.F1_2021.PacketType.Participants:
+ // packet = new Codemasters.F1_2021.ParticipantPacket();
+ // break;
+ //case PacketType.Session:
+ // pack = new SessionPacket();
+ // break;
+ default: break;
+ }
+
+ if (packet != null)
+ packet.LoadBytes(bytes);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/WpfApp1/F1Instrument.xaml.cs b/WpfApp1/F1Instrument.xaml.cs
index 62fe629..82c6482 100644
--- a/WpfApp1/F1Instrument.xaml.cs
+++ b/WpfApp1/F1Instrument.xaml.cs
@@ -45,12 +45,12 @@ public partial class F1Instrument : UserControl
private DoubleAnimation sizeBigAn = new DoubleAnimation
{
From = 50,
- To = 90,
+ To = 80,
Duration = TimeSpan.FromMilliseconds(300)
};
private DoubleAnimation sizeSmln = new DoubleAnimation
{
- From = 90,
+ From = 80,
To = 50,
Duration = TimeSpan.FromMilliseconds(300)
};
@@ -92,7 +92,7 @@ public F1Instrument()
DRSNegative(false);
lb_DRS.Foreground = new SolidColorBrush(Colors.White);
-
+
lb_R.Foreground = new SolidColorBrush(Colors.Gray);
lb_N.Foreground = new SolidColorBrush(Colors.Gray);
lb_1.Foreground = new SolidColorBrush(Colors.Gray);
@@ -111,11 +111,15 @@ public F1Instrument()
public void SetThrottle(float thr)
{
+ thr = thr < 0 ? 0 : thr;
+ thr = thr > 1 ? 1 : thr;
arc_tr.EndAngle = 128 + ((307 - 128) * thr);
}
public void SetBrake(float bre)
{
+ bre = bre < 0 ? 0 : bre;
+ bre = bre > 1 ? 1 : bre;
arc_break.EndAngle = 410 - ((410 - 311) * bre);
}
@@ -123,8 +127,10 @@ public void SetSpeed(int sp)
{
if (SPEED != sp)
{
- arc_speed.EndAngle = ((421 - 120) * (sp / 360.0)) + 120;
lb_speed.Content = sp.ToString();
+ sp = sp > 360 ? 360 : sp;
+ arc_speed.EndAngle = ((421 - 120) * (sp / 360.0)) + 120;
+
SPEED = sp;
}
}
@@ -154,7 +160,7 @@ public void DRSEnable(bool enable)
{
if (DRS_Ena != enable)
{
- if(enable)
+ if (enable)
lb_DRS.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, DRS_Enable_Ac);
else
lb_DRS.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, DRS_Disable_Ac);
diff --git a/WpfApp1/F1_2020_Tools.csproj b/WpfApp1/F1_2020_Tools.csproj
index aa6729b..f5f62aa 100644
--- a/WpfApp1/F1_2020_Tools.csproj
+++ b/WpfApp1/F1_2020_Tools.csproj
@@ -231,10 +231,17 @@
MSBuild:Compile
Designer
+
+
+
+
+
+
+
True
diff --git a/WpfApp1/FH5/FH5.cs b/WpfApp1/FH5/FH5.cs
new file mode 100644
index 0000000..6ad803d
--- /dev/null
+++ b/WpfApp1/FH5/FH5.cs
@@ -0,0 +1,54 @@
+using F1Tools.Models;
+using System;
+
+namespace F1Tools
+{
+ public class FH5
+ {
+ public static bool GetFh5Data(byte[] bytes, out float[] data)
+ {
+ data = new float[100];
+
+ if (bytes.Length != 324)
+ return false;
+ try
+ {
+ int index = 0;
+ int arrayIndex = 0;
+ foreach (var item in FH5Format.FH5FormatData)
+ {
+ switch (item.Type)
+ {
+ case "Int32":
+ data[arrayIndex] = BitConverter.ToInt32(bytes, index);
+ index += item.Size; arrayIndex++;
+ break;
+ case "float":
+ data[arrayIndex] = BitConverter.ToSingle(bytes, index);
+ index += item.Size; arrayIndex++;
+ break;
+ case "bool":
+ data[arrayIndex] = BitConverter.ToInt32(bytes, index);
+ index += item.Size; arrayIndex++;
+ break;
+ case "UInt16":
+ data[arrayIndex] = BitConverter.ToUInt16(bytes, index);
+ index += item.Size; arrayIndex++;
+ break;
+ case "uint8":
+ data[arrayIndex] = bytes[index];
+ index += item.Size; arrayIndex++;
+ break;
+ default: break;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/WpfApp1/FH5/FH5Format.cs b/WpfApp1/FH5/FH5Format.cs
new file mode 100644
index 0000000..e5ad75b
--- /dev/null
+++ b/WpfApp1/FH5/FH5Format.cs
@@ -0,0 +1,115 @@
+using System.Collections.Generic;
+
+namespace F1Tools.Models
+{
+ public class FH5Unit
+ {
+ public int Size;
+ public string Type;
+ public string Name;
+
+ public FH5Unit(int size, string type, string name)
+ {
+ Size = size;
+ Type = type;
+ Name = name;
+ }
+ }
+
+
+ public class FH5Format : List
+ {
+
+ public static FH5Format FH5FormatData = new FH5Format
+ {
+ new FH5Unit(4,"Int32","IsRaceOn"),// = 1 when race is on. = 0 when in menus/race stopped
+ new FH5Unit(4,"Int32","TimestampMS"),//Can overflow to 0 eventually
+ new FH5Unit(4,"float","EngineMaxRpm"),
+ new FH5Unit(4,"float","EngineIdleRpm"),
+ new FH5Unit(4,"float","CurrentEngineRpm"),
+ new FH5Unit(4,"float","AccelerationX"),//In the car's local space; X = right, Y = up, Z = forward
+ new FH5Unit(4,"float","AccelerationY"),
+ new FH5Unit(4,"float","AccelerationZ"),
+ new FH5Unit(4,"float","VelocityX"),
+ new FH5Unit(4,"float","VelocityY"),
+ new FH5Unit(4,"float","VelocityZ"),
+ new FH5Unit(4,"float","AngularVelocityX"),
+ new FH5Unit(4,"float","AngularVelocityY"),
+ new FH5Unit(4,"float","AngularVelocityZ"),
+ new FH5Unit(4,"float","Yaw"),
+ new FH5Unit(4,"float","Pitch"),
+ new FH5Unit(4,"float","Roll"),
+ new FH5Unit(4,"float","NormalizedSuspensionTravelFrontLeft"),// Suspension travel normalized: 0.0f = max stretch; 1.0 = max compression
+ new FH5Unit(4,"float","NormalizedSuspensionTravelFrontRight"),
+ new FH5Unit(4,"float","NormalizedSuspensionTravelRearLeft"),
+ new FH5Unit(4,"float","NormalizedSuspensionTravelRearRight"),
+ new FH5Unit(4,"float","TireSlipRatioFrontLeft"),// Tire normalized slip ratio, = 0 means 100% grip and |ratio| > 1.0 means loss of grip. THis is longitudinal slip or just spin
+ new FH5Unit(4,"float","TireSlipRatioFrontRight"),
+ new FH5Unit(4,"float","TireSlipRatioRearLeft"),
+ new FH5Unit(4,"float","TireSlipRatioRearRight"),
+ new FH5Unit(4,"float","WheelRotationSpeedFrontLeft"),// Wheel rotation speed radians/sec.
+ new FH5Unit(4,"float","WheelRotationSpeedFrontRight"),
+ new FH5Unit(4,"float","WheelRotationSpeedRearLeft"),
+ new FH5Unit(4,"float","WheelRotationSpeedRearRight"),
+ new FH5Unit(4,"bool","WheelOnRumbleStripFrontLeft"),// = 1 when wheel is on rumble strip, = 0 when off.
+ new FH5Unit(4,"bool","WheelOnRumbleStripFrontRight"),
+ new FH5Unit(4,"bool","WheelOnRumbleStripRearLeft"),
+ new FH5Unit(4,"bool","WheelOnRumbleStripRearRight"),
+ new FH5Unit(4,"bool","WheelInPuddleDepthFrontLeft"),// = from 0 to 1, where 1 is the deepest puddle
+ new FH5Unit(4,"bool","WheelInPuddleDepthFrontRight"),
+ new FH5Unit(4,"bool","WheelInPuddleDepthRearLeft"),
+ new FH5Unit(4,"bool","WheelInPuddleDepthRearRight"),
+ new FH5Unit(4,"float","SurfaceRumbleFrontLeft"),// Non-dimensional surface rumble values passed to controller force feedback
+ new FH5Unit(4,"float","SurfaceRumbleFrontRight"),
+ new FH5Unit(4,"float","SurfaceRumbleRearLeft"),
+ new FH5Unit(4,"float","SurfaceRumbleRearRight"),
+ new FH5Unit(4,"float","TireSlipAngleFrontLeft"),// Tire normalized slip angle, = 0 means 100% grip and |angle| > 1.0 means loss of grip. This is lateral tire slip angle (not the same as wheel angle)
+ new FH5Unit(4,"float","TireSlipAngleFrontRight"),
+ new FH5Unit(4,"float","TireSlipAngleRearLeft"),
+ new FH5Unit(4,"float","TireSlipAngleRearRight"),
+ new FH5Unit(4,"float","TireCombinedSlipFrontLeft"),// Tire normalized combined slip, = 0 means 100% grip and |slip| > 1.0 means loss of grip. This is a combination of TireSlipRatioFrontLeft and TireSlipAngleFrontLeft.
+ new FH5Unit(4,"float","TireCombinedSlipFrontRight"),
+ new FH5Unit(4,"float","TireCombinedSlipRearLeft"),
+ new FH5Unit(4,"float","TireCombinedSlipRearRight"),
+ new FH5Unit(4,"float","SuspensionTravelMetersFrontLeft"),// Actual suspension travel in meters
+ new FH5Unit(4,"float","SuspensionTravelMetersFrontRight"),
+ new FH5Unit(4,"float","SuspensionTravelMetersRearLeft"),
+ new FH5Unit(4,"float","SuspensionTravelMetersRearRight"),
+ new FH5Unit(4,"Int32","CarOrdinal"),//Unique ID of the car make/model
+ new FH5Unit(4,"Int32","CarClass"),//Between 0 (D -- worst cars) and 7 (X class -- best cars) inclusive
+ new FH5Unit(4,"Int32","CarPerformanceIndex"),//Between 100 (slowest car) and 999 (fastest car) inclusive
+ new FH5Unit(4,"Int32","DrivetrainType"),//Corresponds to EDrivetrainType; 0 = FWD, 1 = RWD, 2 = AWD
+ new FH5Unit(4,"Int32","NumCylinders"),//Number of cylinders in the engine
+ new FH5Unit(4,"Int32","CarCategory"),
+ new FH5Unit(4,"Int32","unknown"),// > 0 when crashing into objects
+ new FH5Unit(4,"Int32","unknown"),// > 0 when crashing into objects
+ new FH5Unit(4,"float","PositionX"),
+ new FH5Unit(4,"float","PositionY"),
+ new FH5Unit(4,"float","PositionZ"),
+ new FH5Unit(4,"float","Speed"),// in meters per second
+ new FH5Unit(4,"float","Power"),// in watts
+ new FH5Unit(4,"float","Torque"),// newton meter
+ new FH5Unit(4,"float","TireTemperatureFrontLeft"),// °F
+ new FH5Unit(4,"float","TireTemperatureFrontRight"),
+ new FH5Unit(4,"float","TireTemperatureRearLeft"),
+ new FH5Unit(4,"float","TireTemperatureRearRight"),
+ new FH5Unit(4,"float","Boost"),
+ new FH5Unit(4,"float","Fuel"),
+ new FH5Unit(4,"float","DistanceTraveled"),
+ new FH5Unit(4,"float","BestLap"),
+ new FH5Unit(4,"float","LastLap"),
+ new FH5Unit(4,"float","CurrentLap"),
+ new FH5Unit(4,"float","CurrentRaceTime"),
+ new FH5Unit(2,"UInt16","LapNumber"),
+ new FH5Unit(1,"uint8","RacePosition"),
+ new FH5Unit(1,"uint8","Throttle"),// /255
+ new FH5Unit(1,"uint8","Brake"),// /255
+ new FH5Unit(1,"uint8","Clutch"),// /25// /2555
+ new FH5Unit(1,"uint8","HandBrake"),
+ new FH5Unit(1,"uint8","Gear"),
+ new FH5Unit(1,"uint8","Steer"),// /255
+ new FH5Unit(1,"uint8","NormalizedDrivingLine"),
+ new FH5Unit(1,"uint8","NormalizedAIBrakeDifference")
+ };
+ }
+}
diff --git a/WpfApp1/Helper/ConsoleManager.cs b/WpfApp1/Helper/ConsoleManager.cs
new file mode 100644
index 0000000..036e96d
--- /dev/null
+++ b/WpfApp1/Helper/ConsoleManager.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace F1Tools
+{
+ public static class ConsoleManager
+ {
+ private const string Kernel32_DllName = "kernel32.dll";
+
+ [DllImport(Kernel32_DllName)]
+ private static extern bool AllocConsole();
+
+ [DllImport(Kernel32_DllName)]
+ private static extern bool FreeConsole();
+
+ [DllImport(Kernel32_DllName)]
+ private static extern IntPtr GetConsoleWindow();
+
+ [DllImport(Kernel32_DllName)]
+ private static extern int GetConsoleOutputCP();
+
+ public static bool HasConsole
+ {
+ get { return GetConsoleWindow() != IntPtr.Zero; }
+ }
+
+ ///
+ /// Creates a new console instance if the process is not attached to a console already.
+ ///
+ public static void Show()
+ {
+ //#if DEBUG
+ if (!HasConsole)
+ {
+ AllocConsole();
+ InvalidateOutAndError();
+ }
+ //#endif
+ }
+
+ ///
+ /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
+ ///
+ public static void Hide()
+ {
+ //#if DEBUG
+ if (HasConsole)
+ {
+ SetOutAndErrorNull();
+ FreeConsole();
+ }
+ //#endif
+ }
+
+ public static void Toggle()
+ {
+ if (HasConsole)
+ {
+ Hide();
+ }
+ else
+ {
+ Show();
+ }
+ }
+
+ static void InvalidateOutAndError()
+ {
+ Type type = typeof(System.Console);
+
+ System.Reflection.FieldInfo _out = type.GetField("_out",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ System.Reflection.FieldInfo _error = type.GetField("_error",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ Debug.Assert(_out != null);
+ Debug.Assert(_error != null);
+
+ Debug.Assert(_InitializeStdOutError != null);
+
+ _out.SetValue(null, null);
+ _error.SetValue(null, null);
+
+ _InitializeStdOutError.Invoke(null, new object[] { true });
+ }
+
+ static void SetOutAndErrorNull()
+ {
+ Console.SetOut(TextWriter.Null);
+ Console.SetError(TextWriter.Null);
+ }
+ }
+}
diff --git a/WpfApp1/Helper/Helper.cs b/WpfApp1/Helper/Helper.cs
index d697017..20b571e 100644
--- a/WpfApp1/Helper/Helper.cs
+++ b/WpfApp1/Helper/Helper.cs
@@ -11,6 +11,66 @@ namespace F1Tools
{
public static class Helper
{
+
+ public static GameVersion GetGameVersion(byte[] bytes)
+ {
+ if (bytes.Length == 324)
+ return GameVersion.Horizon5;
+
+ try
+ {
+ Codemasters.F1_2021.Packet packet = null;
+ var type = Codemasters.F1_2021.CodemastersToolkit.GetPacketType(bytes);
+ switch (type)
+ {
+ case Codemasters.F1_2021.PacketType.CarStatus:
+ packet = new Codemasters.F1_2021.CarStatusPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.CarTelemetry:
+ packet = new Codemasters.F1_2021.TelemetryPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.FinalClassification:
+ packet = new Codemasters.F1_2021.FinalClassificationPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.Lap:
+ packet = new Codemasters.F1_2021.LapPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.LobbyInfo:
+ packet = new Codemasters.F1_2021.LobbyInfoPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.Motion:
+ packet = new Codemasters.F1_2021.MotionPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.Participants:
+ packet = new Codemasters.F1_2021.ParticipantPacket();
+ break;
+ case Codemasters.F1_2021.PacketType.Session:
+ packet = new Codemasters.F1_2021.SessionPacket();
+ break;
+ default: break;
+ }
+
+ if (packet != null)
+ packet.LoadBytes(bytes);
+
+ switch (packet?.PacketFormat)
+ {
+ case 2019:
+ return GameVersion.F1_2019;
+ case 2020:
+ return GameVersion.F1_2020;
+ case 2021:
+ return GameVersion.F1_2021;
+ default:
+ return GameVersion.Unkonwn;
+ }
+ }
+ catch
+ {
+ return GameVersion.Unkonwn;
+ }
+ }
+
public static string GetIP()
{
string hostName = Dns.GetHostName();//本机名
diff --git a/WpfApp1/MainWindow.xaml.cs b/WpfApp1/MainWindow.xaml.cs
index 004fee9..b7ef099 100644
--- a/WpfApp1/MainWindow.xaml.cs
+++ b/WpfApp1/MainWindow.xaml.cs
@@ -1,6 +1,7 @@
using Codemasters.F1_2019;
using Codemasters.F1_2020;
using Codemasters.F1_2021;
+using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -23,6 +24,8 @@ public MainWindow()
{
InitializeComponent();
+ //ConsoleManager.Show();
+
DataReciver.ReciveEvent += DataReciver_ReciveEvent;
var ip = Helper.GetLocalIP();
lb_ip.Content = $"当前IP:{ip}";
@@ -69,9 +72,9 @@ private void HideIP()
}
#region F1 Data Processor
- private delegate void F1InstrumentDelegate(F1Instrument f1, object packet);
+ private delegate void F1InstrumentDelegate(F1Instrument f1, LocalData packet);
- private void DataReciver_ReciveEvent(object packet)
+ private void DataReciver_ReciveEvent(LocalData packet)
{
f1.Dispatcher.Invoke(new F1InstrumentDelegate(ShowDataHandle.F1Handle), f1, packet);
if (sp_ip.Visibility != Visibility.Hidden)
diff --git a/WpfApp1/Models/GameVersion.cs b/WpfApp1/Models/GameVersion.cs
new file mode 100644
index 0000000..d792ce4
--- /dev/null
+++ b/WpfApp1/Models/GameVersion.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace F1Tools
+{
+ public enum GameVersion
+ {
+ F1_2019, F1_2020, F1_2021, Unkonwn, Horizon5
+ }
+}
diff --git a/WpfApp1/Models/LocalData.cs b/WpfApp1/Models/LocalData.cs
new file mode 100644
index 0000000..ad285eb
--- /dev/null
+++ b/WpfApp1/Models/LocalData.cs
@@ -0,0 +1,17 @@
+namespace F1Tools
+{
+ public class LocalData
+ {
+ public bool? DrsFailure;
+ public bool? DrsAllowed;
+ public bool? DrsActive;
+
+ public float? Throttle;
+ public float? Brake;
+ public float? Clutch;
+ public float? HandBrake;
+ public float? SpeedKph;
+ public float? EngineRpm;
+ public int? Gear;
+ }
+}
diff --git a/WpfApp1/Properties/AssemblyInfo.cs b/WpfApp1/Properties/AssemblyInfo.cs
index 310204d..971cbf3 100644
--- a/WpfApp1/Properties/AssemblyInfo.cs
+++ b/WpfApp1/Properties/AssemblyInfo.cs
@@ -50,5 +50,5 @@
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
-[assembly: AssemblyVersion("2.4.3.0")]
+[assembly: AssemblyVersion("2.5.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]