pyrtcm

Python library for parsing RTCM 3 protocol messages.

https://github.com/semuconsulting/pyrtcm

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (12.1%) to scientific vocabulary

Keywords

gnss gps ntrip rtcm rtcm3
Last synced: 6 months ago · JSON representation ·

Repository

Python library for parsing RTCM 3 protocol messages.

Basic Info
  • Host: GitHub
  • Owner: semuconsulting
  • License: bsd-3-clause
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 744 KB
Statistics
  • Stars: 94
  • Watchers: 4
  • Forks: 29
  • Open Issues: 0
  • Releases: 52
Topics
gnss gps ntrip rtcm rtcm3
Created about 4 years ago · Last pushed 6 months ago
Metadata Files
Readme Contributing Funding License Code of conduct Citation Security

README.md

pyrtcm

Current Status | Installation | Reading | Parsing | Generating | Serializing | Examples | Extensibility | Command Line Utility | 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: - pyubx2 - pynmeagps

Current Status

Status Release Build Codecov Release Date Last Commit Contributors Open Issues

Parses RTCM3 messages into their constituent data fields - DF002, DF003, etc. Refer to the RTCM_MSGIDS dictionary in rtcmtypes_core.py for a list of message types currently implemented. 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. For general queries and advice, post a message to one of the pyrtcm Discussions channels.


Installation

Python version PyPI version PyPI downloads

pyrtcm is compatible with Python 3.9 - 3.13. In the following, python3 & pip refer to the Python 3 executables. You may need to substitute python for python3, depending on your particular environment (on Windows it's generally python).

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

shell python3 -m pip install --upgrade pyrtcm

If required, pyrtcm can also be installed into a virtual environment, e.g.:

shell python3 -m venv env source env/bin/activate # (or env\Scripts\activate on Windows) python3 -m pip install --upgrade pyrtcm

For Conda users, pyrtcm is also available from conda-forge:

Anaconda-Server Badge Anaconda-Server Badge

shell conda install -c conda-forge pyrtcm


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). pyrtcm implements an internal SocketStream class to allow sockets to be read in the same way as other streams (see example below).

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: python from serial import Serial from pyrtcm import RTCMReader with Serial('/dev/tty.usbmodem14101', 9600, timeout=3) as stream: rtr = RTCMReader(stream) raw_data, parsed_data = rtr.read() if parsed_data is not None: print(parsed_data) "<RTCM(1077, DF002=1077, DF003=0, DF004=204137001, DF393=1, DF409=0, DF001_7=0, ..., DF404_15=-9556, DF404_16=-2148, DF404_17=-2174)>",

Example - File input (using iterator). python from pyrtcm import RTCMReader with open('rtcmdata.log', 'rb') as stream: rtr = RTCMReader(stream) for raw_data, parsed_data in rtr: print(parsed_data)

Example - Socket input (using iterator): python import socket from pyrtcm import RTCMReader with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as stream: stream.connect(("localhost", 50007)) 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: python 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 1097 multiple signal message (MSM) contains the following data fields:

python print(msg) print(msg.identity) print(msg.DF248) print(msg.DF404_07) "<RTCM(1097, DF002=1097, DF003=0, DF248=204137001, DF393=1, DF409=0, DF001_7=0, DF411=0, DF412=0, DF417=0, DF418=0, DF394=216181732825628672, NSat=5, DF395=1073872896, NSig=2, DF396=1023, NCell=10, PRN_01=007, PRN_02=008, PRN_03=021, PRN_04=027, ..., DF404_07=5534, DF404_08=5545, DF404_09=-7726, DF404_10=-7733)>", '1097' 204137001 5534

Attributes within repeating groups are parsed with a two-digit suffix (DF419_01, DF419_02, etc. See example below for an illustration of how to iterate through grouped attributes).

Helper methods are available to interpret the individual datafields:

python from pyrtcm import RTCM_DATA_FIELDS, datadesc dfname = "DF012" print(RTCM_DATA_FIELDS[dfname]) print(datadesc(dfname)) (INT20, 0.0001, "GPS L1 PhaseRange - L1 Pseudorange") 'GPS L1 PhaseRange - L1 Pseudorange'

The payload attribute always contains the raw payload as bytes.

Iterating Through Group Attributes

To iterate through a group of one or more repeating attributes in a given RTCMMessage object, the following construct can be used (in this illustration, repeating attributes CELLPRN, CELLSIG, DF405, DF406, DF407, DF408, DF420 and DF404 are extracted from an MSM 1077 message msg and collated in the array msmarray):

python msmarray = [] for i in range(msg.NCell): # msg = MSM 1077, number of cells = NCell vals = [] for attr in ("CELLPRN", "CELLSIG", "DF405", "DF406", "DF407", "DF408", "DF420", "DF404"): val = getattr(msg, f"{attr}_{i+1:02d}") vals.append(val) msmarray.append(vals) print(msmarray) shell [['005', '1C', 0.00014309026300907135, 0.00014193402603268623, 341, 45.0, 0, -0.9231], ..., ['030', '2L', -0.00030865520238876343, -0.00030898721888661385, 341, 41.0, 0, -0.2174]]

The following dedicated helper methods are available to parse selected RTCM3 message types into a series of iterable data arrays: - parse_msm - for MSM message types (e.g. 1077, 1125, etc.). - parse_4076_201 - for 4076_201 SSR (harmonic coefficients) message types.


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:

python 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:

python from serial import Serial from pyrtcm import RTCMMessage serialOut = Serial('COM7', 38400, timeout=5) msg = RTCMMessage(payload=b">\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH ") print(msg) output = msg.serialize() print(output) serialOut.write(output) <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)> b'\xd3\x00\x13>\xd0\x00\x03\x8aX\xd9I<\x87/4\x10\x9d\x07\xd6\xafH Z\xd7\xf7'


