/// <summary>
        /// Generates actual data to send to the client.
        /// </summary>
        /// <remarks>Data is sent according to the behavior of a typical GPS device: $GPGGA,
        /// $GPGSA, $GPRMC, $GPGSV sentences are sent every second, and a $GPGSV sentence
        /// is sent every five seconds.
        /// Developers who want to emulate a specific model of GPS device should override this
        /// method and generate the sentences specific to that device.</remarks>
        protected override void OnEmulation()
        {
            // Update real-time position, speed, bearing, etc.
            base.OnEmulation();

            if (Route.Count == 0)
            {
                CurrentPosition = EmulatePositionError(CurrentPosition);
            }

            /* NMEA devices will transmit "bursts" of NMEA sentences, followed by a one-second pause.
             * Other sentences (usually $GPGSV) are transmitted once every few seconds.  This emulator,
             * by default, will transmit the most common NMEA sentences.
             */

            // $GPGGA
            if (!_gpggaInterval.Equals(TimeSpan.Zero)
                // Has enough time elapsed to send the sentence?
                && UtcDateTime.Subtract(_gpggaLastSent) > _gpggaInterval)
            {
                // Get the tracked satellite count
                int trackedCount = Satellites.Count(item => item.SignalToNoiseRatio.Value > 0);

                // Yes
                _gpggaLastSent = UtcDateTime;

                // Queue the sentence to the read buffer
                WriteSentenceToClient(new GpggaSentence(UtcDateTime.TimeOfDay, CurrentPosition, _fixQuality, trackedCount,
                                                        _horizontalDOP, Altitude.Add(EmulateError(_verticalDOP)), Distance.Empty, TimeSpan.Zero, -1)); //Add an error to the altitude written to the client but don't change the actual value (otherwise it will "walk")
            }

            // $GPRMC
            if (!_gprmcInterval.Equals(TimeSpan.Zero)
                // Has enough time elapsed to send the sentence?
                && UtcDateTime.Subtract(_gprmcLastSent) > _gprmcInterval)
            {
                // Yes
                _gprmcLastSent = UtcDateTime;

                // Queue the sentence to the read buffer
                WriteSentenceToClient(new GprmcSentence(UtcDateTime, _fixStatus == FixStatus.Fix, CurrentPosition, Speed,
                                                        Bearing, _magneticVariation));
            }

            // $GPGLL
            if (!_gpgllInterval.Equals(TimeSpan.Zero)
                // Has enough time elapsed to send the sentence?
                && UtcDateTime.Subtract(_gpgllLastSent) > _gpgllInterval)
            {
                // Yes
                _gpgllLastSent = UtcDateTime;

                // Write a $GPGLL to the client
                WriteSentenceToClient(new GpgllSentence(CurrentPosition, UtcDateTime.TimeOfDay, _fixStatus));
            }

            // $GPGSA
            if (!_gpgsaInterval.Equals(TimeSpan.Zero)
                // Has enough time elapsed to send the sentence?
                && UtcDateTime.Subtract(_gpgsaLastSent) > _gpgsaInterval)
            {
                // Yes
                _gpgsaLastSent = UtcDateTime;

                // Queue the sentence to the read buffer
                WriteSentenceToClient(new GpgsaSentence(_fixMode, _fixMethod, Satellites,
                                                        _meanDOP, _horizontalDOP, _verticalDOP));
            }

            // $GPGSV
            if (!_gpgsvInterval.Equals(TimeSpan.Zero)
                // Has enough time elapsed to send the sentence?
                && UtcDateTime.Subtract(_gpgsvLastSent) > _gpgsvInterval)
            {
                // Build a list of sentences from our satellites
                IList <GpgsvSentence> sentences = GpgsvSentence.FromSatellites(Satellites);

                // Yes
                _gpgsvLastSent = UtcDateTime;

                // Write each sentence to the read buffer
                foreach (GpgsvSentence gpgsv in sentences)
                {
                    WriteSentenceToClient(gpgsv);
                }
            }

            // And signal that we have data (or not)
            if (ReadBuffer.Count == 0)
            {
                ReadDataAvailableWaitHandle.Reset();
            }
            else
            {
                ReadDataAvailableWaitHandle.Set();
            }
        }