Beispiel #1
0
        private void ParserOnParserError(NmeaSinkAndSource source, string message, NmeaError errorCode)
        {
            if (errorCode == NmeaError.PortClosed)
            {
                Task t = Task.Run(() =>
                {
                    lock (_lock)
                    {
                        _activeParsers.Remove(source);
                    }

                    // Can't do this synchronously, as it would cause a deadlock
                    source.StopDecode();
                });
                _serverTasks.Enqueue(t);
                _serverControlEvent.Set();
            }

            FireOnParserError(message, errorCode);
        }
Beispiel #2
0
        /// <summary>
        /// Reads NMEA0183 talker sentence from provided string
        /// </summary>
        /// <param name="sentence">NMEA0183 talker sentence</param>
        /// <param name="expectedTalkerId">If this is not TalkerId.Any, only messages with this talker id are parsed,
        /// all others are ignored. This reduces workload if a source acts as repeater, but the repeated messages are not needed.</param>
        /// <param name="errorCode">Returns an error code, if the parsing failed</param>
        /// <returns>TalkerSentence instance, or null in case of an error</returns>
        /// <remarks><paramref name="sentence"/> does not include new line characters</remarks>
        public static TalkerSentence?FromSentenceString(string sentence, TalkerId expectedTalkerId, out NmeaError errorCode)
        {
            // $XXY, ...
            const int sentenceHeaderMinLength = 4;

            // http://www.tronico.fi/OH6NT/docs/NMEA0183.pdf page 2
            // defines this as 80 + 1 (for $), but we don't really care if it is something within a reasonable limit.
            const int MaxSentenceLength = 256;

            if (sentence == null)
            {
                throw new ArgumentNullException(nameof(sentence));
            }

            if (sentence.Length < sentenceHeaderMinLength)
            {
                errorCode = NmeaError.MessageToShort;
                return(null);
            }

            if (sentence.Length > MaxSentenceLength)
            {
                errorCode = NmeaError.MessageToLong;
                return(null);
            }

            if (sentence[0] != '$' && sentence[0] != '!')
            {
                // Valid sentences start with $ or ! (for the AIS sentences)
                errorCode = NmeaError.NoSyncByte;
                return(null);
            }

            TalkerId talkerId = new TalkerId(sentence[1], sentence[2]);

            if (expectedTalkerId != TalkerId.Any && expectedTalkerId != talkerId)
            {
                errorCode = NmeaError.None;
                return(null);
            }

            int firstComma = sentence.IndexOf(',', 1);

            if (firstComma == -1)
            {
                errorCode = NmeaError.MessageToShort;
                return(null);
            }

            string sentenceIdString = sentence.Substring(3, firstComma - 3);

            SentenceId sentenceId = new SentenceId(sentenceIdString);

            string[] fields       = sentence.Substring(firstComma + 1).Split(',');
            int      lastFieldIdx = fields.Length - 1;

            // This returns null as the checksum if there was none, or a very big number if the checksum couldn't be parsed
            (int?checksum, string lastField) = GetChecksumAndLastField(fields[lastFieldIdx]);
            fields[lastFieldIdx]             = lastField;

            TalkerSentence result = new TalkerSentence(talkerId, sentenceId, fields);

            if (checksum.HasValue)
            {
                byte realChecksum = CalculateChecksumFromSentenceString(sentence.AsSpan());

                if (realChecksum != checksum.Value)
                {
                    errorCode = NmeaError.InvalidChecksum;
                    return(null);
                }
            }

            errorCode = NmeaError.None;
            return(result);
        }
Beispiel #3
0
 /// <summary>
 /// Reads NMEA0183 talker sentence from provided string
 /// </summary>
 /// <param name="sentence">NMEA0183 talker sentence</param>
 /// <param name="errorCode">Returns an error code, if the parsing failed</param>
 /// <returns>TalkerSentence instance, or null in case of an error</returns>
 /// <remarks><paramref name="sentence"/> does not include new line characters</remarks>
 public static TalkerSentence?FromSentenceString(string sentence, out NmeaError errorCode)
 {
     return(FromSentenceString(sentence, TalkerId.Any, out errorCode));
 }
Beispiel #4
0
 /// <summary>
 /// Fire an event informing about parser errors
 /// </summary>
 /// <param name="message">The message to write</param>
 /// <param name="error">The kind of error seen</param>
 protected void FireOnParserError(string message, NmeaError error)
 {
     OnParserError?.Invoke(this, message, error);
 }
Beispiel #5
0
 private void ParserOnParserError(NmeaSinkAndSource source, string message, NmeaError errorCode)
 {
     FireOnParserError(message, errorCode);
 }