예제 #1
0
        /// <summary>
        /// Creates a GpgllSentence from the specified parameters
        /// </summary>
        /// <param name="position"></param>
        /// <param name="utcTime"></param>
        /// <param name="fixStatus"></param>
        public GpgllSentence(Position position, TimeSpan utcTime, FixStatus fixStatus)
        {
            // Build a sentence
            StringBuilder builder = new StringBuilder(128);

            #region Append the command word

            // Append the command word
            builder.Append("$GPGLL");

            #endregion

            // Append a comma
            builder.Append(',');

            #region Append the position

            // Append latitude in the format HHMM.MMMM.
            builder.Append(position.Latitude.ToString("HHMM.MMMM,I,", NmeaCultureInfo));
            // Append Longitude in the format HHHMM.MMMM.
            builder.Append(position.Longitude.ToString("HHHMM.MMMM,I,", NmeaCultureInfo));

            #endregion

            #region Append the UTC time

            builder.Append(utcTime.Hours.ToString("0#", NmeaCultureInfo));
            builder.Append(utcTime.Minutes.ToString("0#", NmeaCultureInfo));
            builder.Append(utcTime.Seconds.ToString("0#", NmeaCultureInfo));
            builder.Append(".");
            builder.Append(utcTime.Milliseconds.ToString("00#", NmeaCultureInfo));

            #endregion

            // Append a comma
            builder.Append(",");

            #region Append the fix status

            switch (fixStatus)
            {
            case FixStatus.Fix:
                builder.Append("A");
                break;

            default:
                builder.Append("V");      // V = INvalid
                break;
            }

            #endregion

            // Set this object's sentence
            SetSentence(builder.ToString());

            // Finally, append the checksum
            AppendChecksum();
        }
예제 #2
0
        public GpgllSentence(Position position, TimeSpan utcTime, FixStatus fixStatus)
        {
            // Build a sentence
            StringBuilder builder = new StringBuilder(128);

            #region Append the command word

            // Append the command word
            builder.Append("$GPGLL");

            #endregion

            // Append a comma
            builder.Append(',');

            #region Append the position

            // Append latitude in the format HHMM.MMMM. 
            builder.Append(position.Latitude.ToString("HHMM.MMMM,I,", NmeaCultureInfo));
            // Append Longitude in the format HHHMM.MMMM.
            builder.Append(position.Longitude.ToString("HHHMM.MMMM,I,", NmeaCultureInfo));

            #endregion

            #region Append the UTC time

            builder.Append(utcTime.Hours.ToString("0#", NmeaCultureInfo));
            builder.Append(utcTime.Minutes.ToString("0#", NmeaCultureInfo));
            builder.Append(utcTime.Seconds.ToString("0#", NmeaCultureInfo));
            builder.Append(".");
            builder.Append(utcTime.Milliseconds.ToString("00#", NmeaCultureInfo));

            #endregion

            // Append a comma
            builder.Append(",");

            #region Append the fix status

            switch (fixStatus)
            {
                case FixStatus.Fix:
                    builder.Append("A");
                    break;
                default:
                    builder.Append("V");  // V = INvalid
                    break;
            }

            #endregion

            // Set this object's sentence
            SetSentence(builder.ToString());

            // Finally, append the checksum
            AppendChecksum();
        }
