Examples¶
This page shows practical C++ and Python examples for the full nmealib workflow: - parsing NMEA 0183 and NMEA 2000 from wire format, - dispatching to typed message classes, - creating new messages from fields, - serializing and validating messages, - handling parse and protocol errors.
C++ Examples¶
Parse NMEA 0183 and dispatch to typed class¶
#include <iostream>
#include <memory>
#include <nmealib.h>
int main() {
const std::string raw =
"$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W,A,V*6A\r\n";
auto msg = nmealib::nmea0183::Nmea0183Factory::create(raw);
std::cout << "Protocol: "
<< nmealib::Message::typeToString(msg->getType())
<< "\n";
std::cout << "Valid: " << std::boolalpha << msg->validate() << "\n";
if (auto* rmc = dynamic_cast<nmealib::nmea0183::RMC*>(msg.get())) {
std::cout << "RMC lat/lon: "
<< rmc->getLatitude() << " " << rmc->getLatitudeDirection()
<< ", "
<< rmc->getLongitude() << " " << rmc->getLongitudeDirection()
<< "\n";
std::cout << "SOG(kn): " << rmc->getSpeedOverGround() << "\n";
}
std::cout << "Verbose dump:\n" << msg->getStringContent(true);
}
Parse NMEA 2000 and inspect CAN/PGN fields¶
#include <iostream>
#include <nmealib.h>
int main() {
const std::string raw = "01F80200:01010040F4010000"; // PGN 129026
auto msg = nmealib::nmea2000::Nmea2000Factory::create(raw);
std::cout << "PGN: " << msg->getPgn() << "\n";
std::cout << "Priority: " << static_cast<int>(msg->getPriority()) << "\n";
std::cout << "Source address: " << static_cast<int>(msg->getSourceAddress()) << "\n";
std::cout << "Destination address: " << static_cast<int>(msg->getDestinationAddress()) << "\n";
if (auto* cogSog = dynamic_cast<nmealib::nmea2000::PGN129026*>(msg.get())) {
std::cout << "COG(deg): " << cogSog->getCogDegrees() << "\n";
std::cout << "SOG(kn): " << cogSog->getSogKnots() << "\n";
}
std::cout << "Verbose dump:\n" << msg->getStringContent(true);
}
Create messages from fields and round-trip serialize/parse¶
#include <cassert>
#include <memory>
#include <nmealib.h>
int main() {
// NMEA 0183: create VTG from field values
nmealib::nmea0183::VTG vtg("GP", 220.86, 218.90, 2.55, 4.724, 'A', false);
std::string vtgWire = vtg.serialize();
auto vtgParsedBase = nmealib::nmea0183::Nmea0183Factory::create(vtgWire);
auto* vtgParsed = dynamic_cast<nmealib::nmea0183::VTG*>(vtgParsedBase.get());
assert(vtgParsed != nullptr);
assert(vtgParsed->validate());
// NMEA 2000: create PGN 129026 from field values
nmealib::nmea2000::PGN129026 pgn(7, 1, 1.5707f, 5.0f);
std::string pgnWire = pgn.serialize();
auto pgnParsedBase = nmealib::nmea2000::Nmea2000Factory::create(pgnWire);
auto* pgnParsed = dynamic_cast<nmealib::nmea2000::PGN129026*>(pgnParsedBase.get());
assert(pgnParsed != nullptr);
assert(pgnParsed->validate());
}
Handle errors cleanly¶
#include <iostream>
#include <nmealib.h>
int main() {
try {
// Invalid start character for NMEA 0183
auto msg = nmealib::nmea0183::Nmea0183Factory::create("GPRMC,123519,A\r\n");
(void)msg;
} catch (const nmealib::nmea0183::InvalidStartCharacterException& ex) {
std::cerr << "Invalid 0183 sentence: " << ex.what() << "\n";
} catch (const nmealib::NmeaException& ex) {
std::cerr << "nmealib error: " << ex.what() << "\n";
}
}
Python Examples¶
Parse NMEA 0183 and use typed accessors¶
import nmealib
raw = "$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W,A,V*6A\r\n"
msg = nmealib.nmea0183.Nmea0183Factory.create(raw)
print(type(msg).__name__) # RMC
print(msg.get_sentence_type())
print(msg.get_string_content(verbose=False))
if isinstance(msg, nmealib.nmea0183.RMC):
print("Lat/Lon:", msg.get_latitude(), msg.get_longitude())
print("COG:", msg.get_course_over_ground())
print("SOG:", msg.get_speed_over_ground())
# Convert raw NMEA coordinate field to decimal degrees when needed
lat_dd = nmealib.nmea0183.Message0183.convert_nmea_coordinate_to_decimal_degrees("4807.038")
print("Converted latitude:", lat_dd)
Parse NMEA 2000 and inspect PGN-specific values¶
import nmealib
raw = "01F80200:01010040F4010000" # PGN 129026
msg = nmealib.nmea2000.Nmea2000Factory.create(raw)
print(type(msg).__name__)
print("PGN:", msg.get_pgn())
print("Source:", msg.get_source_address())
print("Destination:", msg.get_destination_address())
print(msg.get_string_content(verbose=True))
if isinstance(msg, nmealib.nmea2000.PGN129026):
print("COG(deg):", msg.get_cog_degrees())
print("SOG(kn):", msg.get_sog_knots())
Create messages in Python and serialize¶
import nmealib
# NMEA 0183
vtg = nmealib.nmea0183.VTG("GP", 220.86, 218.90, 2.55, 4.724, "A", False)
vtg_wire = vtg.serialize()
print(vtg_wire)
# NMEA 2000
pgn129026 = nmealib.nmea2000.PGN129026(7, 1, 1.5707, 5.0)
pgn_wire = pgn129026.serialize()
print(pgn_wire)
# Round-trip parse back
parsed_0183 = nmealib.nmea0183.Nmea0183Factory.create(vtg_wire)
parsed_2000 = nmealib.nmea2000.Nmea2000Factory.create(pgn_wire)
print(parsed_0183.validate(), parsed_2000.validate())
Handle exceptions in Python¶
import nmealib
bad_raw = "GPRMC,123519,A\r\n"
try:
nmealib.nmea0183.Nmea0183Factory.create(bad_raw)
except nmealib.InvalidStartCharacterException as ex:
print("Invalid start character:", ex)
except nmealib.NmeaException as ex:
print("Generic nmealib exception:", ex)
End-to-End Mixed Stream Example¶
Use this pattern when input lines can be either NMEA 0183 or NMEA 2000.
import nmealib
raw_messages = [
"$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W,A,V*6A\r\n",
"01F10D00:0101FEBF0060FFFF",
"$GPVTG,220.86,T,218.90,M,2.550,N,4.724,K*40\r\n",
"09F11260:342C71FF7FFF7FFD",
]
for raw in raw_messages:
try:
if raw.startswith("$") or raw.startswith("!"):
msg = nmealib.nmea0183.Nmea0183Factory.create(raw)
else:
msg = nmealib.nmea2000.Nmea2000Factory.create(raw)
print(type(msg).__name__, "->", msg.serialize())
except nmealib.NmeaException as ex:
print("Skipped invalid message:", ex)
Coverage Notes¶
The examples above cover the core feature set used across all supported message classes: - Factory parsing and automatic typed dispatch - Protocol/base introspection through Message, Message0183, and Message2000 APIs - Type-specific field getters (RMC, VTG, PGN129026 used as concrete patterns) - Serialization and round-trip validation - Protocol-specific and generic exception handling
You can apply the same pattern to every supported NMEA 0183 sentence class and NMEA 2000 PGN class listed in docs/nmea0183 and docs/nmea2000.