Skip to main content

RTCM3 Protocol Parser

Reason this release was yanked:

obsolete

Project description

pyrtcm

Current Status | Installation | Reading | Parsing | Generating | Serializing | Examples | Extensibility | Graphical Client | Author & License

pyrtcm is an original Python 3 parser for the RTCM3 © GPS/GNSS protocol. RTCM3 is a proprietary GPS/GNSS differential correction or DGPS protocol published by the Radio Technical Commission for Maritime Services.

RTCM STANDARD 10403.n DIFFERENTIAL GNSS (GLOBAL NAVIGATION SATELLITE SYSTEMS) SERVICES – VERSION 3.

The pyrtcm homepage is located at https://github.com/semuconsulting/pyrtcm.

This is an independent project and we have no affiliation whatsoever with the Radio Technical Commission for Maritime Services.

FYI There are companion libraries which handle standard NMEA 0183 © and UBX © (u-blox) GNSS/GPS messages:

Current Status

Release Build Codecov Release Date Last Commit Contributors Open Issues

Currently in Alpha; parses RTCM3 messages into their constituent data fields. Refer to the RTCM_MSGIDS dictionary in rtcmtypes_core.py for a list of message types currently implemented (but not necessarily tested). Additional message types can be readily added - see Extensibility).

Sphinx API Documentation in HTML format is available at https://www.semuconsulting.com/pyrtcm.

Contributions welcome - please refer to CONTRIBUTING.MD.

Bug reports and Feature requests - please use the templates provided.


Installation

pyrtcm is compatible with Python 3.6+ and has no third-party library dependencies.

In the following, python & pip refer to the Python 3 executables. You may need to type python3 or pip3, depending on your particular environment.

Python version PyPI version PyPI downloads

The recommended way to install the latest version of pyrtcm is with pip:

python -m pip install --upgrade pyrtcm

Local installation is also available, provided you have the Python packages setuptools and wheel installed:

git clone https://github.com/semuconsulting/pyrtcm.git
cd pyrtcm
python setup.py sdist bdist_wheel
python -m pip install dist/pyrtcm-0.1.3.tar.gz --user --force_reinstall

Reading (Streaming)

class pyrtcm.rtcmreader.RTCMReader(stream, **kwargs)

You can create a RTCMReader object by calling the constructor with an active stream object. The stream object can be any data stream which supports a read(n) -> bytes method (e.g. File or Serial, with or without a buffer wrapper).

Individual RTCM messages can then be read using the RTCMReader.read() function, which returns both the raw binary data (as bytes) and the parsed data (as a RTCMMessage, via the parse() method). The function is thread-safe in so far as the incoming data stream object is thread-safe. RTCMReader also implements an iterator.

Example - Serial input:

>>> from serial import Serial
>>> from pyrtcm import RTCMReader
>>> stream = Serial('/dev/tty.usbmodem14101', 9600, timeout=3)
>>> rtr = RTCMReader(stream)
>>> (raw_data, parsed_data) = rtr.read()
>>> print(parsed_data)

Example - File input (using iterator).

>>> from pyrtcm import RTCMReader
>>> stream = open('rtcmdata.log', 'rb')
>>> rtr = RTCMReader(stream)
>>> for (raw_data, parsed_data) in rtr: print(parsed_data)
...

Parsing

You can parse individual RTCM messages using the static RTCMReader.parse(data) function, which takes a bytes array containing a binary RTCM message and returns a RTCMMessage object.

NB: Once instantiated, an RTCMMessage object is immutable.

Example:

>>> from pyrtcm import RTCMReader
>>> msg = RTCMReader.parse(b"\xd3\x00\x13>\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH Z\xd7\xf7")
>>> print(msg)
<RTCM(1005, DF002=1005, DF003=0, DF021=0, DF022=1, DF023=1, DF024=1, DF141=0, DF025=4444030.8028, DF142=1, DF001_1=0, DF026=3085671.2349, DF364=0, DF027=3366658.256)>

The RTCMMessage object exposes different public attributes depending on its message type or 'identity'. Attributes are defined as data fields ("DF002", "DF003", etc.) e.g. the 1005 message contains the following data fields:

>>> print(msg)
<RTCM(1005, DF002=1005, DF003=0, DF021=0, DF022=1, DF023=1, DF024=1, DF141=0, DF025=4444030.8028, DF142=1, DF001_1=0, DF026=3085671.2349, DF364=0, DF027=3366658.256)>
>>> msg.identity
'1005'
>>> msg.DF024
1