예제 #3
0
        protected Emulator(string name)
        {
            _Name = name;

            // Create new buffers for reading and writing
            _ReadBuffer  = new List <byte>(_DefaultReadBufferSize);
            _WriteBuffer = new List <byte>(_DefaultWriteBufferSize);

            // Initialize simulated values
            _ReadDataAvailableWaitHandle  = new ManualResetEvent(false);
            _WriteDataAvailableWaitHandle = new ManualResetEvent(false);
            _EmulationIntervalWaitHandle  = new ManualResetEvent(false);

            // Default timeouts for reading and writing
            _ReadTimeout  = _DefaultReadTimeout;
            _WriteTimeout = _DefaultWriteTimeout;

            // Simulated values
            _seed            = new Random();
            _UtcDateTime     = DateTime.UtcNow;
            _CurrentPosition = Positioning.Position.Empty;
            _Altitude        = Distance.FromFeet(1000);
            _Route           = new List <Position>();
            _Satellites      = new List <Satellite>();
            _FixQuality      = FixQuality.GpsFix;
            _FixMode         = FixMode.Automatic;
            _FixMethod       = FixMethod.Fix3D;
            _FixStatus       = FixStatus.Fix;
            _HorizontalDop   = DilutionOfPrecision.Good;
            _VerticalDop     = DilutionOfPrecision.Good;
            _MeanDop         = DilutionOfPrecision.Good;

            _Speed     = Speed.FromStatuteMilesPerHour(20);
            _speedLow  = Speed.FromKilometersPerSecond(10).Value;
            _speedHigh = Speed.FromKilometersPerSecond(25).Value;

            _Bearing      = Azimuth.Southwest;
            _bearingStart = _seed.NextDouble() * 360;
            _bearingArc   = 10;
        }
예제 #4
0
        protected Emulator(string name)
        {
            _Name = name;

            // Create new buffers for reading and writing
            _ReadBuffer = new List<byte>(_DefaultReadBufferSize);
            _WriteBuffer = new List<byte>(_DefaultWriteBufferSize);

            // Initialize simulated values
            _ReadDataAvailableWaitHandle = new ManualResetEvent(false);
            _WriteDataAvailableWaitHandle = new ManualResetEvent(false);
            _EmulationIntervalWaitHandle = new ManualResetEvent(false);

            // Default timeouts for reading and writing
            _ReadTimeout = _DefaultReadTimeout;
            _WriteTimeout = _DefaultWriteTimeout;
            
            // Simulated values
            _seed = new Random();
            _UtcDateTime = DateTime.UtcNow;
            _CurrentPosition = GeoFramework.Position.Empty;            
            _Altitude = Distance.FromFeet(1000);
            _Route = new List<Position>();
            _Satellites = new List<Satellite>();
            _FixQuality = FixQuality.GpsFix;
            _FixMode = FixMode.Automatic;
            _FixMethod = FixMethod.Fix3D;
            _FixStatus = FixStatus.Fix;
            _HorizontalDop = DilutionOfPrecision.Good;
            _VerticalDop = DilutionOfPrecision.Good;
            _MeanDop = DilutionOfPrecision.Good;

            _Speed = Speed.FromStatuteMilesPerHour(20);
            _speedLow = Speed.FromKilometersPerSecond(10).Value;
            _speedHigh = Speed.FromKilometersPerSecond(25).Value;

            _Bearing = Azimuth.Southwest;
            _bearingStart = _seed.NextDouble() * 360;
            _bearingArc = 10;

        }
