public static bool TryParse(string rawNmeaRmcString, out RmcData rmcData) { try { rmcData = Parse(rawNmeaRmcString); return(true); } catch { rmcData = null; return(false); } }
//======================================================================= //======================================================================= #region -= constructors =- #endregion //======================================================================= //======================================================================= #region -= public methods =- #endregion //======================================================================= //======================================================================= #region -= static methods =- public static RmcData Parse(string inputString) { //---- declare vars RmcData rmcData = new RmcData(); string dataString = inputString.Substring(0, inputString.IndexOf('*')); // strip off the checksum string[] values = dataString.Split(','); //---- if we don't have 12 (header + 11), it's no good if (values.Length < 12) { return(rmcData); } //---- Status if (values[2].ToUpper() == "A") { rmcData.Status = Status.Valid; } else { rmcData.Status = Status.Invalid; } //---- if the date and time both are six digits if (values[1].Length >= 6 && values[9].Length == 6) { //---- make sure that they're actually numbers int temp; if (int.TryParse(values[1].Substring(0, 6), out temp) && int.TryParse(values[9], out temp)) { //---- should add more validation here int day = int.Parse(values[9].Substring(0, 2)); int month = int.Parse(values[9].Substring(2, 2)); // assume same century int year = int.Parse(values[9].Substring(4, 2)) + (DateTime.Now.Year / 100) * 100; // Fix for timestamps from previous century // RMC format does not allow us to detect older than 100 years though if (year > DateTime.Now.Year) { year -= 100; } int hour = int.Parse(values[1].Substring(0, 2)); int minute = int.Parse(values[1].Substring(2, 2)); int second = int.Parse(values[1].Substring(4, 2)); rmcData.UtcDateTime = new DateTime(year, month, day, hour, minute, second); // Timestamp may have higher granularity than seconds, this fix handles that. if (values[1].Length > 7) { int extraDigits = values[1].Length - 7; int partSeconds = int.Parse(values[1].Substring(7)); rmcData.UtcDateTime.Add(TimeSpan.FromSeconds((double)partSeconds / System.Math.Pow(10, extraDigits))); } } } else if (values[1].Length >= 9) { //---- should add more validation here int hour = int.Parse(values[1].Substring(0, 2)); int minute = int.Parse(values[1].Substring(2, 2)); int second = int.Parse(values[1].Substring(4, 2)); int millisecond = 0; if (values[1].Length >= 9) { millisecond = Convert.ToInt32(double.Parse(values[1].Substring(6, 3)) * 1000); } rmcData.UtcDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, minute, second, millisecond); } //---- lat/long position rmcData.Position = Position.Parse(values[3] + "," + values[4] + ";" + values[5] + "," + values[6]); //一节也是1.852公里/小时 //---- speed in km rmcData.GroundSpeed = Decimal.Parse(values[7]) * 1.852m; ////---- speed in knots //rmcData.GroundSpeed = Decimal.Parse(values[7]); //---- true course rmcData.Heading = values[8].Length == 0 ? 0 : Decimal.Parse(values[8]); //---- magnetic declination MagneticVariation mag = null; MagneticVariation.TryParse(values[10] + "," + values[11], out mag); rmcData.MagneticVariation = mag; //---- return return(rmcData); //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 }
private static void ParseSentence(GpsReading gpsReading, string sentence) { var cmd = ParseCommand(sentence); if (string.IsNullOrEmpty(cmd)) { return; } //GPNTR switch (cmd.ToUpper()) { case "$GPGGA": case "$GNGGA": case "$BDGGA": gpsReading.FixedGpsData = GgaData.Parse(sentence); break; case "$GPVTG": case "$GNVTG": case "$BDVTG": gpsReading.GroundVector = VtgData.Parser(sentence); break; case "$GPRMC": case "$GNRMC": case "$BDRMC": gpsReading.Summary = RmcData.Parse(sentence); break; case "#HEADINGA": gpsReading.Heading = HgaData.Parse(sentence); break; case "#BESTUTMA": gpsReading.Utm = UtmData.Parse(sentence); break; case "$GPNTR": gpsReading.NtrData = NtrData.Parse(sentence); break; //case "$GPGSA": // gpsReading.DopActiveSatellites = GsaData.Parse(sentence); // break; //case "$GPGSV": // gpsReading.SatellitesInView.Add(GsvData.Parse(sentence)); // break; //case "$GPHDT": // gpsReading.HdtData = HdtData.Parse(sentence); // break; case "$PTNL": if (sentence.IndexOf("AVR", System.StringComparison.Ordinal) > 0) { gpsReading.AvrData = AvrData.Parse(sentence); } else if (sentence.IndexOf("VGK", System.StringComparison.Ordinal) > 0) { gpsReading.VgkData = VgkData.Parse(sentence); } break; } }