001/*
002 *  $Rev: 1020 $:     Revision of last commit
003 *  $Author: tgutwin $:  Author of last commit
004 *  $Date: 2015-10-28 15:59:29 -0700 (Wed, 28 Oct 2015) $:    Date of last commit
005 *  $URL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/F1TelemetryPacket.java $
006 */
007/*
008 *
009 *  Written by Tom Gutwin - WebARTS Design.
010 *  Copyright (C) 2015 WebARTS Design, North Vancouver Canada
011 *  http://www.webarts.bc.ca
012 *
013 *  This program is free software; you can redistribute it and/or modify
014 *  it under the terms of the GNU General Public License as published by
015 *  the Free Software Foundation; either version 2 of the License, or
016 *  (at your option) any later version.
017 *
018 *  This program is distributed in the hope that it will be useful,
019 *  but WITHOUT ANY WARRANTY; without_ even the implied warranty of
020 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
021 *  GNU General Public License for more details.
022 *
023 *  You should have received a copy of the GNU General Public License
024 *  along with this program; if not, write to the Free Software
025 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
026 */
027
028package ca.bc.webarts.tools;
029
030import java.io.*;
031import java.nio.ByteBuffer;
032import java.nio.FloatBuffer;
033import java.nio.ByteOrder;
034import java.net.*;
035
036/** A Java Class that wraps the F1 Telemetry Packet.
037  * It Splits the data packet into useable variables.<br>
038  * As of this coding, it handles 252 bytes or 63 floats for the F1 2012 game packet.<br>
039  * the F1 2013 game spits back 66 floats or 264 bytes.
040  * <br> I think this is controlled by the extradata="3" attribute on the xml config done on the game config file.
041  *
042  * See more at: http://www.robertgray.net.au/posts/codemasters-f1-data-feed-updated
043  *<br>
044  * <p>The packet F1 2011 puts out through this contains the following fields in order.&nbsp; All fields are
045  * <span>float </span>datatype </p>
046  * <table style="width: 900px;" border="1" cellpadding="2" cellspacing="0">
047  * <tbody>
048  * <tr>
049  * <td valign="top" width="200"><span>Field</span></td>
050  * <td valign="top" width="700"><span>Description</span></td>
051  * </tr>
052  * <tr>
053  * <td valign="top" width="200"><span>Lap</span></td>
054  * <td valign="top" width="700">
055  * <p>The number of laps since the session began.</p>
056  * <p>Restarting a Session in the game will set this back to 0.</p>
057  * </td>
058  * </tr>
059  * <tr>
060  * <td valign="top" width="200">Time</td>
061  * <td valign="top" width="700">
062  * <p>Time in seconds since this telemetry session began</p>
063  * <p>Restarting a Session in the game will set this back to 0.</p>
064  * </td>
065  * </tr>
066  * <tr>
067  * <td valign="top" width="200">LapTime</td>
068  * <td valign="top" width="700">Time in seconds since the lap began. F1 2012 has a capture/send rate of 60 telemetry
069  * packets per second. &nbsp;This is 0 for an 'out lap'</td>
070  * </tr>
071  * <tr>
072  * <td valign="top" width="200">LapDistance</td>
073  * <td valign="top" width="700">The distance in meters since the lap began. &nbsp;This can be negative for 'out' laps.
074  *  &nbsp;If you cross the start finish line and then reverse back over it the LapDistance will shoot back up buytbut
075  *  the Lap will stay the same</td>
076  * </tr>
077  * <tr>
078  * <td valign="top" width="200">Distance</td>
079  * <td valign="top" width="700">
080  * <p>The laps and percent of laps covered since the session began.</p>
081  * <p>The value is negative when you first enter a practice session. &nbsp;After you cross the start finish line for
082  *  the first time it becomes positive (0). &nbsp;A value of 1.5 would indicate you're halfway through your second lap.
083  *  &nbsp;1.995 would indicate you're almost finished your second lap.</p>
084  * </td>
085  * </tr>
086  * <tr>
087  * <td valign="top" width="200">X</td>
088  * <td valign="top" width="700">The X position of the car in the world</td>
089  * </tr>
090  * <tr>
091  * <td valign="top" width="200">Y</td>
092  * <td valign="top" width="700">The Y position of the car in the world</td>
093  * </tr>
094  * <tr>
095  * <td valign="top" width="200">Z</td>
096  * <td valign="top" width="700">The Z position of the car in the world</td>
097  * </tr>
098  * <tr>
099  * <td valign="top" width="200">Speed</td>
100  * <td valign="top" width="700">The car speed at this point in time.&nbsp; To get km/hr, multiply this value by 3.6
101  *  (I'm not sure why codemasters uses this scale).</td>
102  * </tr>
103  * <tr>
104  * <td valign="top" width="200">XV</td>
105  * <td valign="top" width="700">&nbsp;</td>
106  * </tr>
107  * <tr>
108  * <td valign="top" width="200">YV</td>
109  * <td valign="top" width="700">&nbsp;</td>
110  * </tr>
111  * <tr>
112  * <td valign="top" width="200">ZV</td>
113  * <td valign="top" width="700">&nbsp;</td>
114  * </tr>
115  * <tr>
116  * <td valign="top" width="200">XR</td>
117  * <td valign="top" width="700">&nbsp;</td>
118  * </tr>
119  * <tr>
120  * <td valign="top" width="200">YR</td>
121  * <td valign="top" width="700">&nbsp;</td>
122  * </tr>
123  * <tr>
124  * <td valign="top" width="200">ZR</td>
125  * <td valign="top" width="700">&nbsp;</td>
126  * </tr>
127  * <tr>
128  * <td valign="top" width="200">XD</td>
129  * <td valign="top" width="700">&nbsp;</td>
130  * </tr>
131  * <tr>
132  * <td valign="top" width="200">YD</td>
133  * <td valign="top" width="700">&nbsp;</td>
134  * </tr>
135  * <tr>
136  * <td valign="top" width="200">ZD</td>
137  * <td valign="top" width="700">&nbsp;</td>
138  * </tr>
139  * <tr>
140  * <td valign="top" width="200">SuspensionPositionRearLeft</td>
141  * <td valign="top" width="700">The position of the rear left suspension</td>
142  * </tr>
143  * <tr>
144  * <td valign="top" width="200">SuspensionPositionRearRight</td>
145  * <td valign="top" width="700">The position of the rear right suspension</td>
146  * </tr>
147  * <tr>
148  * <td valign="top" width="200">SuspensionPositionFrontLeft</td>
149  * <td valign="top" width="700">The position of the front left suspension</td>
150  * </tr>
151  * <tr>
152  * <td valign="top" width="200">SuspensionPositionFrontRight</td>
153  * <td valign="top" width="700">The position of the front right suspension</td>
154  * </tr>
155  * <tr>
156  * <td valign="top" width="200">SuspensionVelocityRearLeft</td>
157  * <td valign="top" width="700">The speed of travel of the rear left suspension</td>
158  * </tr>
159  * <tr>
160  * <td valign="top" width="200">SuspensionVelocityRearRight</td>
161  * <td valign="top" width="700">The speed of travel of the rear right suspension</td>
162  * </tr>
163  * <tr>
164  * <td valign="top" width="200">SuspensionVelocityFrontLeft</td>
165  * <td valign="top" width="700">The speed of travel of the front left suspension</td>
166  * </tr>
167  * <tr>
168  * <td valign="top" width="200">SuspensionVelocityFrontRight</td>
169  * <td valign="top" width="700">The speed of travel of the front right suspension</td>
170  * </tr>
171  * <tr>
172  * <td valign="top" width="200">WheelSpeedRearLeft</td>
173  * <td valign="top" width="700">The speed the rear left wheel is travelling.&nbsp; <span>I assume this value with
174  * <span>Speed </span>subtracted gives wheelspin.&nbsp; Although it's a good 6 km/hr faster than the front,
175  *  if that's the case!</span></td>
176  * </tr>
177  * <tr>
178  * <td valign="top" width="200">WheelSpeedRearRight</td>
179  * <td valign="top" width="700">The speed the rear right wheel is travelling.</td>
180  * </tr>
181  * <tr>
182  * <td valign="top" width="200">WheelSpeedFrontLeft</td>
183  * <td valign="top" width="700">The speed the front left wheel is travelling</td>
184  * </tr>
185  * <tr>
186  * <td valign="top" width="200">WheelSpeedFrontRight</td>
187  * <td valign="top" width="700">The speed the front right wheel is travelling</td>
188  * </tr>
189  * <tr>
190  * <td valign="top" width="200">Throttle</td>
191  * <td valign="top" width="700">The percent of throttle applied.&nbsp; 1 = full throttle and 0 = no throttle</td>
192  * </tr>
193  * <tr>
194  * <td valign="top" width="200">Steer</td>
195  * <td valign="top" width="700">The amount of left/right (-/+) input into steering. 0 = straight ahead.</td>
196  * </tr>
197  * <tr>
198  * <td valign="top" width="200">Brake</td>
199  * <td valign="top" width="700">The percent of brake applied. 1 = full brake and 0 = no brake</td>
200  * </tr>
201  * <tr>
202  * <td valign="top" width="200">Clutch</td>
203  * <td valign="top" width="700"><span>This value will always be 0</span></td>
204  * </tr>
205  * <tr>
206  * <td valign="top" width="200">Gear</td>
207  * <td valign="top" width="700">The current gear</td>
208  * </tr>
209  * <tr>
210  * <td valign="top" width="200">GForceLatitudinal</td>
211  * <td valign="top" width="700">The amount of gforces being generated due to turning</td>
212  * </tr>
213  * <tr>
214  * <td valign="top" width="200">GForceLongitudinal</td>
215  * <td valign="top" width="700">The amount of gforces being generated due to acceleration or braking</td>
216  * </tr>
217  * <tr>
218  * <td valign="top" width="200">Lap</td>
219  * <td valign="top" width="700">The current Lap.&nbsp; 0 = first lap across the start/finish line.</td>
220  * </tr>
221  * <tr>
222  * <td valign="top" width="200">EngineRevs</td>
223  * <td valign="top" width="700">The RPM of the engine. This value needs to be multiplied by 10 to get the real RPM,
224  *  so it would seen.</td>
225  * </tr>
226  * </tbody>
227  * </table>
228  * <h3>Detecting new laps</h3>
229  * <p>From what I can tell, the following can be used to determine which lap the driver is on.</p>
230  * <table border="1">
231  * <tbody>
232  * <tr>
233  * <td width="200"><span>Action</span></td>
234  * <td><span>Details</span></td>
235  * </tr>
236  * <tr>
237  * <td>Sitting in the Pits</td>
238  * <td><span>When the driver is sitting in the pits </span><span>LapTime</span><span> is 0, </span><span>Speed </span>
239  * <span>is&nbsp;0. </span></td>
240  * </tr>
241  * <tr>
242  * <td>Out Laps</td>
243  * <td>
244  * <p>Out laps, that is laps where the driver has exited the pits but not yet crossed the start/finish line on the race
245  *  track have a <span>LapTime</span> value of 0 and a negative&nbsp;<span>Distance</span> value or a Distance value of
246  *  less than 1. &nbsp; The value is the fraction of a lap you have left before you start your first timed lap.
247  *  &nbsp;As you leave it'll be around -0.95 (95% to go) and as you're about to cross the start finish line it'll
248  *  be -0.0001 (.01% to go) approx. &nbsp;If you've crossed the start/finish line once, the value starts at 0 and gets
249  *  larger as you progress through the lap, toward a value of 1 (which is the start of the next lap).</p>
250  * <p>On your very first of the session the <span>Lap</span> value will be the same as the next lap so you cannot use
251  *  only&nbsp;changes in the <span>Lap</span> value to detect new laps.</p>
252  * </td>
253  * </tr>
254  * <tr>
255  * <td>Return to Pits</td>
256  * <td>When you return to the pits after being partway through a lap your <span>Lap</span> value will not change, so
257  *  you need to use some logic to recognise a return to pits. &nbsp;<span>LapTime</span> = 0 is a good one.</td>
258  * </tr>
259  * <tr>
260  * <td>Packet frequency</td>
261  * <td>The first packet received from F1 2012 after the car has crossed the start/finish line will be within 1/60th of
262  *  a second, which is the rate at which F1 2011 publishes data.</td>
263  * </tr>
264  * <tr>
265  * <td>Reversing back across the start finish line</td>
266  * <td><span>LapDistance </span>will vary depending on how much you move around during your lap. &nbsp;If you cross
267  *  the line it'll be set back to 0. &nbsp;If you then reverse back across the finish line it'll jump to a large
268  *  number.</td>
269  * </tr>
270  * </tbody>
271  * </table>
272**/
273public class F1TelemetryPacket //implements Serializable
274{
275  public float Time;
276  public float LapTime;
277  public float LapDistance;
278  public float Distance;
279  public float X;
280  public float Y;
281  public float Z;
282  public float Speed;
283  public float WorldSpeedX;
284  public float WorldSpeedY;
285  public float WorldSpeedZ;
286  public float XR;
287  public float Roll;
288  public float ZR;
289  public float XD;
290  public float Pitch;
291  public float ZD;
292  public float SuspensionPositionRearLeft;
293  public float SuspensionPositionRearRight;
294  public float SuspensionPositionFrontLeft;
295  public float SuspensionPositionFrontRight;
296  public float SuspensionVelocityRearLeft;
297  public float SuspensionVelocityRearRight;
298  public float SuspensionVelocityFrontLeft;
299  public float SuspensionVelocityFrontRight;
300  public float WheelSpeedBackLeft;
301  public float WheelSpeedBackRight;
302  public float WheelSpeedFrontLeft;
303  public float WheelSpeedFrontRight;
304  public float Throttle;
305  public float Steer;
306  public float Brake;
307  public float Clutch;
308  public float Gear;
309  public float LateralAcceleration;
310  public float LongitudinalAcceleration;
311  public float Lap;
312  public float EngineRevs;
313  /* New Fields in Patch 12 */
314  public float NewField1;                                                           // Always 1?
315  public float RacePosition;                                                           // Position in race
316  public float KersRemaining;                                                           // Kers Remaining
317  public float KersRecharge;                                                           // Always 400000?
318  public float DrsStatus;                                                           // Drs Status
319  public float Difficulty;                                                           // 2 = Medium or Easy, 1 = Hard, 0 = Expert
320  public float Assists;                                                           // 0 = All assists are off. 1 = some assist is on.
321  public float FuelRemaining;                                                           // Not sure if laps or Litres?
322  public float SessionType;                                                           // 9.5 = race, 10 = time trail / time attack, 170 = quali, practice, championsmode
323  public float NewField10;
324  public float Sector;                                                           // Sector (0, 1, 2)
325  public float TimeSector1;                                                           // Time Intermediate 1
326  public float TimeSector2;                                                           // Time Intermediate 2
327  public float BrakeTemperatureRearLeft;
328  public float BrakeTemperatureRearRight;
329  public float BrakeTemperatureFrontLeft;
330  public float BrakeTemperatureFrontRight;
331  public float NewField18;                                                           // Always 0?
332  public float NewField19;                                                           // Always 0?
333  public float NewField20;                                                           // Always 0?
334  public float NewField21;                                                           // Always 0?
335  public float CompletedLapsInRace;                                                           // Number of laps Completed (in GP only)
336  public float TotalLapsInRace;                                                           // Number of laps in GP (GP only)
337  public float TrackLength;                                                           // Track Length
338  public float PreviousLapTime;                                                           // Lap time of previous lap
339  // The next three fields are new for F1 2013... controlled by the extradata="3" attribute on the xml config done on the game config file.
340  public float NewField26; // Always 0?
341  public float NewField27; // Always 0?
342  public float NewField28; // Always 0?
343  /* End new Fields */
344
345
346  public  F1TelemetryPacket (byte[] data)
347  {
348    int end = data.length - 7;
349    //byte [] currVarBytes = new byte[4];
350    int currPosition = 0;
351
352    System.out.println("F1TelemetryPacket["+data.length+"]: "+java.util.Arrays.toString(data));
353
354    try
355    {
356      // if using serialization...
357      //ByteArrayInputStream dataStream = new ByteArrayInputStream(data);
358      //ObjectInputStream iStream = new ObjectInputStream(dataStream);
359      //retVal = (F1TelemetryPacket) iStream.readObject(); // using serializable interface
360      //iStream.close();
361      //dataStream.close();
362
363      // do it by hand
364      FloatBuffer fbuf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();
365      if (fbuf.hasRemaining()) {Time = fbuf.get();currPosition+=4;}
366      if (fbuf.hasRemaining()) {LapTime = fbuf.get();currPosition+=4;}
367      if (fbuf.hasRemaining()) {LapDistance = fbuf.get();currPosition+=4;}
368      if (fbuf.hasRemaining()) {Distance = fbuf.get();currPosition+=4;}
369      if (fbuf.hasRemaining()) {X = fbuf.get();currPosition+=4;}
370      if (fbuf.hasRemaining()) {Y = fbuf.get();currPosition+=4;}
371      if (fbuf.hasRemaining()) {Z = fbuf.get();currPosition+=4;}
372      if (fbuf.hasRemaining()) {Speed = fbuf.get();currPosition+=4;}
373      if (fbuf.hasRemaining()) {WorldSpeedX = fbuf.get();currPosition+=4;}
374      if (fbuf.hasRemaining()) {WorldSpeedY = fbuf.get();currPosition+=4;}
375      if (fbuf.hasRemaining()) {WorldSpeedZ = fbuf.get();currPosition+=4;}
376      if (fbuf.hasRemaining()) {XR = fbuf.get();currPosition+=4;}
377      if (fbuf.hasRemaining()) {Roll = fbuf.get();currPosition+=4;}
378      if (fbuf.hasRemaining()) {ZR = fbuf.get();currPosition+=4;}
379      if (fbuf.hasRemaining()) {XD = fbuf.get();currPosition+=4;}
380      if (fbuf.hasRemaining()) {Pitch = fbuf.get();currPosition+=4;}
381      if (fbuf.hasRemaining()) {ZD = fbuf.get();currPosition+=4;}
382      if (fbuf.hasRemaining()) {SuspensionPositionRearLeft = fbuf.get();currPosition+=4;}
383      if (fbuf.hasRemaining()) {SuspensionPositionRearRight = fbuf.get();currPosition+=4;}
384      if (fbuf.hasRemaining()) {SuspensionPositionFrontLeft = fbuf.get();currPosition+=4;}
385      if (fbuf.hasRemaining()) {SuspensionPositionFrontRight = fbuf.get();currPosition+=4;}
386      if (fbuf.hasRemaining()) {SuspensionVelocityRearLeft = fbuf.get();currPosition+=4;}
387      if (fbuf.hasRemaining()) {SuspensionVelocityRearRight = fbuf.get();currPosition+=4;}
388      if (fbuf.hasRemaining()) {SuspensionVelocityFrontLeft = fbuf.get();currPosition+=4;}
389      if (fbuf.hasRemaining()) {SuspensionVelocityFrontRight = fbuf.get();currPosition+=4;}
390      if (fbuf.hasRemaining()) {WheelSpeedBackLeft = fbuf.get();currPosition+=4;}
391      if (fbuf.hasRemaining()) {WheelSpeedBackRight = fbuf.get();currPosition+=4;}
392      if (fbuf.hasRemaining()) {WheelSpeedFrontLeft = fbuf.get();currPosition+=4;}
393      if (fbuf.hasRemaining()) {WheelSpeedFrontRight = fbuf.get();currPosition+=4;}
394      if (fbuf.hasRemaining()) {Throttle = fbuf.get();currPosition+=4;}
395      if (fbuf.hasRemaining()) {Steer = fbuf.get();currPosition+=4;}
396      if (fbuf.hasRemaining()) {Brake = fbuf.get();currPosition+=4;}
397      if (fbuf.hasRemaining()) {Clutch = fbuf.get();currPosition+=4;}
398      if (fbuf.hasRemaining()) {Gear = fbuf.get();currPosition+=4;}
399      if (fbuf.hasRemaining()) {LateralAcceleration = fbuf.get();currPosition+=4;}
400      if (fbuf.hasRemaining()) {LongitudinalAcceleration = fbuf.get();currPosition+=4;}
401      if (fbuf.hasRemaining()) {Lap = fbuf.get();currPosition+=4;}
402      if (fbuf.hasRemaining()) {EngineRevs = fbuf.get();currPosition+=4;}
403      if (fbuf.hasRemaining()) {NewField1 = fbuf.get();currPosition+=4;}
404      if (fbuf.hasRemaining()) {RacePosition = fbuf.get();currPosition+=4;}
405      if (fbuf.hasRemaining()) {KersRemaining = fbuf.get();currPosition+=4;}
406      if (fbuf.hasRemaining()) {KersRecharge = fbuf.get();currPosition+=4;}
407      if (fbuf.hasRemaining()) {DrsStatus = fbuf.get();currPosition+=4;}
408      if (fbuf.hasRemaining()) {Difficulty = fbuf.get();currPosition+=4;}
409      if (fbuf.hasRemaining()) {Assists = fbuf.get();currPosition+=4;}
410      if (fbuf.hasRemaining()) {FuelRemaining = fbuf.get();currPosition+=4;}
411      if (fbuf.hasRemaining()) {SessionType = fbuf.get();currPosition+=4;}
412      if (fbuf.hasRemaining()) {NewField10 = fbuf.get();currPosition+=4;}
413      if (fbuf.hasRemaining()) {Sector = fbuf.get();currPosition+=4;}
414      if (fbuf.hasRemaining()) {TimeSector1 = fbuf.get();currPosition+=4;}
415      if (fbuf.hasRemaining()) {TimeSector2 = fbuf.get();currPosition+=4;}
416      if (fbuf.hasRemaining()) {BrakeTemperatureRearLeft = fbuf.get();currPosition+=4;}
417      if (fbuf.hasRemaining()) {BrakeTemperatureRearRight = fbuf.get();currPosition+=4;}
418      if (fbuf.hasRemaining()) {BrakeTemperatureFrontLeft = fbuf.get();currPosition+=4;}
419      if (fbuf.hasRemaining()) {BrakeTemperatureFrontRight = fbuf.get();currPosition+=4;}
420      if (fbuf.hasRemaining()) {NewField18 = fbuf.get();currPosition+=4;}
421      if (fbuf.hasRemaining()) {NewField19 = fbuf.get();currPosition+=4;}
422      if (fbuf.hasRemaining()) {NewField20 = fbuf.get();currPosition+=4;}
423      if (fbuf.hasRemaining()) {NewField21 = fbuf.get();currPosition+=4;}
424      if (fbuf.hasRemaining()) {CompletedLapsInRace = fbuf.get();currPosition+=4;}
425      if (fbuf.hasRemaining()) {TotalLapsInRace = fbuf.get();currPosition+=4;}
426      if (fbuf.hasRemaining()) {TrackLength = fbuf.get();currPosition+=4;}
427      if (fbuf.hasRemaining()) {PreviousLapTime = fbuf.get();currPosition+=4;}
428      if (fbuf.hasRemaining()) {NewField26 = fbuf.get();currPosition+=4;}
429      if (fbuf.hasRemaining()) {NewField27 = fbuf.get();currPosition+=4;}
430      if (fbuf.hasRemaining()) {NewField28 = fbuf.get();currPosition+=4;}
431      /*
432      if(currPosition<end) { Time=                          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
433      if(currPosition<end) { LapTime =                      ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
434      if(currPosition<end) { LapDistance =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
435      if(currPosition<end) { Distance =                     ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
436      if(currPosition<end) { X =                            ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
437      if(currPosition<end) { Y =                            ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
438      if(currPosition<end) { Z =                            ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
439      if(currPosition<end) { Speed =                        ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
440      if(currPosition<end) { WorldSpeedX =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
441      if(currPosition<end) { WorldSpeedY =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
442      if(currPosition<end) { WorldSpeedZ =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
443      if(currPosition<end) { XR =                           ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
444      if(currPosition<end) { Roll =                         ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
445      if(currPosition<end) { ZR =                           ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
446      if(currPosition<end) { XD =                           ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
447      if(currPosition<end) { Pitch =                        ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
448      if(currPosition<end) { ZD =                           ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
449      if(currPosition<end) { SuspensionPositionRearLeft =   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
450      if(currPosition<end) { SuspensionPositionRearRight =  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
451      if(currPosition<end) { SuspensionPositionFrontLeft =  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
452      if(currPosition<end) { SuspensionPositionFrontRight = ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
453      if(currPosition<end) { SuspensionVelocityRearLeft =   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
454      if(currPosition<end) { SuspensionVelocityRearRight =  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
455      if(currPosition<end) { SuspensionVelocityFrontLeft =  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
456      if(currPosition<end) { SuspensionVelocityFrontRight = ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
457      if(currPosition<end) { WheelSpeedBackLeft =           ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
458      if(currPosition<end) { WheelSpeedBackRight =          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
459      if(currPosition<end) { WheelSpeedFrontLeft =          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
460      if(currPosition<end) { WheelSpeedFrontRight =         ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
461      if(currPosition<end) { Throttle =                     ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
462      if(currPosition<end) { Steer =                        ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
463      if(currPosition<end) { Brake =                        ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
464      if(currPosition<end) { Clutch =                       ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
465      if(currPosition<end) { Gear =                         ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
466      if(currPosition<end) { LateralAcceleration =          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
467      if(currPosition<end) { LongitudinalAcceleration =     ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
468      if(currPosition<end) { Lap =                          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
469      if(currPosition<end) { EngineRevs =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
470      if(currPosition<end) { NewField1 =                    ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
471      if(currPosition<end) { RacePosition =                 ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
472      if(currPosition<end) { KersRemaining =                ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
473      if(currPosition<end) { KersRecharge =                 ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
474      if(currPosition<end) { DrsStatus =                    ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
475      if(currPosition<end) { Difficulty =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
476      if(currPosition<end) { Assists =                      ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
477      if(currPosition<end) { FuelRemaining =                ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
478      if(currPosition<end) { SessionType =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
479      if(currPosition<end) { NewField10 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
480      if(currPosition<end) { Sector =                       ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
481      if(currPosition<end) { TimeSector1 =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
482      if(currPosition<end) { TimeSector2 =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
483      if(currPosition<end) { BrakeTemperatureRearLeft =     ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
484      if(currPosition<end) { BrakeTemperatureRearRight =    ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
485      if(currPosition<end) { BrakeTemperatureFrontLeft =    ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
486      if(currPosition<end) { BrakeTemperatureFrontRight =   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
487      if(currPosition<end) { NewField18 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
488      if(currPosition<end) { NewField19 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
489      if(currPosition<end) { NewField20 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
490      if(currPosition<end) { NewField21 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
491      if(currPosition<end) { CompletedLapsInRace =          ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
492      if(currPosition<end) { TotalLapsInRace =              ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
493      if(currPosition<end) { TrackLength =                  ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
494      if(currPosition<end) { PreviousLapTime =              ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
495      if(currPosition<end) { NewField26 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
496      if(currPosition<end) { NewField27 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
497      if(currPosition<end) { NewField28 =                   ByteBuffer.wrap(data,currPosition,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();   currPosition+=4;   }
498      */
499    }
500    catch(Exception e)
501    {
502      e.printStackTrace();
503      System.out.println("\nUnrecognized data:\n"+java.util.Arrays.toString(data));
504      System.out.println("\n at position : "+currPosition);
505    }
506    if (currPosition<data.length)System.out.println("\nOverRUN data at position : "+currPosition);
507  }
508
509  @Override
510  public String toString()
511  {
512    StringBuilder sb = new StringBuilder("{F1Telemetry:\n  {");
513    sb.append("  EngineRevs: ");sb.append(EngineRevs);sb.append(",\n");
514    sb.append("  Throttle: ");sb.append(Throttle);sb.append(",\n");
515    sb.append("  Gear: ");sb.append(Gear);sb.append(",\n");
516    sb.append("  Brake: ");sb.append(Brake);sb.append(",\n");
517    sb.append("  Clutch: ");sb.append(Clutch);sb.append(",\n");
518    sb.append("  FuelRemaining: ");sb.append(FuelRemaining);sb.append(",\n");
519    sb.append("  Speed: ");sb.append(Speed);sb.append(",\n");
520    sb.append("  RacePosition: ");sb.append(RacePosition);sb.append(",\n");
521    sb.append("  Time: ");sb.append(Time);sb.append(",\n");
522    sb.append("  LapTime: ");sb.append(LapTime);sb.append(",\n");
523    sb.append("  PreviousLapTime: ");sb.append(PreviousLapTime);sb.append(",\n");
524    sb.append("  Lap: ");sb.append(Lap);sb.append(",\n");
525    sb.append("  CompletedLapsInRace: ");sb.append(CompletedLapsInRace);sb.append(",\n");
526    sb.append("  TotalLapsInRace: ");sb.append(TotalLapsInRace);sb.append(",\n");
527    sb.append("  LapDistance: ");sb.append(LapDistance);sb.append(",\n");
528    sb.append("  Distance: ");sb.append(Distance);sb.append(",\n");
529
530    sb.append("  }\n}");
531    return sb.toString();
532  }
533
534
535  /**
536   * Deserialize the udp-packet back to readable an F1TelemetryPacket object.
537   * @param data
538   * @return this class object
539   */
540  public static F1TelemetryPacket deserializePacket(byte[] data)
541  {
542    F1TelemetryPacket retVal = new F1TelemetryPacket(data);
543
544    return retVal;
545  }
546
547
548  /**
549    * Set Method for class field 'EngineRevs'.
550    *
551    * @param EngineRevs is the value to set this class field to.
552    *
553    **/
554  public  void setEngineRevs(float EngineRevs)
555  {
556    this.EngineRevs = EngineRevs;
557  }  // setEngineRevs Method
558
559
560  /**
561    * Get Method for class field 'EngineRevs'.
562    *
563    * @return float - The value the class field 'EngineRevs'.
564    *
565    **/
566  public float getEngineRevs()
567  {
568    return EngineRevs;
569  }  // getEngineRevs Method
570
571
572  /**
573    * Gets the engin RPM (which is EngineRevs*10).
574    *
575    * @return float - The value the class field 'EngineRevs'.
576    *
577    **/
578  public float getRPM()
579  {
580    return EngineRevs*10;
581  }  // getEngineRevs Method
582
583
584  /**
585    * Set Method for class field 'Speed'.
586    *
587    * @param Speed is the value to set this class field to.
588    *
589    **/
590  public  void setSpeed(float Speed)
591  {
592    this.Speed = Speed;
593  }  // setSpeed Method
594
595
596  /**
597    * Get Method for class field 'Speed'.
598    *
599    * @return float - The value the class field 'Speed'.
600    *
601    **/
602  public float getSpeed()
603  {
604    return Speed;
605  }  // getSpeed Method
606
607
608  /**
609    * Gets the speed in km/hr.
610    *
611    * @return float - The value the class field 'Speed'.
612    *
613    **/
614  public float getSpeedKM()
615  {
616    return Speed*3.6f;
617  }  // getSpeed Method
618
619
620  /**
621    * Set Method for class field 'Gear'.
622    *
623    * @param Gear is the value to set this class field to.
624    *
625    **/
626  public  void setGear(float Gear)
627  {
628    this.Gear = Gear;
629  }  // setGear Method
630
631
632  /**
633    * Get Method for class field 'Gear'.
634    *
635    * @return float - The value the class field 'Gear'.
636    *
637    **/
638  public float getGear()
639  {
640    return Gear;
641  }  // getGear Method
642
643
644  /**
645    * Set Method for class field 'Throttle'.
646    *
647    * @param Throttle is the value to set this class field to.
648    *
649    **/
650  public  void setThrottle(float Throttle)
651  {
652    this.Throttle = Throttle;
653  }  // setThrottle Method
654
655
656  /**
657    * Get Method for class field 'Throttle'.
658    *
659    * @return float - The value the class field 'Throttle'.
660    *
661    **/
662  public float getThrottle()
663  {
664    return Throttle;
665  }  // getThrottle Method
666
667
668}