NMEAParser
NMEA Parser Library - Monte Variakojis @VisualGPS
|
Monte Variakojis @VisualGPS
The NMEA 0813 standard for interfacing marine electronics devices specifies the NMEA data sentence structure as well as general definitions of approved sentences. However, the specification does not cover implementation and design. This article will hopefully clarify some of the design tasks needed to parse through NMEA sentences robustly. It will try to show techniques in parsing and data integrity checking. The article does assume that the reader has knowledge in software design and has experience in some sort of programming language. This article will reference the NMEA 0183 specification and it is recommended that the NMEA 0813 specification be available as a reference.
This article makes no assumption of the media that the NMEA data is acquired. The techniques here can be applied on received data from a higher abstraction layer. A simple example written in C++ demonstrates this parser design. Please note that the specific NMEA sentences parsed are centric to a GPS device.
NMEA data is sent in 8-bit ASCII where the MSB is set to zero (0). The specification also has a set of reserved characters. These characters assist in the formatting of the NMEA data string. The specification also states valid characters and gives a table of these characters ranging from HEX 20 to HEX 7E.
As stated in the NMEA 0183 specification version 3.01 the maximum number of characters shall be 82, consisting of a maximum of 79 characters between start of message "$" or "!" and terminating delimiter <CR><LF> (HEX 0D and 0A). The minimum number of fields is one (1).
Most protocols have a state machine tracking the protocol state and any errors that may occur during the data transfer. The NMEA parser we are discussing is based on a simple state machine. By using a state machine the computer can easily keep track of where it is within the protocol as well as recover from any errors such as timeouts and checksum errors.
The parsing example is designed such that a buffer can be sent to the parser along with the buffer length to maximize the computer processor efficiency. This will allow the computer to parse data when it is received. Since NMEA data is typically sent at 4800 baud, computers are often waiting for data. By having a state machine in place, partial or complete sets of NMEA data may be parsed. If only a partial set of data was received and sent to the parser, then when the rest of the data is received, the parser will complete any NMEA sentence that may have been incomplete.
Below, Figure 1 illustrates the data flow to the NMEA parser. Our design will assume two abstract software layers, NMEA protocol parser and specific NMEA sentence parser. It does not matter the number of data bytes received or if there is only a partial message. The NMEA parser will manage the data and extract individual NMEA sentences.
The NMEAParser class is composed of two main classes and individual NMEA sentence classes.
The CNMEAParserPacket does the work of parsing the actual packet from a buffer of data. The data is feed into the state machine using the CNMEAParserPacket::ProcessNMEABuffer() method. This method will parse through the data, verify the checksum (if present) and call the virtual method CNMEAParserPacket::ProcessRxCommand(). The CNMEAParser class is based from the CNMEAParserPacket, redefines the ProcessRxCommand() method, and actual parse the specific NMEA sentence.
Located in the CNMEAParserPacket::ProcessNMEABuffer() method, the state machine will parse the incoming buffer weather it’s one byte or contains multiple NMEA sentences. Below describes the packet parsing states for a NMEA sentence.
When a complete NMEA command sentence is received, the virtual method CNMEAParserPacket::ProcessRxCommand() is called. This method is redefined in the CNMEAParser class and will parse the command, data, and stuff them into the correct CNMESentence object.
Timeouts can be handled at a higher level. If for some reason data has not been received for a specified period of time, the software can reset the NMEA Parser by calling the CNMEAParserPacket::Reset() method.
NMEAParserLib is a C++ class library that will accept variable length data and parse a NMEA stream. Even though the code is written in C++, it only uses inherencies and virtual methods.
Below is a basic program that defines a CNMEAParser object and streams NMEA data from a text file.