private int readFromOffset(int offset, byte[] rawData) { // the first 2 bytes are the version - discard it for now int frameTypeAndSequence = rawData[offset + 2]; int frameType = frameTypeAndSequence & 3; int sequence = frameTypeAndSequence >> 2; int frameLength = 0; if (frameType == 0) { telemPacketCount++; if (telemPacketCount > packetCountAtStartOfNextRateCheck) { lastPacketRateEstimate = (int)((float)TimeSpan.TicksPerSecond * (float)(telemPacketCount - packetCountAtStartOfCurrentRateCheck) / (float)(DateTime.UtcNow.Ticks - ticksAtStartOfCurrentPacketRateCheck)); Console.WriteLine("Packet rate = " + lastPacketRateEstimate + "Hz, totals: type0 = " + telemPacketCount + " type1 = " + stringsPacketCount + " type2 = " + additionalStringsPacketCount + " in sequence = " + inSequenceTelemCount + " oos accepted = " + acceptedOutOfSequenceTelemCount + " oos rejected = " + discardedTelemCount); packetCountAtStartOfCurrentRateCheck = telemPacketCount; packetCountAtStartOfNextRateCheck = packetCountAtStartOfCurrentRateCheck + packetRateCheckInterval; ticksAtStartOfCurrentPacketRateCheck = DateTime.UtcNow.Ticks; } frameLength = sTelemetryData_PacketSize; Boolean sequenceCheckOK = isNextInSequence(sequence); if (sequenceCheckOK) { inSequenceTelemCount++; } if (strictPacketOrdering && !sequenceCheckOK) { discardedTelemCount++; } else { GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned); try { sTelemetryData telem = (sTelemetryData)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sTelemetryData)); if (sequenceCheckOK || !telemIsOutOfSequence(telem)) { buttonsState = ConvertBytesToBoolArray(telem.sDPad, telem.sJoyPad1, telem.sJoyPad2); lastSequenceNumberForTelemPacket = sequence; workingGameState = StructHelper.MergeWithExistingState(workingGameState, telem); newSpotterData = workingGameState.hasNewPositionData; } } finally { handle.Free(); } } } else if (frameType == 1) { stringsPacketCount++; frameLength = sParticipantInfoStrings_PacketSize; GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned); try { sParticipantInfoStrings strings = (sParticipantInfoStrings)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStrings)); workingGameState = StructHelper.MergeWithExistingState(workingGameState, strings); } finally { handle.Free(); } } else if (frameType == 2) { additionalStringsPacketCount++; frameLength = sParticipantInfoStringsAdditional_PacketSize; GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned); try { sParticipantInfoStringsAdditional additional = (sParticipantInfoStringsAdditional)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStringsAdditional)); workingGameState = StructHelper.MergeWithExistingState(workingGameState, additional); } finally { handle.Free(); } } else { Console.WriteLine("Unrecognised frame type " + frameType + " from byte " + rawData[offset + 2]); } return(frameLength + offset); }
public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sParticipantInfoStrings udpParticipantStrings) { existingState.mCarClassName = udpParticipantStrings.sCarClassName; existingState.mCarName = udpParticipantStrings.sCarName; existingState.mTrackLocation = udpParticipantStrings.sTrackLocation; existingState.mTrackVariation = udpParticipantStrings.sTrackVariation; if (existingState.mParticipantData == null) { existingState.mParticipantData = new pCarsAPIParticipantStruct[56]; } for (int i = 0; i < udpParticipantStrings.sName.Count(); i++) { existingState.mParticipantData[i].mName = udpParticipantStrings.sName[i].nameByteArray; } return(existingState); }