예제 #5
0
        protected override void OnSentenceChanged()
        {
            // First, process the basic info for the sentence
            base.OnSentenceChanged();

            // Cache the sentence words
            string[] words = base.Words;
            int wordCount = words.Length;

            /*
             * $GPRMC

                 Recommended minimum specific GPS/Transit data

                 eg1. $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
                 eg2. $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68


                            225446       Time of fix 22:54:46 UTC
                            A            Navigation receiver warning A = OK, V = warning
                            4916.45,N    Latitude 49 deg. 16.45 min North
                            12311.12,W   Longitude 123 deg. 11.12 min West
                            000.5        Speed over ground, Knots
                            054.7        Course Made Good, True
                            191194       Date of fix  19 November 1994
                            020.3,E      Magnetic variation 20.3 deg East
                            *68          mandatory checksum


                 eg3. $GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
                               1    2    3    4    5     6    7    8      9     10  11 12


                       1   220516     Time Stamp
                       2   A          validity - A-ok, V-invalid
                       3   5133.82    current Latitude
                       4   N          North/South
                       5   00042.24   current Longitude
                       6   W          East/West
                       7   173.8      Speed in knots
                       8   231.8      True course
                       9   130694     Date Stamp
                       10  004.2      Variation
                       11  W          East/West
                       12  *70        checksum


                 eg4. $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
                 1    = UTC of position fix
                 2    = Data status (V=navigation receiver warning)
                 3    = Latitude of fix
                 4    = N or S
                 5    = Longitude of fix
                 6    = E or W
                 7    = Speed over ground in knots
                 8    = Track made good in degrees True
                 9    = UT date
                 10   = Magnetic variation degrees (Easterly var. subtracts from true course)
                 11   = E or W
                 12   = Checksum
             */


            // Do we have enough words to parse the fix status?
            if (wordCount >= 2 && words[1].Length != 0)
            {
                #region Fix status 

                // Get the fix flag
                _FixStatus = words[1].Equals("A", StringComparison.OrdinalIgnoreCase) ? FixStatus.Fix : FixStatus.NoFix;

                #endregion
            }
            else
            {
                // The fix status is invalid
                _FixStatus = FixStatus.Unknown;
            }

            // Do we have enough words to parse the UTC date/time?
            if (wordCount >= 9 && words[0].Length != 0 && words[8].Length != 0)
            {
                #region Parse the UTC time

                string utcTimeWord = words[0];
                int utcHours = int.Parse(utcTimeWord.Substring(0, 2), NmeaCultureInfo);                 // AA
                int utcMinutes = int.Parse(utcTimeWord.Substring(2, 2), NmeaCultureInfo);               // BB
                int utcSeconds = int.Parse(utcTimeWord.Substring(4, 2), NmeaCultureInfo);               // CC
                int utcMilliseconds = 0;
                if(utcTimeWord.Length > 6)
                    utcMilliseconds = Convert.ToInt32(float.Parse(utcTimeWord.Substring(6), NmeaCultureInfo) * 1000, NmeaCultureInfo);    // DDDD

                #endregion

                #region Parse the UTC date

                string utcDateWord = words[8];
                int utcDay = int.Parse(utcDateWord.Substring(0, 2), NmeaCultureInfo);
                int utcMonth = int.Parse(utcDateWord.Substring(2, 2), NmeaCultureInfo);
                int utcYear = int.Parse(utcDateWord.Substring(4, 2), NmeaCultureInfo) + 2000;

                #endregion

                #region Build a UTC date/time

                _UtcDateTime = new DateTime(utcYear, utcMonth, utcDay, utcHours, utcMinutes, utcSeconds, utcMilliseconds, DateTimeKind.Utc);

                #endregion
            }
            else
            {
                // The UTC date/time is invalid
                _UtcDateTime = DateTime.MinValue;
            }

            // Do we have enough data to parse the location?
            if (wordCount >= 6 && words[2].Length != 0 && words[3].Length != 0 && words[4].Length != 0 && words[5].Length != 0)
            {
                #region Parse the latitude

                string latitudeWord = words[2];
                int latitudeHours = int.Parse(latitudeWord.Substring(0, 2), NmeaCultureInfo);
                double latitudeDecimalMinutes = double.Parse(latitudeWord.Substring(2), NmeaCultureInfo);
                LatitudeHemisphere latitudeHemisphere =
                    words[3].Equals("N", StringComparison.Ordinal) ? LatitudeHemisphere.North : LatitudeHemisphere.South;

                #endregion

                #region Parse the longitude

                string longitudeWord = words[4];
                int longitudeHours = int.Parse(longitudeWord.Substring(0, 3), NmeaCultureInfo);
                double longitudeDecimalMinutes = double.Parse(longitudeWord.Substring(3), NmeaCultureInfo);
                LongitudeHemisphere longitudeHemisphere =
                    words[5].Equals("E", StringComparison.Ordinal) ? LongitudeHemisphere.East : LongitudeHemisphere.West;

                #endregion

                #region Build a Position from the latitude and longitude

                _Position = new Position(
                                new Latitude(latitudeHours, latitudeDecimalMinutes, latitudeHemisphere),
                                new Longitude(longitudeHours, longitudeDecimalMinutes, longitudeHemisphere));

                #endregion
            }
            else
            {
                _Position = Position.Invalid;
            }

            // Do we have enough info to process speed?
            if (wordCount >= 7 && words[6].Length != 0)
            {
                #region Speed

                // The speed is the sixth word, expressed in knots                
                _Speed = new Speed(double.Parse(words[6], NmeaCultureInfo), SpeedUnit.Knots);

                #endregion
            }
            else
            {
                // The speed is invalid
                _Speed = Speed.Invalid;
            }

            // do we have enough info to process the bearing?
            if (wordCount >= 8 && words[7].Length != 0)
            {
                #region Bearing

                // The bearing is the seventh word
                _Bearing = new Azimuth(double.Parse(words[7], NmeaCultureInfo));

                #endregion
            }
            else
            {
                // The bearing is invalid
                _Bearing = Azimuth.Invalid;
            }

            // Do we have enough info for magnetic variation?
            if (wordCount >= 10 && words[9].Length != 0)
            {
                // Parse the value
                _MagneticVariation = new Longitude(double.Parse(words[9], NmeaCultureInfo));
            }
            else
            {
                // The magnetic variation is invalid
                _MagneticVariation = Longitude.Invalid;
            }
        }
