Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Rmb"/> class.
        /// </summary>
        /// <param name="type">The message type</param>
        /// <param name="message">The NMEA message values.</param>
        public Rmb(string type, string[] message) : base(type, message)
        {
            if (message == null || message.Length < 13)
            {
                throw new ArgumentException("Invalid GPRMB", "message");
            }

            Status = message[0] == "A" ? DataStatus.Ok : Rmb.DataStatus.Warning;
            double tmp;

            if (double.TryParse(message[1], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
            {
                CrossTrackError = tmp;

                if (message[2] == "L") //Steer left
                {
                    CrossTrackError *= -1;
                }
            }
            else
            {
                CrossTrackError = double.NaN;
            }

            if (message[3].Length > 0)
            {
                OriginWaypointId = int.Parse(message[3], CultureInfo.InvariantCulture);
            }
            if (message[3].Length > 0)
            {
                DestinationWaypointId = int.Parse(message[4], CultureInfo.InvariantCulture);
            }
            DestinationLatitude  = NmeaMessage.StringToLatitude(message[5], message[6]);
            DestinationLongitude = NmeaMessage.StringToLongitude(message[7], message[8]);
            if (double.TryParse(message[9], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
            {
                RangeToDestination = tmp;
            }
            else
            {
                RangeToDestination = double.NaN;
            }
            if (double.TryParse(message[10], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
            {
                TrueBearing = tmp;
            }
            else
            {
                TrueBearing = double.NaN;
            }
            if (double.TryParse(message[11], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
            {
                Velocity = tmp;
            }
            else
            {
                Velocity = double.NaN;
            }
            Arrived = message[12] == "A";
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Gga"/> class.
        /// </summary>
        /// <param name="type">The message type</param>
        /// <param name="message">The NMEA message values.</param>
        public Gga(string type, string[] message) : base(type, message)
        {
            if (message == null || message.Length < 14)
            {
                throw new ArgumentException("Invalid GPGGA", "message");
            }
            FixTime            = StringToTimeSpan(message[0]);
            Latitude           = NmeaMessage.StringToLatitude(message[1], message[2]);
            Longitude          = NmeaMessage.StringToLongitude(message[3], message[4]);
            Quality            = (Gga.FixQuality) int.Parse(message[5], CultureInfo.InvariantCulture);
            NumberOfSatellites = int.Parse(message[6], CultureInfo.InvariantCulture);
            Hdop               = NmeaMessage.StringToDouble(message[7]);
            Altitude           = NmeaMessage.StringToDouble(message[8]);
            AltitudeUnits      = message[9];
            HeightOfGeoid      = NmeaMessage.StringToDouble(message[10]);
            HeightOfGeoidUnits = message[11];
            var timeInSeconds = StringToDouble(message[12]);

            if (!double.IsNaN(timeInSeconds))
            {
                TimeSinceLastDgpsUpdate = TimeSpan.FromSeconds(timeInSeconds);
            }
            else
            {
                TimeSinceLastDgpsUpdate = TimeSpan.MaxValue;
            }
            if (message[13].Length > 0)
            {
                DgpsStationId = int.Parse(message[13], CultureInfo.InvariantCulture);
            }
            else
            {
                DgpsStationId = -1;
            }
        }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Gll"/> class.
        /// </summary>
        /// <param name="type">The message type</param>
        /// <param name="message">The NMEA message values.</param>
        public Gll(string type, string[] message) : base(type, message)
        {
            if (message == null || message.Length < 4)
            {
                throw new ArgumentException("Invalid GPGLL", "message");
            }
            Latitude  = NmeaMessage.StringToLatitude(message[0], message[1]);
            Longitude = NmeaMessage.StringToLongitude(message[2], message[3]);
            if (message.Length >= 5)             //Some older GPS doesn't broadcast fix time
            {
                FixTime = StringToTimeSpan(message[4]);
            }
            DataActive    = (message.Length < 6 || message[5] == "A");
            ModeIndicator = DataActive ? Mode.Autonomous : Mode.DataNotValid;
            if (message.Length > 6)
            {
                switch (message[6])
                {
                case "A": ModeIndicator = Mode.Autonomous; break;

                case "D": ModeIndicator = Mode.DataNotValid; break;

                case "E": ModeIndicator = Mode.EstimatedDeadReckoning; break;

                case "M": ModeIndicator = Mode.Manual; break;

                case "S": ModeIndicator = Mode.Simulator; break;

                case "N": ModeIndicator = Mode.DataNotValid; break;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Rmc"/> class.
        /// </summary>
        /// <param name="type">The message type</param>
        /// <param name="message">The NMEA message values.</param>
        public Rmc(string type, string[] message) : base(type, message)
        {
            if (message == null || message.Length < 11)
            {
                throw new ArgumentException("Invalid GPRMC", "message");
            }

            if (message[8].Length == 6 && message[0].Length >= 6)
            {
                FixTime = new DateTime(int.Parse(message[8].Substring(4, 2), CultureInfo.InvariantCulture) + 2000,
                                       int.Parse(message[8].Substring(2, 2), CultureInfo.InvariantCulture),
                                       int.Parse(message[8].Substring(0, 2), CultureInfo.InvariantCulture),
                                       int.Parse(message[0].Substring(0, 2), CultureInfo.InvariantCulture),
                                       int.Parse(message[0].Substring(2, 2), CultureInfo.InvariantCulture),
                                       0, DateTimeKind.Utc).AddSeconds(double.Parse(message[0].Substring(4), CultureInfo.InvariantCulture));
            }
            Active            = (message[1] == "A");
            Latitude          = NmeaMessage.StringToLatitude(message[2], message[3]);
            Longitude         = NmeaMessage.StringToLongitude(message[4], message[5]);
            Speed             = NmeaMessage.StringToDouble(message[6]);
            Course            = NmeaMessage.StringToDouble(message[7]);
            MagneticVariation = NmeaMessage.StringToDouble(message[9]);
            if (!double.IsNaN(MagneticVariation) && message[10] == "W")
            {
                MagneticVariation *= -1;
            }
        }
Example #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Gns"/> class.
        /// </summary>
        /// <param name="type">The message type</param>
        /// <param name="message">The NMEA message values.</param>
        public Gns(string type, string[] message) : base(type, message)
        {
            if (message == null || message.Length < 12)
            {
                throw new ArgumentException("Invalid GNS", "message");
            }
            FixTime   = StringToTimeSpan(message[0]);
            Latitude  = NmeaMessage.StringToLatitude(message[1], message[2]);
            Longitude = NmeaMessage.StringToLongitude(message[3], message[4]);
            if (message[5].Length > 0)
            {
                GpsModeIndicator = ParseModeIndicator(message[5][0]);
            }
            if (message[5].Length > 1)
            {
                GlonassModeIndicator = ParseModeIndicator(message[5][1]);
            }
            if (message[5].Length > 2)
            {
                FutureModeIndicator = message[5].Skip(2).Select(t => ParseModeIndicator(t)).ToArray();
            }
            else
            {
                FutureModeIndicator = new Mode[] { }
            };
            NumberOfSatellites = int.Parse(message[6], CultureInfo.InvariantCulture);
            Hdop              = NmeaMessage.StringToDouble(message[7]);
            OrhometricHeight  = NmeaMessage.StringToDouble(message[8]);
            GeoidalSeparation = NmeaMessage.StringToDouble(message[9]);
            var timeInSeconds = StringToDouble(message[10]);

            if (!double.IsNaN(timeInSeconds))
            {
                TimeSinceLastDgpsUpdate = TimeSpan.FromSeconds(timeInSeconds);
            }
            else
            {
                TimeSinceLastDgpsUpdate = TimeSpan.MaxValue;
            }
            if (message[11].Length > 0)
            {
                DgpsStationId = message[11];
            }

            if (message.Length > 12)
            {
                switch (message[12])
                {
                case "S": Status = NavigationalStatus.Safe; break;

                case "C": Status = NavigationalStatus.Caution; break;

                case "U": Status = NavigationalStatus.Unsafe; break;

                case "V":
                default: Status = NavigationalStatus.NotValid; break;
                }
            }
        }
Example #6
0
        /// <summary>
        /// Parses the specified NMEA message.
        /// </summary>
        /// <param name="message">The NMEA message string.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">
        /// Invalid nmea message: Missing starting character '$'
        /// or checksum failure
        /// </exception>
        public static NmeaMessage Parse(string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                throw new ArgumentNullException("message");
            }

            int checksum = -1;

            if (message[0] != '$')
            {
                throw new ArgumentException("Invalid nmea message: Missing starting character '$'");
            }
            var idx = message.IndexOf('*');

            if (idx >= 0)
            {
                checksum = Convert.ToInt32(message.Substring(idx + 1), 16);
                message  = message.Substring(0, message.IndexOf('*'));
            }
            if (checksum > -1)
            {
                int checksumTest = 0;
                for (int i = 1; i < message.Length; i++)
                {
                    checksumTest ^= Convert.ToByte(message[i]);
                }
                if (checksum != checksumTest)
                {
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Invalid nmea message: Checksum failure. Got {0:X2}, Expected {1:X2}", checksum, checksumTest));
                }
            }

            string[] parts       = message.Split(new char[] { ',' });
            string   MessageType = parts[0].Substring(1);

            string[] MessageParts = parts.Skip(1).ToArray();
            if (messageTypes == null)
            {
                LoadResponseTypes();
            }
            NmeaMessage msg = null;

            if (messageTypes.ContainsKey(MessageType))
            {
                msg = (NmeaMessage)messageTypes[MessageType].Invoke(new object[] { });
            }
            else
            {
                msg = new UnknownMessage();
            }
            msg.MessageType  = MessageType;
            msg.MessageParts = MessageParts;
            msg.OnLoadMessage(MessageParts);
            return(msg);
        }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Vtg"/> class.
 /// </summary>
 /// <param name="type">The message type</param>
 /// <param name="message">The NMEA message values.</param>
 public Vtg(string type, string[] message) : base(type, message)
 {
     if (message == null || message.Length < 7)
     {
         throw new ArgumentException("Invalid Gpvtg", "message");
     }
     TrueCourseOverGround     = NmeaMessage.StringToDouble(message[0]);
     MagneticCourseOverGround = NmeaMessage.StringToDouble(message[2]);
     SpeedInKnots             = NmeaMessage.StringToDouble(message[4]);
     SpeedInKph = NmeaMessage.StringToDouble(message[6]);
 }
Example #8
0
 /// <summary>
 /// Called when the message is being loaded.
 /// </summary>
 /// <param name="message">The NMEA message values.</param>
 protected override void OnLoadMessage(string[] message)
 {
     if (message == null || message.Length < 14)
     {
         throw new ArgumentException("Invalid GPGGA", "message");
     }
     FixTime   = StringToTimeSpan(message[0]);
     Validity  = message[1];
     Latitude  = NmeaMessage.StringToLatitude(message[2], message[3]);
     Longitude = NmeaMessage.StringToLongitude(message[4], message[5]);
     Sog       = Double.Parse(message[5], CultureInfo.InvariantCulture);
     Cog       = Double.Parse(message[6], CultureInfo.InvariantCulture);
     DateOfFix = message[7];
 }
Example #9
0
 /// <summary>
 /// Called when the message is being loaded.
 /// </summary>
 /// <param name="message">The NMEA message values.</param>
 protected override void OnLoadMessage(string[] message)
 {
     if (message == null || message.Length < 4)
     {
         throw new ArgumentException("Invalid GPGLL", "message");
     }
     Latitude  = NmeaMessage.StringToLatitude(message[0], message[1]);
     Longitude = NmeaMessage.StringToLongitude(message[2], message[3]);
     if (message.Length >= 5)             //Some older GPS doesn't broadcast fix time
     {
         FixTime = StringToTimeSpan(message[4]);
     }
     DataActive = (message.Length < 6 || message[5] == "A");
 }
Example #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Gst"/> class.
 /// </summary>
 /// <param name="type">The message type</param>
 /// <param name="message">The NMEA message values.</param>
 public Gst(string type, string[] message) : base(type, message)
 {
     if (message == null || message.Length < 8)
     {
         throw new ArgumentException("Invalid GPGST", "message");
     }
     FixTime             = StringToTimeSpan(message[0]);
     Rms                 = NmeaMessage.StringToDouble(message[1]);
     SemiMajorError      = NmeaMessage.StringToDouble(message[2]);
     SemiMinorError      = NmeaMessage.StringToDouble(message[3]);
     ErrorOrientation    = NmeaMessage.StringToDouble(message[4]);
     SigmaLatitudeError  = NmeaMessage.StringToDouble(message[5]);
     SigmaLongitudeError = NmeaMessage.StringToDouble(message[6]);
     SigmaHeightError    = NmeaMessage.StringToDouble(message[7]);
 }
Example #11
0
        private void OnMessageReceived(Nmea.NmeaMessage msg)
        {
            var args  = new NmeaMessageReceivedEventArgs(msg);
            var multi = msg as IMultiPartMessage;

            if (multi != null)
            {
                args.IsMultipart = true;
                if (MultiPartMessageCache.ContainsKey(msg.MessageType))
                {
                    var dic = MultiPartMessageCache[msg.MessageType];
                    if (dic.ContainsKey(multi.MessageNumber - 1) && !dic.ContainsKey(multi.MessageNumber))
                    {
                        dic[multi.MessageNumber] = msg;
                    }
                    else //Something is out of order. Clear cache
                    {
                        MultiPartMessageCache.Remove(msg.MessageType);
                    }
                }
                else if (multi.MessageNumber == 1)
                {
                    MultiPartMessageCache[msg.MessageType]    = new Dictionary <int, Nmea.NmeaMessage>(multi.TotalMessages);
                    MultiPartMessageCache[msg.MessageType][1] = msg;
                }
                if (MultiPartMessageCache.ContainsKey(msg.MessageType))
                {
                    var dic = MultiPartMessageCache[msg.MessageType];
                    if (dic.Count == multi.TotalMessages) //We have a full list
                    {
                        MultiPartMessageCache.Remove(msg.MessageType);
                        args.MessageParts = dic.Values.ToArray();
                    }
                }
            }

            if (MessageReceived != null)
            {
                MessageReceived(this, args);
            }
        }
Example #12
0
        private void OnMessageReceived(Nmea.NmeaMessage msg)
        {
            if (msg == null)
            {
                return;
            }
            Nmea.NmeaMessage[]? messageParts = null;
            if (msg is IMultiPartMessage multi)
            {
                string messageType = msg.MessageType.Substring(2); //We don't care about the two first characters. Ie GPGSV, GLGSV, GAGSV etc are all part of the same multi-part message
                if (MultiPartMessageCache.ContainsKey(messageType))
                {
                    var dic = MultiPartMessageCache[messageType];
                    if (dic.ContainsKey(multi.MessageNumber - 1) && !dic.ContainsKey(multi.MessageNumber))
                    {
                        dic[multi.MessageNumber] = msg;
                    }
                    else //Something is out of order. Clear cache
                    {
                        MultiPartMessageCache.Remove(messageType);
                    }
                }
                else if (multi.MessageNumber == 1)
                {
                    MultiPartMessageCache[messageType]    = new Dictionary <int, Nmea.NmeaMessage>(multi.TotalMessages);
                    MultiPartMessageCache[messageType][1] = msg;
                }
                if (MultiPartMessageCache.ContainsKey(messageType))
                {
                    var dic = MultiPartMessageCache[messageType];
                    if (dic.Count == multi.TotalMessages) //We have a full list
                    {
                        MultiPartMessageCache.Remove(messageType);
                        messageParts = dic.Values.ToArray();
                    }
                }
            }

            MessageReceived?.Invoke(this, new NmeaMessageReceivedEventArgs(msg, messageParts));
        }
Example #13
0
 internal NmeaMessageReceivedEventArgs(Nmea.NmeaMessage message)
 {
     Message = message;
 }
Example #14
0
 internal NmeaMessageReceivedEventArgs(Nmea.NmeaMessage message, IReadOnlyList <Nmea.NmeaMessage>?messageParts)
 {
     Message      = message;
     MessageParts = messageParts;
 }