CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pynmea2

Python library for parsing and generating NMEA 0183 protocol messages used in GPS and marine navigation systems

77

1.11x
Overview
Eval results
Files

proprietary-sentences.mddocs/

Proprietary Sentences

Proprietary sentences provide manufacturer-specific extensions to the standard NMEA protocol, allowing GPS and marine equipment manufacturers to include specialized data and functionality.

Base ProprietarySentence Class

class ProprietarySentence(NMEASentence):
    """Base class for proprietary manufacturer sentences."""
    
    manufacturer: str        # Three-character manufacturer code
    data: List[str]         # List of sentence field data
    
    def __init__(self, manufacturer: str, data: List[str]):
        """Initialize proprietary sentence with manufacturer code and data."""
    
    def identifier(self) -> str:
        """Return sentence identifier (e.g., 'PGRM')."""

Supported Manufacturers

Garmin (GRM)

class GRME(ProprietarySentence):
    """Garmin Estimated Position Error."""
    
    subtype: str             # Message subtype
    hpe: str                # Horizontal position error
    hpe_unit: str           # HPE unit (usually 'M')
    vpe: str                # Vertical position error  
    vpe_unit: str           # VPE unit (usually 'M')
    osepe: str              # Overall spherical equivalent position error
    osepe_unit: str         # OSEPE unit (usually 'M')
class GRMZ(ProprietarySentence):
    """Garmin Altitude Information."""
    
    subtype: str             # Message subtype
    altitude: str           # Altitude value
    altitude_unit: str      # Altitude unit ('f' = feet, 'M' = meters)
    pos_fix_dim: str        # Position fix dimension (2 = 2D, 3 = 3D)

Ashtech (ASH)

class ASHRPOS(ProprietarySentence, LatLonFix):
    """Ashtech Position Message."""
    
    _r: str                 # 'R' indicator
    subtype: str            # Message subtype
    mode: str               # Positioning mode
    sat_count: str          # Number of satellites
    timestamp: datetime.time # UTC time
    lat: str                # Latitude
    lat_dir: str           # Latitude direction
    lon: str               # Longitude  
    lon_dir: str           # Longitude direction
    altitude: str          # Altitude
    course: str            # Course over ground
    spd_over_grnd: str     # Speed over ground
    
    @property
    def latitude(self) -> float:
        """Latitude in decimal degrees."""
    
    @property
    def longitude(self) -> float:
        """Longitude in decimal degrees."""

u-blox (UBX)

class UBX00(ProprietarySentence, LatLonFix):
    """u-blox Lat/Long Position Data."""
    
    _blank: str             # Blank field
    ubx_type: str           # UBX message type
    timestamp: datetime.time # UTC time
    lat: str                # Latitude
    lat_dir: str           # Latitude direction
    lon: str               # Longitude
    lon_dir: str           # Longitude direction
    alt_ref: str           # Altitude reference
    nav_stat: str          # Navigation status
    h_acc: str             # Horizontal accuracy
    v_acc: str             # Vertical accuracy
    sog: str               # Speed over ground
    cog: str               # Course over ground
    v_vel: str             # Vertical velocity
    diff_age: str          # Differential age
    hdop: str              # Horizontal DOP
    vdop: str              # Vertical DOP
    tdop: str              # Time DOP
    num_svs: str           # Number of satellites
    reserved: str          # Reserved field

Trimble (TNL)

class TNLAVR(ProprietarySentence):
    """Trimble AVR Message (Attitude and Heading)."""
    
    _: str                  # Blank field
    type: str               # Message type
    timestamp: datetime.time # UTC time
    yaw_angle: str          # Yaw angle in degrees
    yaw: str                # Yaw indicator
    tilt_angle: str         # Tilt angle in degrees
    tilt: str               # Tilt indicator  
    roll_angle: str         # Roll angle in degrees
    roll: str               # Roll indicator
    baseline: str           # Baseline length
    gps_quality: str        # GPS quality indicator
    pdop: str               # Position DOP
    num_sats: str           # Number of satellites