예제 #6
0
        protected override void OnSentenceChanged()
        {
            // Parse the basic sentence information
            base.OnSentenceChanged();

            // Cache the words
            string[] words = base.Words;
            int wordCount = words.Length;

            // Do we have enough words to make a lat/long location?
            if (wordCount >= 4 && words[0].Length != 0 && words[1].Length != 0 && words[2].Length != 0 && words[3].Length != 0)
            {
                #region Latitude

                string latitudeWord = words[0];
                int latitudeHours = int.Parse(latitudeWord.Substring(0, 2), NmeaCultureInfo);                            
                double latitudeDecimalMinutes = double.Parse(latitudeWord.Substring(2), NmeaCultureInfo);                
                LatitudeHemisphere latitudeHemisphere =
                    words[1].Equals("N", StringComparison.OrdinalIgnoreCase) ? LatitudeHemisphere.North : LatitudeHemisphere.South;         

                #endregion

                #region Longitude

                string longitudeWord = words[2];
                int longitudeHours = int.Parse(longitudeWord.Substring(0, 3), NmeaCultureInfo);
                double longitudeDecimalMinutes = double.Parse(longitudeWord.Substring(3), NmeaCultureInfo);                
                LongitudeHemisphere longitudeHemisphere =
                    words[3].Equals("E", StringComparison.OrdinalIgnoreCase) ? LongitudeHemisphere.East : LongitudeHemisphere.West;           

                #endregion

                #region Position

                _Position = new Position(
                                new Latitude(latitudeHours, latitudeDecimalMinutes, latitudeHemisphere),
                                new Longitude(longitudeHours, longitudeDecimalMinutes, longitudeHemisphere));

                #endregion
            }


            // Do we have enough data to process the UTC time?
            if (wordCount >= 5 && words[4].Length != 0)
            {
                #region UTC Time

                string utcTimeWord = words[4];
                int utcHours = int.Parse(utcTimeWord.Substring(0, 2), NmeaCultureInfo);
                int utcMinutes = int.Parse(utcTimeWord.Substring(2, 2), NmeaCultureInfo);
                int utcSeconds = int.Parse(utcTimeWord.Substring(4, 2), NmeaCultureInfo);
                int utcMilliseconds = 0;
                if (utcTimeWord.Length > 6)
                    utcMilliseconds = Convert.ToInt32(float.Parse(utcTimeWord.Substring(6), NmeaCultureInfo) * 1000, NmeaCultureInfo);

                // Build a TimeSpan for this value
                _UtcTime = new TimeSpan(0, utcHours, utcMinutes, utcSeconds, utcMilliseconds);

                #endregion
            }
            else
            {
                // The UTC time is invalid
                _UtcTime = TimeSpan.MinValue;
            }


            // Do we have enough data to get the fix status?
            if (wordCount >= 6 && words[5].Length != 0)
            {
                #region Fix Status

                // An "A" means a valid fix
                _FixStatus = words[5].Equals("A", StringComparison.OrdinalIgnoreCase) ? FixStatus.Fix : FixStatus.NoFix;

                #endregion
            }
            else
            {
                // The fix status is invalid
                _FixStatus = FixStatus.Unknown;
            }
        }