Examples

The following examples are available in the /examples folder:

  1. rtcmpoller.py - illustrates how to read and display RTCM messages 'concurrently' with other tasks using threads and queues. This represents a useful generic pattern for many end user applications.
  2. rtcmfile.py - illustrates how to stream RTCM data from binary log file.
  3. rtcmsocket.py - illustrates how to implement a TCP Socket reader for RTCM messages using RTCMReader iterator functionality.
  4. msmparser.py - illustrates how to parse RTCM3 MSM (multiple signal messages) into a series of iterable data arrays keyed on satellite PRN and signal ID.
  5. rtcm_ntrip_client.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 ("DF03001", "DF03002", etc.). Nested repeating groups are supported.


Command Line Utility

A command line utility gnssstreamer is available via the pygnssutils package. This is capable of reading and parsing NMEA, UBX and RTCM3 data from a variety of input sources (e.g. serial, socket and file) and outputting to a variety of media in a variety of formats. See https://github.com/semuconsulting/pygnssutils for further details.

To install pygnssutils: python3 -m pip install --upgrade pygnssutils

For help with the gnssstreamer utility, type: gnssstreamer -h


Graphical Client

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

https://github.com/semuconsulting/PyGPSClient


Author & License Information

semuadmin@semuconsulting.com

License

pyrtcm is maintained entirely by unpaid volunteers. It receives no funding from advertising or corporate sponsorship. If you find the utility useful, please consider sponsoring the project with the price of a coffee...

Sponsor

Freedom for Ukraine

Owner

  • Name: SEMU Consulting
  • Login: semuconsulting
  • Kind: organization

Citation (CITATION.bib)

@Misc{pyrtcm,
  author       = {{SEMU Consulting}},
  howpublished = {GitHub repository},
  note         = {Viewed last: xxxx:xx:xx},
  title        = {Python library for reading and parsing RTCM3 protocol messages.},
  year         = {2022},
  url          = {https://github.com/semuconsulting/pyrtcm},
}

GitHub Events

Total
  • Create event: 9
  • Release event: 6
  • Issues event: 5
  • Watch event: 21
  • Delete event: 12
  • Issue comment event: 12
  • Push event: 31
  • Pull request review comment event: 2
  • Pull request review event: 6
  • Pull request event: 13
  • Fork event: 7
Last Year
  • Create event: 9
  • Release event: 6
  • Issues event: 5
  • Watch event: 21
  • Delete event: 12
  • Issue comment event: 12
  • Push event: 31
  • Pull request review comment event: 2
  • Pull request review event: 6
  • Pull request event: 13
  • Fork event: 7

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 353
  • Total Committers: 7
  • Avg Commits per committer: 50.429
  • Development Distribution Score (DDS): 0.048
Past Year
  • Commits: 56
  • Committers: 2
  • Avg Commits per committer: 28.0
  • Development Distribution Score (DDS): 0.089
Top Committers
Name Email Commits
semuadmin 2****n 336
David Lascelles d****s@g****m 5
Akihiro Yamazaki 6****e 5
Jürgen Fredriksson j****i 4
k-stf k****o@a****u 1
Ralphccs 9****s 1
Geoffrey Kirk j****b 1
Committer Domains (Top 20 + Academic)
arhs.ru: 1

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 18
  • Total pull requests: 52
  • Average time to close issues: 3 days
  • Average time to close pull requests: 2 days
  • Total issue authors: 11
  • Total pull request authors: 9
  • Average comments per issue: 3.72
  • Average comments per pull request: 0.75
  • Merged pull requests: 44
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 4
  • Pull requests: 14
  • Average time to close issues: 2 days
  • Average time to close pull requests: 6 days
  • Issue authors: 2
  • Pull request authors: 2
  • Average comments per issue: 0.75
  • Average comments per pull request: 1.36
  • Merged pull requests: 10
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • jcmb (4)
  • semuadmin (4)
  • foxittt (2)
  • augustomazzoni (1)
  • sandeshworld (1)
  • jaguaryang (1)
  • kmhallen (1)
  • Alexgar24 (1)
  • semudev2 (1)
  • EgehanYaglici (1)
  • Harsh005385 (1)
Pull Request Authors
  • semuadmin (49)
  • jcmb (2)
  • ArlinJae (2)
  • davidtlascelles (2)
  • Ralphccs (1)
  • zakkie (1)
  • leoheck (1)
  • k-stf (1)
  • jiargei (1)
Top Labels
Issue Labels
bug (9) enhancement (2) question (2)
Pull Request Labels
enhancement (40) bug (17) documentation (8)

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 54,272 last-month
  • Total docker downloads: 125
  • Total dependent packages: 4
  • Total dependent repositories: 3
  • Total versions: 49
  • Total maintainers: 1
pypi.org: pyrtcm

RTCM3 protocol parser

  • Versions: 49
  • Dependent Packages: 4
  • Dependent Repositories: 3
  • Downloads: 54,272 Last month
  • Docker Downloads: 125
Rankings
Dependent packages count: 1.9%
Docker downloads count: 2.5%
Downloads: 2.8%
Average: 4.0%
Dependent repos count: 9.0%
Maintainers (1)
Last synced: 6 months ago

Dependencies

.github/workflows/checkpr.yml actions
  • actions/checkout v3 composite
  • actions/setup-python v4 composite
.github/workflows/main.yml actions
  • actions/checkout v3 composite
  • actions/setup-python v4 composite
  • codecov/codecov-action v3 composite
pyproject.toml pypi