It is also possible to parse raw RTCM3 messages from a buffer using the RTCMReader.parse_buffer(bytearray) function, which takes a bytearray containing one or more whole or partial RTCM3 messages and returns the first complete raw RTCM3 message and any remaining buffer.

Example - Reading successive RTCM3 messages from an NTRIP server socket.

  buf = bytearray()
  data = True
  while data:
    data = sock.recv(1024) # NTRIP server socket
    buf += data
    while True:
      raw_data, buf = RTCMReader.parse_buffer(buf)
      if raw_data is not None:
        parsed_data = RTCMReader.parse(raw_data)
        print(parsed_data)
      else:
        break

Helper methods are available to interpret the individual datafields:

>>> from pyrtcm import RTCM_DATA_FIELDS, datasiz, datascale, datadesc
>>> dfname = "DF012"
>>> RTCM_DATA_FIELDS[dfname]
(INT20, 0.0001, "GPS L1 PhaseRange - L1 Pseudorange")
>>> datasiz(dfname) # size in bits
20
>>> datascale(dfname) # scaling factor
0.0001
>>> datadesc(dfname) # description
'GPS L1 PhaseRange - L1 Pseudorange'

Attributes within repeating groups are parsed with a two-digit suffix ("DF030_01", "DF030_02", etc.). The payload attribute always contains the raw payload as bytes.


Generating

class pyrtcm.rtcmmessage.RTCMMessage(**kwargs)

You can create an RTCMMessage object by calling the constructor with the following keyword arguments:

  1. payload as bytes

Example:

>>> from pyrtcm import RTCMMessage
>>> msg = RTCMMessage(payload=b">\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH ")
>>> print(msg)
<RTCM(1005, DF002=1005, DF003=0, DF021=0, DF022=1, DF023=1, DF024=1, DF141=0, DF025=4444030.8028, DF142=1, DF001_1=0, DF026=3085671.2349, DF364=0, DF027=3366658.256)>

Serializing

The RTCMMessage class implements a serialize() method to convert a RTCMMessage object to a bytes array suitable for writing to an output stream.

e.g. to create and send a 1005 message type:

>>> from serial import Serial
>>> serialOut = Serial('COM7', 38400, timeout=5)
>>> from pyrtcm import RTCMMessage
>>> msg = RTCMMessage(payload=b">\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH ")
>>> print(msg)
<RTCM(1005, DF002=1005, DF003=0, DF021=0, DF022=1, DF023=1, DF024=1, DF141=0, DF025=4444030.8028, DF142=1, DF001_1=0, DF026=3085671.2349, DF364=0, DF027=3366658.256)>
>>> output = msg.serialize()
>>> output
b'\xd3\x00\x13>\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH Z\xd7\xf7'
>>> serialOut.write(output)

Examples

The following examples are available in the /examples folder:

  1. rtcmfile.py - illustrates how to stream RTCM data from binary log file.
  2. rtcmserial.py - illustrates how to stream RTCM data from serial/UART port.
  3. rtcmbuild.py - illustrates how to construct RTCM payload from constituent datafields.
  4. ntripclient.py - illustrates a simple NTRIP client using pyrtcm to parse the RTCM3 output.

Extensibility

The RTCM protocol is principally defined in the modules rtcmtypes_core.py and rtcmtypes_get.py as a series of dictionaries. RTCM uses a series of pre-defined data fields ("DF002", DF003" etc.), each of which has a designated data type (UINT32, etc.). Message payload definitions must conform to the following rules:

1. datafield names must be unique within each message class
2. datafield types must be one of the valid data fields ("DF026", "DF059", etc.)
3. repeating or bitfield groups must be defined as a tuple ('numr', {dict}), where:
   'numr' is either:
     a. an integer representing a fixed number of repeats e.g. 32
     b. a string representing the name of a preceding attribute containing the number of repeats e.g. 'DF029'
   {dict} is the nested dictionary of repeating items or bitfield group

Repeating attribute names are parsed with a two-digit suffix ("DF030_01", "DF030_02", etc.). Nested repeating groups are supported.


Graphical Client

A python/tkinter graphical GPS client which supports NMEA, UBX and RTCM protocols is available at:

https://github.com/semuconsulting/PyGPSClient


Author & License Information

semuadmin@semuconsulting.com

License

pyrtcm is maintained entirely by volunteers. If you find it useful, a small donation would be greatly appreciated!

Donations

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyrtcm-0.2.1.tar.gz (30.7 kB view hashes)

Uploaded Source

Built Distribution

pyrtcm-0.2.1-py3-none-any.whl (28.4 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page