예제 #7
0
        protected override void OnSentenceChanged()
        {
            // First, process the basic info for the sentence
            base.OnSentenceChanged();

            // Cache the sentence words
            string[] words     = base.Words;
            int      wordCount = words.Length;

            /*
             * $GPRMC
             *
             *   Recommended minimum specific GPS/Transit data
             *
             *   eg1. $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
             *   eg2. $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
             *
             *
             *              225446       Time of fix 22:54:46 UTC
             *              A            Navigation receiver warning A = OK, V = warning
             *              4916.45,N    Latitude 49 deg. 16.45 min North
             *              12311.12,W   Longitude 123 deg. 11.12 min West
             *              000.5        Speed over ground, Knots
             *              054.7        Course Made Good, True
             *              191194       Date of fix  19 November 1994
             *              020.3,E      Magnetic variation 20.3 deg East
             * 68          mandatory checksum
             *
             *
             *   eg3. $GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
             *                 1    2    3    4    5     6    7    8      9     10  11 12
             *
             *
             *         1   220516     Time Stamp
             *         2   A          validity - A-ok, V-invalid
             *         3   5133.82    current Latitude
             *         4   N          North/South
             *         5   00042.24   current Longitude
             *         6   W          East/West
             *         7   173.8      Speed in knots
             *         8   231.8      True course
             *         9   130694     Date Stamp
             *         10  004.2      Variation
             *         11  W          East/West
             *         12  *70        checksum
             *
             *
             *   eg4. $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
             *   1    = UTC of position fix
             *   2    = Data status (V=navigation receiver warning)
             *   3    = Latitude of fix
             *   4    = N or S
             *   5    = Longitude of fix
             *   6    = E or W
             *   7    = Speed over ground in knots
             *   8    = Track made good in degrees True
             *   9    = UT date
             *   10   = Magnetic variation degrees (Easterly var. subtracts from true course)
             *   11   = E or W
             *   12   = Checksum
             */


            // Do we have enough words to parse the fix status?
            if (wordCount >= 2 && words[1].Length != 0)
            {
                #region Fix status

                // Get the fix flag
                _FixStatus = words[1].Equals("A", StringComparison.OrdinalIgnoreCase) ? FixStatus.Fix : FixStatus.NoFix;

                #endregion
            }
            else
            {
                // The fix status is invalid
                _FixStatus = FixStatus.Unknown;
            }

            // Do we have enough words to parse the UTC date/time?
            if (wordCount >= 9 && words[0].Length != 0 && words[8].Length != 0)
            {
                #region Parse the UTC time

                string utcTimeWord     = words[0];
                int    utcHours        = int.Parse(utcTimeWord.Substring(0, 2), NmeaCultureInfo);       // AA
                int    utcMinutes      = int.Parse(utcTimeWord.Substring(2, 2), NmeaCultureInfo);       // BB
                int    utcSeconds      = int.Parse(utcTimeWord.Substring(4, 2), NmeaCultureInfo);       // CC
                int    utcMilliseconds = 0;
                if (utcTimeWord.Length > 6)
                {
                    utcMilliseconds = Convert.ToInt32(float.Parse(utcTimeWord.Substring(6), NmeaCultureInfo) * 1000, NmeaCultureInfo);    // DDDD
                }
                #endregion

                #region Parse the UTC date

                string utcDateWord = words[8];
                int    utcDay      = int.Parse(utcDateWord.Substring(0, 2), NmeaCultureInfo);
                int    utcMonth    = int.Parse(utcDateWord.Substring(2, 2), NmeaCultureInfo);
                int    utcYear     = int.Parse(utcDateWord.Substring(4, 2), NmeaCultureInfo) + 2000;

                #endregion

                #region Build a UTC date/time

                _UtcDateTime = new DateTime(utcYear, utcMonth, utcDay, utcHours, utcMinutes, utcSeconds, utcMilliseconds, DateTimeKind.Utc);

                #endregion
            }
            else
            {
                // The UTC date/time is invalid
                _UtcDateTime = DateTime.MinValue;
            }

            // Do we have enough data to parse the location?
            if (wordCount >= 6 && words[2].Length != 0 && words[3].Length != 0 && words[4].Length != 0 && words[5].Length != 0)
            {
                #region Parse the latitude

                string             latitudeWord           = words[2];
                int                latitudeHours          = int.Parse(latitudeWord.Substring(0, 2), NmeaCultureInfo);
                double             latitudeDecimalMinutes = double.Parse(latitudeWord.Substring(2), NmeaCultureInfo);
                LatitudeHemisphere latitudeHemisphere     =
                    words[3].Equals("N", StringComparison.Ordinal) ? LatitudeHemisphere.North : LatitudeHemisphere.South;

                #endregion

                #region Parse the longitude

                string longitudeWord                    = words[4];
                int    longitudeHours                   = int.Parse(longitudeWord.Substring(0, 3), NmeaCultureInfo);
                double longitudeDecimalMinutes          = double.Parse(longitudeWord.Substring(3), NmeaCultureInfo);
                LongitudeHemisphere longitudeHemisphere =
                    words[5].Equals("E", StringComparison.Ordinal) ? LongitudeHemisphere.East : LongitudeHemisphere.West;

                #endregion

                #region Build a Position from the latitude and longitude

                _Position = new Position(
                    new Latitude(latitudeHours, latitudeDecimalMinutes, latitudeHemisphere),
                    new Longitude(longitudeHours, longitudeDecimalMinutes, longitudeHemisphere));

                #endregion
            }
            else
            {
                _Position = Position.Invalid;
            }

            // Do we have enough info to process speed?
            if (wordCount >= 7 && words[6].Length != 0)
            {
                #region Speed

                // The speed is the sixth word, expressed in knots
                _Speed = new Speed(double.Parse(words[6], NmeaCultureInfo), SpeedUnit.Knots);

                #endregion
            }
            else
            {
                // The speed is invalid
                _Speed = Speed.Invalid;
            }

            // do we have enough info to process the bearing?
            if (wordCount >= 8 && words[7].Length != 0)
            {
                #region Bearing

                // The bearing is the seventh word
                _Bearing = new Azimuth(double.Parse(words[7], NmeaCultureInfo));

                #endregion
            }
            else
            {
                // The bearing is invalid
                _Bearing = Azimuth.Invalid;
            }

            // Do we have enough info for magnetic variation?
            if (wordCount >= 10 && words[9].Length != 0)
            {
                // Parse the value
                _MagneticVariation = new Longitude(double.Parse(words[9], NmeaCultureInfo));
            }
            else
            {
                // The magnetic variation is invalid
                _MagneticVariation = Longitude.Invalid;
            }
        }
