private void HandlePacket(PacketHeader packet, byte[] bytes)
        {
            _telemetryRecorder.RecordPacket(packet, bytes);

            switch (packet.PacketType)
            {
            case PacketType.Motion:
                var motionPacket = StructUtility.ConvertToPacket <PacketMotionData>(bytes);
                OnMotionPacketReceived(new PacketReceivedEventArgs <PacketMotionData>(_oldMotionData, motionPacket));
                _oldMotionData = motionPacket;
                break;

            case PacketType.Session:
                var sessionPacket = StructUtility.ConvertToPacket <PacketSessionData>(bytes);
                OnSessionPacketReceived(new PacketReceivedEventArgs <PacketSessionData>(_oldSessionData, sessionPacket));
                _oldSessionData = sessionPacket;
                break;

            case PacketType.LapData:
                var lapPacket = StructUtility.ConvertToPacket <PacketLapData>(bytes);
                OnLapPacketReceivedReceived(new PacketReceivedEventArgs <PacketLapData>(_oldLapData, lapPacket));
                _oldLapData = lapPacket;
                break;

            case PacketType.Event:
                var eventPacket = StructUtility.ConvertToPacket <EventPacket>(bytes);
                OnEventPacketReceived(new PacketReceivedEventArgs <EventPacket>(_oldEventPacket, eventPacket));
                _oldEventPacket = eventPacket;
                break;

            case PacketType.Participants:
                var participantPacket = StructUtility.ConvertToPacket <PacketParticipantsData>(bytes);
                OnParticipantsPacketReceived(new PacketReceivedEventArgs <PacketParticipantsData>(_oldParticipantsData, participantPacket));
                _oldParticipantsData = participantPacket;
                break;

            case PacketType.CarSetups:
                var carSetupsPacket = StructUtility.ConvertToPacket <PacketCarSetupData>(bytes);
                OnCarSetupPacketReceived(new PacketReceivedEventArgs <PacketCarSetupData>(_oldCarSetupData, carSetupsPacket));
                _oldCarSetupData = carSetupsPacket;
                break;

            case PacketType.CarTelemetry:
                var carTelemetryPacket = StructUtility.ConvertToPacket <PacketCarTelemetryData>(bytes);
                OnCarTelemetryPacketReceived(new PacketReceivedEventArgs <PacketCarTelemetryData>(_oldCarTelemetryData, carTelemetryPacket));
                _oldCarTelemetryData = carTelemetryPacket;
                break;

            case PacketType.CarStatus:
                var carStatusPacket = StructUtility.ConvertToPacket <PacketCarStatusData>(bytes);
                OnCarStatusPacketReceived(new PacketReceivedEventArgs <PacketCarStatusData>(_oldCarStatusData, carStatusPacket));
                _oldCarStatusData = carStatusPacket;
                break;
            }

            _oldSessionId       = packet.SessionUId;
            _oldFrameIdentifier = packet.FrameIdentifier;
        }
        public void OnDebugDataSelected(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 0)
            {
                return;
            }

            var selectedDebugData = ((DebugModel)e.AddedItems[0]);

            switch (selectedDebugData.PacketType)
            {
            case PacketType.Motion:
                PacketMotionData motionData = StructUtility.ConvertToPacket <PacketMotionData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(motionData);
                return;

            case PacketType.Session:
                PacketSessionData sessionData = StructUtility.ConvertToPacket <PacketSessionData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(sessionData);
                return;

            case PacketType.LapData:
                PacketLapData lapData = StructUtility.ConvertToPacket <PacketLapData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(lapData);
                return;

            case PacketType.Event:
                EventPacket eventData = StructUtility.ConvertToPacket <EventPacket>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(eventData);
                return;

            case PacketType.Participants:
                PacketParticipantsData participantsData = StructUtility.ConvertToPacket <PacketParticipantsData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(participantsData);
                return;

            case PacketType.CarSetups:
                PacketCarSetupData carSetupsData = StructUtility.ConvertToPacket <PacketCarSetupData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(carSetupsData);
                return;

            case PacketType.CarTelemetry:
                PacketCarTelemetryData carTelemetryData = StructUtility.ConvertToPacket <PacketCarTelemetryData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(carTelemetryData);
                return;

            case PacketType.CarStatus:
                PacketCarStatusData carStatusData = StructUtility.ConvertToPacket <PacketCarStatusData>(selectedDebugData.Data);
                DebugDetails = new ObjectViewModelHierarchy(carStatusData);
                return;
            }
        }
        private void UdpLoop()
        {
            while (true)
            {
                InitUdp(_port);
                try
                {
                    _udpClient.Client.ReceiveTimeout = 5000;
                    byte[] receiveBytes = _udpClient.Receive(ref _senderIp);
                    var    packet       = StructUtility.ConvertToPacket <PacketHeader>(receiveBytes);
                    HandlePacket(packet, receiveBytes);
                }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
                catch (Exception)
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
                {
                    // can be ignored (timeout etc)
                }
            }
        }