Nortek DVL (NOR)

class NORBT0(ProprietarySentence, DatetimeFix):
    """Nortek Bottom Track DF350/DF351."""
    
    timestamp: datetime.time # UTC time
    datestamp: datetime.date # Date
    # Additional bottom track fields...
    
    @property
    def datetime(self) -> datetime.datetime:
        """Combined date and time."""

Usage Examples

import pynmea2

# Parse Garmin position error
msg = pynmea2.parse("$PGRME,15.0,M,45.0,M,25.0,M*22")
print(f"Manufacturer: {msg.manufacturer}")        # GRM
print(f"Horizontal error: {msg.hpe} {msg.hpe_unit}")  # 15.0 M
print(f"Vertical error: {msg.vpe} {msg.vpe_unit}")    # 45.0 M
print(f"Overall error: {msg.osepe} {msg.osepe_unit}") # 25.0 M

# Parse Garmin altitude
msg = pynmea2.parse("$PGRMZ,1494,f,3*21")
print(f"Altitude: {msg.altitude} {msg.altitude_unit}")  # 1494 f
print(f"Fix dimension: {msg.pos_fix_dim}D")            # 3D

# Parse Ashtech position
msg = pynmea2.parse("$PASHR,POS,0,3,184353.07,1929.045,S,02410.506,E,100.0,309.62,0.13,1.5,1.2,2.1,1.8,12*3F")
print(f"Position: {msg.latitude}, {msg.longitude}")    # Decimal degrees
print(f"Satellites: {msg.sat_count}")                  # Number of satellites
print(f"Mode: {msg.mode}")                             # Positioning mode

# Parse u-blox position data
msg = pynmea2.parse("$PUBX,00,184353.07,1929.045,S,02410.506,E,100.0,G3,16,9,0.9,309.62,0.13,,,1.2,1.8,1.5,12,0,0*6F")
print(f"Navigation status: {msg.nav_stat}")           # G3
print(f"Horizontal accuracy: {msg.h_acc}")            # Accuracy estimate
print(f"Satellites used: {msg.num_svs}")              # 12

# Create proprietary sentence
grme_data = ['15.0', 'M', '45.0', 'M', '25.0', 'M']
msg = pynmea2.GRME('GRM', grme_data)
print(str(msg))  # $PGRME,15.0,M,45.0,M,25.0,M*22

Manufacturer Codes

CodeManufacturerCommon Sentences
ASHAshtechRPOS, RATT, RHPR, RVEL
FECFurunoGPatt, GPhve
GRMGarminRME, RMZ, RMM, RMW
KWDKenwoodWPL, S (status messages)
MGNMagellanWPL (waypoint location)
NORNortekBT (bottom track), WT (water track)
RDIRD InstrumentsD (heading/pitch/roll)
SRFSiRF100, 103 (configuration)
SXNSeapath20-24 (quality, attitude, rates)
TNLTrimbleAVR, GGK, VGK, VHD
UBXu-blox00, 03, 04 (position, satellites)
VTXVectronix0000, 0002, 0012, 0020

Custom Proprietary Sentences

import pynmea2

# Parse unknown proprietary sentence (falls back to generic ProprietarySentence)
msg = pynmea2.parse("$PXYZ,field1,field2,field3*12")
print(f"Type: {type(msg)}")                   # <class 'pynmea2.nmea.ProprietarySentence'>
print(f"Manufacturer: {msg.manufacturer}")    # XYZ
print(f"Data: {msg.data}")                    # ['field1', 'field2', 'field3']

# Access raw field data
print(f"Field 1: {msg.data[0]}")              # field1
print(f"Field 2: {msg.data[1]}")              # field2

Install with Tessl CLI

npx tessl i tessl/pypi-pynmea2

docs

core-parsing.md

depth-sonar.md

gps-positioning.md

index.md

navigation-course.md

proprietary-sentences.md

stream-processing.md

utilities.md

wind-weather.md

tile.json