예제 #8
0
        /// <summary>
        /// Updates the fix status to the specified value.
        /// </summary>
        /// <param name="value">The value.</param>
        protected virtual void SetFixStatus(FixStatus value)
        {
            // If the new value is the same or it's invalid, ignore it
            if (value == _fixStatus || value == FixStatus.Unknown)
                return;

            // Set the new status
            _fixStatus = value;

            DeviceEventArgs e = new DeviceEventArgs(_device);

            // Is a fix acquired or lost?
            if (_fixStatus == FixStatus.Fix)
            {
                // Acquired.
                if (FixAcquired != null)
                    FixAcquired(this, e);

                Devices.RaiseFixAcquired(e);
            }
            else
            {
                // Lost.
                if (FixLost != null)
                    FixLost(this, e);

                Devices.RaiseFixLost(e);
            }
        }
예제 #9
0
 /// <summary>
 /// Does the initialize.
 /// </summary>
 private void DoInitialize()
 {
     _altitude = Distance.Invalid;
     _altitudeAboveEllipsoid = _altitude;
     _bearing = Azimuth.Invalid;
     _heading = Azimuth.Invalid;
     _fixStatus = FixStatus.Unknown;
     _horizontalDop = DilutionOfPrecision.Maximum;
     _magneticVariation = Longitude.Invalid;
     _position = Position.Invalid;
     _speed = Speed.Invalid;
     _meanDop = DilutionOfPrecision.Invalid;
     _verticalDop = DilutionOfPrecision.Invalid;
     if (_satellites != null)
         _satellites.Clear();
 }
