public void Parse(NmeaSentence sentence) { /* NMEA data is parsed in a specific order to maximize data quality and also to reduce latency * problems. The date/time is processed first to minimize latency. Then, dilution of precision * values are processed. Finally, if precision is good enough to work with, remaining values are * processed. */ // Is this a fix method message? IFixMethodSentence fixMethodSentence = sentence as IFixMethodSentence; if (fixMethodSentence != null) SetFixMethod(fixMethodSentence.FixMethod); // Is this a fix quality message? IFixQualitySentence fixQualitySentence = sentence as IFixQualitySentence; if (fixQualitySentence != null) SetFixQuality(fixQualitySentence.FixQuality); #region Process common GPS information // If a fix is required, don't process time if (!IsFixRequired || (IsFixRequired && IsFixed)) { // Does this sentence support the UTC date and time? IUtcDateTimeSentence dateTimeSentence = sentence as IUtcDateTimeSentence; if (dateTimeSentence != null) SetDateTimes(dateTimeSentence.UtcDateTime); /* Some NMEA sentences provide UTC time information, but no date! To make this work, * we must combine the time report with the current UTC date. */ IUtcTimeSentence timeSentence = sentence as IUtcTimeSentence; if (timeSentence != null && !timeSentence.UtcTime.Equals(TimeSpan.MinValue) && !timeSentence.UtcTime.Equals(TimeSpan.Zero)) SetDateTimes(new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, timeSentence.UtcTime.Hours, timeSentence.UtcTime.Minutes, timeSentence.UtcTime.Seconds, timeSentence.UtcTime.Milliseconds, DateTimeKind.Utc)); } // Does this sentence support horizontal DOP? IHorizontalDilutionOfPrecisionSentence hdopSentence = sentence as IHorizontalDilutionOfPrecisionSentence; if (hdopSentence != null) SetHorizontalDilutionOfPrecision(hdopSentence.HorizontalDilutionOfPrecision); // Does the sentence support vertical DOP? IVerticalDilutionOfPrecisionSentence vdopSentence = sentence as IVerticalDilutionOfPrecisionSentence; if (vdopSentence != null) SetVerticalDilutionOfPrecision(vdopSentence.VerticalDilutionOfPrecision); // Does the sentence support mean DOP? IPositionDilutionOfPrecisionSentence mdopSentence = sentence as IPositionDilutionOfPrecisionSentence; if (mdopSentence != null) SetMeanDilutionOfPrecision(mdopSentence.PositionDilutionOfPrecision); #endregion // If a fix is required, don't process time if (!IsFixRequired || (IsFixRequired && IsFixed)) { // Is precision good enough to work with? if (this.HorizontalDilutionOfPrecision.Value <= this.MaximumHorizontalDilutionOfPrecision.Value) { #region Process real-time positional data // Does this sentence support lat/long info? IPositionSentence positionSentence = sentence as IPositionSentence; if (positionSentence != null) SetPosition(positionSentence.Position); // Does this sentence support bearing? IBearingSentence bearingSentence = sentence as IBearingSentence; if (bearingSentence != null) SetBearing(bearingSentence.Bearing); // Does this sentence support speed? ISpeedSentence speedSentence = sentence as ISpeedSentence; if (speedSentence != null) SetSpeed(speedSentence.Speed); #endregion } // Is the vertical DOP low enough to be worth processing? if (this.VerticalDilutionOfPrecision.Value <= this.MaximumVerticalDilutionOfPrecision.Value) { #region Process altitude data // Does this sentence support altitude? IAltitudeSentence altitudeSentence = sentence as IAltitudeSentence; if (altitudeSentence != null) SetAltitude(altitudeSentence.Altitude); // Does this sentence support altitude? IAltitudeAboveEllipsoidSentence altitudeAboveEllipsoidSentence = sentence as IAltitudeAboveEllipsoidSentence; if (altitudeAboveEllipsoidSentence != null) SetAltitude(altitudeAboveEllipsoidSentence.AltitudeAboveEllipsoid); // Does this sentence support geoidal separation? IGeoidalSeparationSentence geoidSeparationSentence = sentence as IGeoidalSeparationSentence; if (geoidSeparationSentence != null) SetGeoidalSeparation(geoidSeparationSentence.GeoidalSeparation); #endregion } } #region Lower-priority information // Is this a fix mode sentence? IFixModeSentence fixModeSentence = sentence as IFixModeSentence; if (fixModeSentence != null) SetFixMode(fixModeSentence.FixMode); // Does this sentence have fix status? IFixStatusSentence fixedSentence = sentence as IFixStatusSentence; if (fixedSentence != null) SetFixStatus(fixedSentence.FixStatus); // Does this sentence support magnetic variation? IMagneticVariationSentence magVarSentence = sentence as IMagneticVariationSentence; if (magVarSentence != null) SetMagneticVariation(magVarSentence.MagneticVariation); // Process satellite data ISatelliteCollectionSentence satelliteSentence = sentence as ISatelliteCollectionSentence; if (satelliteSentence != null) { /* GPS.NET 2.0 performed thorough comparison of satellites in order to update * an *existing* instance of Satellite objects. I think now that this was overkill. * For performance and limited memory use, satellites are just overwritten. */ AppendSatellites(satelliteSentence.Satellites); } // Fixed satellite count IFixedSatelliteCountSentence fixedCountSentence = sentence as IFixedSatelliteCountSentence; if (fixedCountSentence != null) SetFixedSatelliteCount(fixedCountSentence.FixedSatelliteCount); // Process fixed satellites IFixedSatellitesSentence fixedSatellitesSentence = sentence as IFixedSatellitesSentence; if (fixedSatellitesSentence != null) { SetFixedSatellites(fixedSatellitesSentence.FixedSatellites); } #endregion }
protected void WriteSentenceToClient(NmeaSentence sentence) { // Get a byte array of the sentence byte[] sentenceBytes = sentence.ToByteArray(); /* Some customers were found to make an emulator, but then not actually read from it. * To prevent huge buffers, we will only write a sentence if the buffer can handle it. * Otherwise, we'll ignore it completely. */ if (ReadBuffer.Count + sentenceBytes.Length + 2 > ReadBuffer.Capacity) return; // Add the bytes ReadBuffer.AddRange(sentenceBytes); // Add a CrLf ReadBuffer.Add(13); ReadBuffer.Add(10); }
/// <summary> /// Process the valid NMEA sentence. Check which /// type of DVL message it is and create the data set. /// Then send the data set to the CurrentDataSetManager. /// </summary> /// <param name="sentence">Sentence to process.</param> private void ProcessSentence(NmeaSentence sentence) { // Check for PRTI01 if (sentence.CommandWord.EndsWith(RTI.Prti01Sentence.CMD_WORD_PRTI01, StringComparison.Ordinal)) { // Check if the previous PRTI01 was used // If it was not used, send the data if (_prti01 != null) { SendData(_prti01); _prti01 = null; } // Store the sentence to be combined with PRTI02 _prti01 = new Prti01Sentence(sentence.Sentence, sentence.CommandWord, sentence.Words, sentence.ExistingChecksum); } // Check for PRTI02 else if (sentence.CommandWord.EndsWith(RTI.Prti02Sentence.CMD_WORD_PRTI02, StringComparison.Ordinal)) { Prti02Sentence prti02 = new Prti02Sentence(sentence.Sentence, sentence.CommandWord, sentence.Words, sentence.ExistingChecksum); // Check if the PRTI01 and PRTI02 match // If they match, combine and send // If they do not match, send PRTI02 if (_prti01 != null && _prti01.SampleNumber == prti02.SampleNumber) { SendData(_prti01, prti02, _prti30, _prti31); _prti01 = null; } else { SendData(prti02); } } // Check for PRTI03 else if (sentence.CommandWord.EndsWith(RTI.Prti03Sentence.CMD_WORD_PRTI03, StringComparison.Ordinal)) { // Store the sentence to be combined with PRTI02 Prti03Sentence prti03 = new Prti03Sentence(sentence.Sentence, sentence.CommandWord, sentence.Words, sentence.ExistingChecksum); SendData(prti03); } // Check for PRTI30 else if (sentence.CommandWord.EndsWith(RTI.Prti30Sentence.CMD_WORD_PRTI30, StringComparison.Ordinal)) { // Store the sentence to be combined with PRTI01 and PRTI02 _prti30 = new Prti30Sentence(sentence.Sentence, sentence.CommandWord, sentence.Words, sentence.ExistingChecksum); } // Check for PRTI31 else if (sentence.CommandWord.EndsWith(RTI.Prti31Sentence.CMD_WORD_PRTI31, StringComparison.Ordinal)) { // Store the sentence to be combined with PRTI01 and PRTI02 _prti31 = new Prti31Sentence(sentence.Sentence, sentence.CommandWord, sentence.Words, sentence.ExistingChecksum); } else { // If the data was nether PRTI01 or PRTI02, then it must be GPS NMEA data and add it // to the NMEA buffer to be processed with a complete dataset AddNmeaData(sentence.Sentence + NMEA_END); } }
protected void OnSentenceRecorded(NmeaSentence sentence) { if (SentenceRecorded != null) SentenceRecorded(this, new NmeaSentenceEventArgs(sentence)); }
/// <summary> /// Creates a new instance of the Nmea Sentence Resolver Event arguments class /// </summary> /// <param name="sentence">The sentence.</param> public NmeaSentenceResolverEventArgs(NmeaSentence sentence) { _sentence = sentence; }
/// <summary> /// Find the first $. Then find the first start /// of a checksum. Remove the string of a complete /// NMEA sentence and check if its a valid sentence. /// If it is valid, process the sentence. /// </summary> private void ProcessDataThread( ) { while (_continue) { try { // Block until awoken when data is received // Timeout every 60 seconds to see if shutdown occured _eventWaitData.WaitOne(); // If wakeup was called to kill thread if (!_continue) { return; } // Ensure the data can contain NMEA sentences while (_buffer.Length > 0 && _buffer.Contains("$") && _buffer.Contains("*")) { // Find a sentence in the buffer string nmea = FindSentence(); // If one is found, process the data if (nmea.Length > 0) { // Create a NMEA sentence and verify its valid NmeaSentence sentence = new NmeaSentence(nmea); if (sentence.IsValid) { // Process sentence ProcessSentence(sentence); } } // If wakeup was called to kill thread if (!_continue) { return; } } } catch (ThreadAbortException) { // Thread is aborted to stop processing return; } catch (Exception e) { log.Error("Error processing binary codec data.", e); return; } // Send an event that processing is complete if (ProcessDataCompleteEvent != null) { ProcessDataCompleteEvent(); } } }
/// <summary> /// Parse the string of all valid NMEA sentences. /// Store them to the array. /// </summary> /// <param name="nmeaStrings">String containing NMEA sentences.</param> private void SetNmeaStringArray(string nmeaStrings) { LinkedList<NmeaSentence> list = new LinkedList<NmeaSentence>(); // Find the first $ while(nmeaStrings.Contains("$") && nmeaStrings.Contains("*")) { int start = nmeaStrings.IndexOf("$"); nmeaStrings = nmeaStrings.Substring(start); // Check if a checksum exist in the data // If so, being parsing int checksumLoc = nmeaStrings.IndexOf("*"); string nmea = ""; // Find the start of the checksum // Add NMEA_CHECKSUM_SIZE to include the * and checksum value if (checksumLoc >= 0) { if (nmeaStrings.Length >= checksumLoc + NMEA_CHECKSUM_SIZE) { // Check if the checksum is good if (!nmeaStrings.Substring(checksumLoc, NMEA_CHECKSUM_SIZE).Contains("$")) { // Get the NMEA string and remove it from the buffer. nmea = nmeaStrings.Substring(0, checksumLoc + NMEA_CHECKSUM_SIZE); nmeaStrings = nmeaStrings.Remove(0, nmea.Length); // Remove any trailing new lines nmea = nmea.TrimEnd(REMOVE_END); } else { // Bad Nmea string, $ within checksum // Remove the bad string nmeaStrings = nmeaStrings.Remove(0, checksumLoc); } } else { nmeaStrings = nmeaStrings.Remove(0, checksumLoc); } } if (nmea.Length > 0) { // Create a NMEA sentence and verify its valid NmeaSentence sentence = new NmeaSentence(nmea); if (sentence.IsValid) { // Add the nmea data to list NmeaStrings.Add(sentence.Sentence); // Set values from the NMEA data SetValues(sentence); } } } // Store the Nmea data //NmeaStrings = new NmeaSentence[list.Count]; //list.CopyTo(NmeaStrings, 0); }
/// <summary> /// Set any possible values for the given NMEA data. /// It will continue to replace /// the values so the last value is used as the final value. /// </summary> /// <param name="sentence">NMEA sentence containing data.</param> private void SetValues(NmeaSentence sentence) { /* * NMEA specification states that the first two letters of * a sentence may change. For example, for "$GPGSV" there may be variations such as * "$__GSV" where the first two letters change. As a result, we need only test the last three * characters. */ if (sentence.CommandWord.EndsWith("GGA", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPGGA = new GpggaSentence(sentence.Sentence); // Set the Lat and Lon and time } if (sentence.CommandWord.EndsWith("VTG", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPVTG = new GpvtgSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("RMC", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPRMC = new GprmcSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("RMF", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor PGRMF = new PgrmfSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("GLL", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPGLL = new GpgllSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("GSV", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPGSV = new GpgsvSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("GSA", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPGSA = new GpgsaSentence(sentence.Sentence); } if (sentence.CommandWord.EndsWith("HDT", StringComparison.Ordinal)) { // Yes. Convert it using the fast pre-parseed constructor GPHDT = new GphdtSentence(sentence.Sentence); } }
/// <summary> /// Decode the NMEA sentence from the array. Then add /// it to the list of NMEA sentences. Set value will try /// to update the NMEA data with the latest information. /// </summary> /// <param name="nmeaSentences">All the NMEA setences.</param> private void DecodeNmeaData(List<string> nmeaSentences) { // Create a list of all the NMEA setences LinkedList<string> list = new LinkedList<string>(); if (nmeaSentences != null) { for (int x = 0; x < nmeaSentences.Count; x++) { // Create a NMEA sentence and verify its valid NmeaSentence sentence = new NmeaSentence(nmeaSentences[x]); if (sentence.IsValid) { // Set values from the NMEA data SetValues(sentence); } } } }
/// <summary> /// Decode the NMEA sentence from the array. Then add /// it to the list of NMEA sentences. Set value will try /// to update the NMEA data with the latest information. /// </summary> /// <param name="nmeaSentences">All the NMEA setences.</param> private void DecodeNmeaData(string[] nmeaSentences) { // Create a list of all the NMEA setences LinkedList<string> list = new LinkedList<string>(); if (nmeaSentences != null) { for (int x = 0; x < nmeaSentences.Length; x++) { // Create a NMEA sentence and verify its valid NmeaSentence sentence = new NmeaSentence(nmeaSentences[x]); if (sentence.IsValid) { // Add to the list NmeaStrings.Add(sentence.Sentence); // Set values from the NMEA data SetValues(sentence); } } } // Copy the list to the NmeaStrings //NmeaStrings = new string[list.Count]; //list.CopyTo(NmeaStrings, 0); }
private void OnSentenceReceivedFromClient(NmeaSinkAndSource source, NmeaSentence sentence) { DispatchSentenceEvents(sentence); }
private void ForwardDecoded(NmeaSinkAndSource source, NmeaSentence sentence) { DispatchSentenceEvents(sentence); }
/// <inheritdoc /> public override void SendSentence(NmeaSinkAndSource source, NmeaSentence sentence) { }