예제 #10
0
        protected override void OnSentenceChanged()
        {
            // Parse the basic sentence information
            base.OnSentenceChanged();

            // Cache the words
            string[] words     = base.Words;
            int      wordCount = words.Length;

            // Do we have enough words to make a lat/long location?
            if (wordCount >= 4 && words[0].Length != 0 && words[1].Length != 0 && words[2].Length != 0 && words[3].Length != 0)
            {
                #region Latitude

                string             latitudeWord           = words[0];
                int                latitudeHours          = int.Parse(latitudeWord.Substring(0, 2), NmeaCultureInfo);
                double             latitudeDecimalMinutes = double.Parse(latitudeWord.Substring(2), NmeaCultureInfo);
                LatitudeHemisphere latitudeHemisphere     =
                    words[1].Equals("N", StringComparison.OrdinalIgnoreCase) ? LatitudeHemisphere.North : LatitudeHemisphere.South;

                #endregion

                #region Longitude

                string longitudeWord                    = words[2];
                int    longitudeHours                   = int.Parse(longitudeWord.Substring(0, 3), NmeaCultureInfo);
                double longitudeDecimalMinutes          = double.Parse(longitudeWord.Substring(3), NmeaCultureInfo);
                LongitudeHemisphere longitudeHemisphere =
                    words[3].Equals("E", StringComparison.OrdinalIgnoreCase) ? LongitudeHemisphere.East : LongitudeHemisphere.West;

                #endregion

                #region Position

                _Position = new Position(
                    new Latitude(latitudeHours, latitudeDecimalMinutes, latitudeHemisphere),
                    new Longitude(longitudeHours, longitudeDecimalMinutes, longitudeHemisphere));

                #endregion
            }


            // Do we have enough data to process the UTC time?
            if (wordCount >= 5 && words[4].Length != 0)
            {
                #region UTC Time

                string utcTimeWord     = words[4];
                int    utcHours        = int.Parse(utcTimeWord.Substring(0, 2), NmeaCultureInfo);
                int    utcMinutes      = int.Parse(utcTimeWord.Substring(2, 2), NmeaCultureInfo);
                int    utcSeconds      = int.Parse(utcTimeWord.Substring(4, 2), NmeaCultureInfo);
                int    utcMilliseconds = 0;
                if (utcTimeWord.Length > 6)
                {
                    utcMilliseconds = Convert.ToInt32(float.Parse(utcTimeWord.Substring(6), NmeaCultureInfo) * 1000, NmeaCultureInfo);
                }

                // Build a TimeSpan for this value
                _UtcTime = new TimeSpan(0, utcHours, utcMinutes, utcSeconds, utcMilliseconds);

                #endregion
            }
            else
            {
                // The UTC time is invalid
                _UtcTime = TimeSpan.MinValue;
            }


            // Do we have enough data to get the fix status?
            if (wordCount >= 6 && words[5].Length != 0)
            {
                #region Fix Status

                // An "A" means a valid fix
                _FixStatus = words[5].Equals("A", StringComparison.OrdinalIgnoreCase) ? FixStatus.Fix : FixStatus.NoFix;

                #endregion
            }
            else
            {
                // The fix status is invalid
                _FixStatus = FixStatus.Unknown;
            }
        }