pyrtcm


Namepyrtcm JSON
Version 1.0.20 PyPI version JSON
download
home_pageNone
SummaryRTCM3 protocol parser
upload_time2024-05-08 07:07:09
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseBSD 3-Clause License ("BSD License 2.0", "Revised BSD License", "New BSD License", or "Modified BSD License") Copyright (c) 2022, SEMU Consulting All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the <organization> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pyrtcm

[Current Status](#currentstatus) |
[Installation](#installation) |
[Reading](#reading) |
[Parsing](#parsing) |
[Generating](#generating) |
[Serializing](#serializing) |
[Examples](#examples) |
[Extensibility](#extensibility) |
[Command Line Utility](#cli) |
[Graphical Client](#gui) |
[Author & License](#author)

`pyrtcm` is an original Python 3 parser for the RTCM3 &copy; GPS/GNSS protocol. RTCM3 is a proprietary GPS/GNSS [differential correction or DGPS](https://en.wikipedia.org/wiki/Differential_GPS) protocol published by the Radio Technical Commission for Maritime Services.

[RTCM STANDARD 10403.n DIFFERENTIAL GNSS (GLOBAL NAVIGATION SATELLITE SYSTEMS) SERVICES – VERSION 3](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards/products/rtcm-10403-3-differential-gnss-global-navigation-satellite-systems-services-version-3-amendment-2-may-20-2021).

The `pyrtcm` homepage is located at [https://github.com/semuconsulting/pyrtcm](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 &copy; and UBX &copy; (u-blox) GNSS/GPS messages:
- [pyubx2](http://github.com/semuconsulting/pyubx2)
- [pynmeagps](http://github.com/semuconsulting/pynmeagps)

## <a name="currentstatus">Current Status</a>

![Status](https://img.shields.io/pypi/status/pyrtcm)
![Release](https://img.shields.io/github/v/release/semuconsulting/pyrtcm?include_prereleases)
![Build](https://img.shields.io/github/actions/workflow/status/semuconsulting/pyrtcm/main.yml?branch=main)
![Codecov](https://img.shields.io/codecov/c/github/semuconsulting/pyrtcm)
![Release Date](https://img.shields.io/github/release-date-pre/semuconsulting/pyrtcm)
![Last Commit](https://img.shields.io/github/last-commit/semuconsulting/pyrtcm)
![Contributors](https://img.shields.io/github/contributors/semuconsulting/pyrtcm.svg)
![Open Issues](https://img.shields.io/github/issues-raw/semuconsulting/pyrtcm)

Parses RTCM3 messages into their constituent data fields - `DF002`, `DF003`, etc. Refer to the `RTCM_MSGIDS` dictionary in [`rtcmtypes_core.py`](https://github.com/semuconsulting/pyrtcm/blob/main/src/pyrtcm/rtcmtypes_core.py#L695) for a list of message types currently implemented. Additional message types can be readily added - see [Extensibility](#extensibility).

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

Contributions welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pyrtcm/blob/master/CONTRIBUTING.md).

[Bug reports](https://github.com/semuconsulting/pyrtcm/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) and [Feature requests](https://github.com/semuconsulting/pyrtcm/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) - please use the templates provided. For general queries and advice, post a message to one of the [pyrtcm Discussions](https://github.com/semuconsulting/pyrtcm/discussions) channels.

---
## <a name="installation">Installation</a>

`pyrtcm` is compatible with Python >=3.8 and has no third-party library dependencies.

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

![Python version](https://img.shields.io/pypi/pyversions/pyrtcm.svg?style=flat)
[![PyPI version](https://img.shields.io/pypi/v/pyrtcm.svg?style=flat)](https://pypi.org/project/pyrtcm/)
![PyPI downloads](https://img.shields.io/pypi/dm/pyrtcm.svg?style=flat)

The recommended way to install the latest version of `pyrtcm` is with
[pip](http://pypi.python.org/pypi/pip/):

```shell
python3 -m pip install --upgrade pyrtcm
```

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

```shell
python3 -m pip install --user --upgrade virtualenv
python3 -m virtualenv env
source env/bin/activate (or env\Scripts\activate on Windows)
(env) python3 -m pip install --upgrade pyrtcm
...
deactivate
```

For [Conda](https://docs.conda.io/en/latest/) users, `pyrtcm` is also available from [conda-forge](https://github.com/conda-forge/pyrtcm-feedstock):

[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyrtcm/badges/version.svg)](https://anaconda.org/conda-forge/pyrtcm)
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyrtcm/badges/downloads.svg)](https://anaconda.org/conda-forge/pyrtcm)

```shell
conda install -c conda-forge pyrtcm
```

---
## <a name="reading">Reading (Streaming)</a>

```
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()
  print(parsed_data)
```
```
 <RTCM(1077, DF002=1077, DF003=0, GNSSEpoch=204137001, DF393=1, DF409=0, DF001_7=0, DF411=0, DF412=0, DF417=0, DF418=0, DF394=760738918298550272, NSat=10, DF395=1073807360, NSig=2, DF396=1044459, DF397_01(005)=75, DF397_02(007)=75, DF397_03(009)=81, ..., DF404_19(030,1C)=0.0, DF404_20(030,2L)=0.0)>,
```

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)
```

---
## <a name="parsing">Parsing</a>

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 `1087` multiple signal message (MSM) contains the following data fields:

```python
print(msg)
print(msg.identity)
print(msg.DF034)
print(msg.DF419_03)
```
```
<RTCM(1087, DF002=1087, DF003=0, DF416=2, DF034=42119001, DF393=1, DF409=0, DF001_7=0, DF411=0, DF412=0, DF417=0, DF418=0, DF394=4039168114821169152, NSat=7, DF395=1090519040, NSig=2, DF396=16382, NCell=13, DF397_01(003)=69, DF397_02(004)=64, DF397_03(005)=73, DF397_04(013)=76, DF397_05(014)=66, DF397_06(015)=70, DF397_07(023)=78, DF419_01(003)=12, DF419_02(004)=13, DF419_03(005)=8, DF419_04(013)=5, DF419_05(014)=0, DF419_06(015)=7, DF419_07(023)=10, DF398_01(003)=0.6337890625, DF398_02(004)=0.3427734375, DF398_03(005)=0.25390625, DF398_04(013)=0.310546875, DF398_05(014)=0.5126953125, DF398_06(015)=0.8271484375, DF398_07(023)=0.8837890625, DF399_01(003)=-665, DF399_02(004)=29, DF399_03(005)=672, DF399_04(013)=-573, DF399_05(014)=-211, DF399_06(015)=312, DF399_07(023)=317, DF405_01(003,1C)=0.00024936161935329437, ... , DF404_12(015,2C)=0.3947, DF404_13(023,1C)=0.6146)>
'1087'
42119001
8
```

Attributes within repeating groups are parsed with a two-digit suffix (`DF419_01`, `DF419_02`, etc. See [example below](#iterating) for an illustration of how to iterate through grouped attributes). Attributes within MSM NSAT and NCELL repeating groups can optionally be labelled with their corresponding satellite PRN and signal ID when the `__str__()` (`print()`) method is invoked, by setting the keyword argument `labelmsm` to True - e.g. `DF404_13(023,1C)` signifies that the 13th item in the DF404 ("fine Phase Range Rate") group refers to satellite PRN 023, signal ID 1C.

Helper methods are available to interpret the individual datafields:

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

The `payload` attribute always contains the raw payload as bytes.

#### <a name="iterating">Iterating Through Group Attributes</a>

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 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 ("DF405", "DF406", "DF407", "DF408", "DF420", "DF404"):
    val = getattr(msg, f"{attr}_{i+1:02d}")
    vals.append(val)
  msmarray.append(vals)
print(msmarray)
```
```shell
[[0.00014309026300907135, 0.00014193402603268623, 341, 45.0, 0, -0.9231], [0.00014183297753334045, 0.00014339853078126907, 341, 38.0, 0, -0.9194], ... etc.]
```

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.

---
## <a name="generating">Generating</a>

```
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)>
```

---
## <a name="serializing">Serializing</a>

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'
```

---
## <a name="examples">Examples</a>

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.
1. `rtcmfile.py` - illustrates how to stream RTCM data from binary log file.
1. `rtcmsocket.py` - illustrates how to implement a TCP Socket reader for RTCM messages using RTCMReader iterator functionality.
1. `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.
1. `rtcm_ntrip_client.py` - illustrates a simple [NTRIP](https://en.wikipedia.org/wiki/Networked_Transport_of_RTCM_via_Internet_Protocol) client using pyrtcm to parse the RTCM3 output.

---
## <a name="extensibility">Extensibility</a>

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.

---
## <a name="cli">Command Line Utility</a>

A command line utility `gnssdump` 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 `gnssdump` utility, type:
```
gnssdump -h
```

---
## <a name="gui">Graphical Client</a>

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

[https://github.com/semuconsulting/PyGPSClient](https://github.com/semuconsulting/PyGPSClient)

---
## <a name="author">Author & License Information</a>

semuadmin@semuconsulting.com

![License](https://img.shields.io/github/license/semuconsulting/pyrtcm.svg)

`pyrtcm` is maintained entirely by unpaid volunteers. It receives no funding from advertising or corporate sponsorship. If you find the library useful, a small donation would be greatly appreciated!

[![Donations](https://www.paypalobjects.com/en_GB/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate/?business=UL24WUA4XHNRY&no_recurring=0&item_name=The+SEMU+GNSS+Python+libraries+are+maintained+entirely+by+unpaid+volunteers.+All+donations+are+greatly+appreciated.&currency_code=GBP)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pyrtcm",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "semuadmin <semuadmin@semuconsulting.com>",
    "keywords": null,
    "author": null,
    "author_email": "semuadmin <semuadmin@semuconsulting.com>",
    "download_url": "https://files.pythonhosted.org/packages/b4/05/23a43f6978f19bde690d35ff50f65a81fd259d938526b6e8b7c3172ec371/pyrtcm-1.0.20.tar.gz",
    "platform": null,
    "description": "# pyrtcm\n\n[Current Status](#currentstatus) |\n[Installation](#installation) |\n[Reading](#reading) |\n[Parsing](#parsing) |\n[Generating](#generating) |\n[Serializing](#serializing) |\n[Examples](#examples) |\n[Extensibility](#extensibility) |\n[Command Line Utility](#cli) |\n[Graphical Client](#gui) |\n[Author & License](#author)\n\n`pyrtcm` is an original Python 3 parser for the RTCM3 &copy; GPS/GNSS protocol. RTCM3 is a proprietary GPS/GNSS [differential correction or DGPS](https://en.wikipedia.org/wiki/Differential_GPS) protocol published by the Radio Technical Commission for Maritime Services.\n\n[RTCM STANDARD 10403.n DIFFERENTIAL GNSS (GLOBAL NAVIGATION SATELLITE SYSTEMS) SERVICES \u2013 VERSION 3](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards/products/rtcm-10403-3-differential-gnss-global-navigation-satellite-systems-services-version-3-amendment-2-may-20-2021).\n\nThe `pyrtcm` homepage is located at [https://github.com/semuconsulting/pyrtcm](https://github.com/semuconsulting/pyrtcm).\n\nThis is an independent project and we have no affiliation whatsoever with the Radio Technical Commission for Maritime Services.\n\n**FYI** There are companion libraries which handle standard NMEA 0183 &copy; and UBX &copy; (u-blox) GNSS/GPS messages:\n- [pyubx2](http://github.com/semuconsulting/pyubx2)\n- [pynmeagps](http://github.com/semuconsulting/pynmeagps)\n\n## <a name=\"currentstatus\">Current Status</a>\n\n![Status](https://img.shields.io/pypi/status/pyrtcm)\n![Release](https://img.shields.io/github/v/release/semuconsulting/pyrtcm?include_prereleases)\n![Build](https://img.shields.io/github/actions/workflow/status/semuconsulting/pyrtcm/main.yml?branch=main)\n![Codecov](https://img.shields.io/codecov/c/github/semuconsulting/pyrtcm)\n![Release Date](https://img.shields.io/github/release-date-pre/semuconsulting/pyrtcm)\n![Last Commit](https://img.shields.io/github/last-commit/semuconsulting/pyrtcm)\n![Contributors](https://img.shields.io/github/contributors/semuconsulting/pyrtcm.svg)\n![Open Issues](https://img.shields.io/github/issues-raw/semuconsulting/pyrtcm)\n\nParses RTCM3 messages into their constituent data fields - `DF002`, `DF003`, etc. Refer to the `RTCM_MSGIDS` dictionary in [`rtcmtypes_core.py`](https://github.com/semuconsulting/pyrtcm/blob/main/src/pyrtcm/rtcmtypes_core.py#L695) for a list of message types currently implemented. Additional message types can be readily added - see [Extensibility](#extensibility).\n\nSphinx API Documentation in HTML format is available at [https://www.semuconsulting.com/pyrtcm](https://www.semuconsulting.com/pyrtcm).\n\nContributions welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pyrtcm/blob/master/CONTRIBUTING.md).\n\n[Bug reports](https://github.com/semuconsulting/pyrtcm/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) and [Feature requests](https://github.com/semuconsulting/pyrtcm/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) - please use the templates provided. For general queries and advice, post a message to one of the [pyrtcm Discussions](https://github.com/semuconsulting/pyrtcm/discussions) channels.\n\n---\n## <a name=\"installation\">Installation</a>\n\n`pyrtcm` is compatible with Python >=3.8 and has no third-party library dependencies.\n\nIn the following, `python3` & `pip` refer to the Python 3 executables. You may need to type \n`python` or `pip3`, depending on your particular environment.\n\n![Python version](https://img.shields.io/pypi/pyversions/pyrtcm.svg?style=flat)\n[![PyPI version](https://img.shields.io/pypi/v/pyrtcm.svg?style=flat)](https://pypi.org/project/pyrtcm/)\n![PyPI downloads](https://img.shields.io/pypi/dm/pyrtcm.svg?style=flat)\n\nThe recommended way to install the latest version of `pyrtcm` is with\n[pip](http://pypi.python.org/pypi/pip/):\n\n```shell\npython3 -m pip install --upgrade pyrtcm\n```\n\nIf required, `pyrtcm` can also be installed into a virtual environment, e.g.:\n\n```shell\npython3 -m pip install --user --upgrade virtualenv\npython3 -m virtualenv env\nsource env/bin/activate (or env\\Scripts\\activate on Windows)\n(env) python3 -m pip install --upgrade pyrtcm\n...\ndeactivate\n```\n\nFor [Conda](https://docs.conda.io/en/latest/) users, `pyrtcm` is also available from [conda-forge](https://github.com/conda-forge/pyrtcm-feedstock):\n\n[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyrtcm/badges/version.svg)](https://anaconda.org/conda-forge/pyrtcm)\n[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyrtcm/badges/downloads.svg)](https://anaconda.org/conda-forge/pyrtcm)\n\n```shell\nconda install -c conda-forge pyrtcm\n```\n\n---\n## <a name=\"reading\">Reading (Streaming)</a>\n\n```\nclass pyrtcm.rtcmreader.RTCMReader(stream, **kwargs)\n```\n\nYou can create a `RTCMReader` object by calling the constructor with an active stream object. \nThe stream object can be any data stream which supports a `read(n) -> bytes` method (e.g. File or Serial, with \nor 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).\n\nIndividual 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.\n\nExample -  Serial input:\n```python\nfrom serial import Serial\nfrom pyrtcm import RTCMReader\nwith Serial('/dev/tty.usbmodem14101', 9600, timeout=3) as stream:\n  rtr = RTCMReader(stream)\n  raw_data, parsed_data = rtr.read()\n  print(parsed_data)\n```\n```\n <RTCM(1077, DF002=1077, DF003=0, GNSSEpoch=204137001, DF393=1, DF409=0, DF001_7=0, DF411=0, DF412=0, DF417=0, DF418=0, DF394=760738918298550272, NSat=10, DF395=1073807360, NSig=2, DF396=1044459, DF397_01(005)=75, DF397_02(007)=75, DF397_03(009)=81, ..., DF404_19(030,1C)=0.0, DF404_20(030,2L)=0.0)>,\n```\n\nExample - File input (using iterator).\n```python\nfrom pyrtcm import RTCMReader\nwith open('rtcmdata.log', 'rb') as stream:\n  rtr = RTCMReader(stream)\n  for raw_data, parsed_data in rtr:\n    print(parsed_data)\n```\n\nExample - Socket input (using iterator):\n```python\nimport socket\nfrom pyrtcm import RTCMReader\nwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as stream:\n  stream.connect((\"localhost\", 50007))\n  rtr = RTCMReader(stream)\n  for raw_data, parsed_data in rtr:\n    print(parsed_data)\n```\n\n---\n## <a name=\"parsing\">Parsing</a>\n\nYou 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.\n\n**NB:** Once instantiated, an `RTCMMessage` object is immutable.\n\nExample:\n```python\nfrom pyrtcm import RTCMReader\nmsg = RTCMReader.parse(b\"\\xd3\\x00\\x13>\\xd0\\x00\\x03\\x8aX\\xd9I<\\x87/4\\x10\\x9d\\x07\\xd6\\xafH Z\\xd7\\xf7\")\nprint(msg)\n```\n```\n<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)>\n```\n\nThe `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 `1087` multiple signal message (MSM) contains the following data fields:\n\n```python\nprint(msg)\nprint(msg.identity)\nprint(msg.DF034)\nprint(msg.DF419_03)\n```\n```\n<RTCM(1087, DF002=1087, DF003=0, DF416=2, DF034=42119001, DF393=1, DF409=0, DF001_7=0, DF411=0, DF412=0, DF417=0, DF418=0, DF394=4039168114821169152, NSat=7, DF395=1090519040, NSig=2, DF396=16382, NCell=13, DF397_01(003)=69, DF397_02(004)=64, DF397_03(005)=73, DF397_04(013)=76, DF397_05(014)=66, DF397_06(015)=70, DF397_07(023)=78, DF419_01(003)=12, DF419_02(004)=13, DF419_03(005)=8, DF419_04(013)=5, DF419_05(014)=0, DF419_06(015)=7, DF419_07(023)=10, DF398_01(003)=0.6337890625, DF398_02(004)=0.3427734375, DF398_03(005)=0.25390625, DF398_04(013)=0.310546875, DF398_05(014)=0.5126953125, DF398_06(015)=0.8271484375, DF398_07(023)=0.8837890625, DF399_01(003)=-665, DF399_02(004)=29, DF399_03(005)=672, DF399_04(013)=-573, DF399_05(014)=-211, DF399_06(015)=312, DF399_07(023)=317, DF405_01(003,1C)=0.00024936161935329437, ... , DF404_12(015,2C)=0.3947, DF404_13(023,1C)=0.6146)>\n'1087'\n42119001\n8\n```\n\nAttributes within repeating groups are parsed with a two-digit suffix (`DF419_01`, `DF419_02`, etc. See [example below](#iterating) for an illustration of how to iterate through grouped attributes). Attributes within MSM NSAT and NCELL repeating groups can optionally be labelled with their corresponding satellite PRN and signal ID when the `__str__()` (`print()`) method is invoked, by setting the keyword argument `labelmsm` to True - e.g. `DF404_13(023,1C)` signifies that the 13th item in the DF404 (\"fine Phase Range Rate\") group refers to satellite PRN 023, signal ID 1C.\n\nHelper methods are available to interpret the individual datafields:\n\n```python\nfrom pyrtcm import RTCM_DATA_FIELDS, datasiz, datascale, datadesc\ndfname = \"DF012\"\nprint(RTCM_DATA_FIELDS[dfname])\nprint(datasiz(dfname))\nprint(datascale(dfname))\nprint(datadesc(dfname))\n```\n```\n(INT20, 0.0001, \"GPS L1 PhaseRange - L1 Pseudorange\")\n20\n0.0001\n'GPS L1 PhaseRange - L1 Pseudorange'\n```\n\nThe `payload` attribute always contains the raw payload as bytes.\n\n#### <a name=\"iterating\">Iterating Through Group Attributes</a>\n\nTo 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 DF405, DF406, DF407, DF408, DF420 and DF404 are extracted from an MSM 1077 message `msg` and collated in the array `msmarray`):\n\n```python\nmsmarray = []\nfor i in range(msg.NCell): # msg = MSM 1077, number of cells = NCell\n  vals = []\n  for attr in (\"DF405\", \"DF406\", \"DF407\", \"DF408\", \"DF420\", \"DF404\"):\n    val = getattr(msg, f\"{attr}_{i+1:02d}\")\n    vals.append(val)\n  msmarray.append(vals)\nprint(msmarray)\n```\n```shell\n[[0.00014309026300907135, 0.00014193402603268623, 341, 45.0, 0, -0.9231], [0.00014183297753334045, 0.00014339853078126907, 341, 38.0, 0, -0.9194], ... etc.]\n```\n\nThe following dedicated helper methods are available to parse selected RTCM3 message types into a series of iterable data arrays:\n- `parse_msm` - for MSM message types (e.g. 1077, 1125, etc.).\n- `parse_4076_201` - for 4076_201 SSR (harmonic coefficients) message types.\n\n---\n## <a name=\"generating\">Generating</a>\n\n```\nclass pyrtcm.rtcmmessage.RTCMMessage(**kwargs)\n```\n\nYou can create an `RTCMMessage` object by calling the constructor with the following keyword arguments:\n1. payload as bytes\n\nExample:\n\n```python\nfrom pyrtcm import RTCMMessage\nmsg = RTCMMessage(payload=b\">\\xd0\\x00\\x03\\x8aX\\xd9I<\\x87/4\\x10\\x9d\\x07\\xd6\\xafH \")\nprint(msg)\n```\n```\n<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)>\n```\n\n---\n## <a name=\"serializing\">Serializing</a>\n\nThe `RTCMMessage` class implements a `serialize()` method to convert a `RTCMMessage` object to a bytes array suitable for writing to an output stream.\n\ne.g. to create and send a `1005` message type:\n\n```python\nfrom serial import Serial\nfrom pyrtcm import RTCMMessage\nserialOut = Serial('COM7', 38400, timeout=5)\nmsg = RTCMMessage(payload=b\">\\xd0\\x00\\x03\\x8aX\\xd9I<\\x87/4\\x10\\x9d\\x07\\xd6\\xafH \")\nprint(msg)\noutput = msg.serialize()\nprint(output)\nserialOut.write(output)\n```\n```\n<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)>\nb'\\xd3\\x00\\x13>\\xd0\\x00\\x03\\x8aX\\xd9I<\\x87/4\\x10\\x9d\\x07\\xd6\\xafH Z\\xd7\\xf7'\n```\n\n---\n## <a name=\"examples\">Examples</a>\n\nThe following examples are available in the /examples folder:\n\n1. `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.\n1. `rtcmfile.py` - illustrates how to stream RTCM data from binary log file.\n1. `rtcmsocket.py` - illustrates how to implement a TCP Socket reader for RTCM messages using RTCMReader iterator functionality.\n1. `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.\n1. `rtcm_ntrip_client.py` - illustrates a simple [NTRIP](https://en.wikipedia.org/wiki/Networked_Transport_of_RTCM_via_Internet_Protocol) client using pyrtcm to parse the RTCM3 output.\n\n---\n## <a name=\"extensibility\">Extensibility</a>\n\nThe 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:\n\n```\n1. datafield names must be unique within each message class\n2. datafield types must be one of the valid data fields (\"DF026\", \"DF059\", etc.)\n3. repeating or bitfield groups must be defined as a tuple ('numr', {dict}), where:\n   'numr' is either:\n     a. an integer representing a fixed number of repeats e.g. 32\n     b. a string representing the name of a preceding attribute containing the number of repeats e.g. 'DF029'\n   {dict} is the nested dictionary of repeating items or bitfield group\n```\n\nRepeating attribute names are parsed with a two-digit suffix (\"DF030_01\", \"DF030_02\", etc.). Nested repeating groups are supported.\n\n---\n## <a name=\"cli\">Command Line Utility</a>\n\nA command line utility `gnssdump` 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.\n\nTo install `pygnssutils`:\n```\npython3 -m pip install --upgrade pygnssutils\n```\n\nFor help with the `gnssdump` utility, type:\n```\ngnssdump -h\n```\n\n---\n## <a name=\"gui\">Graphical Client</a>\n\nA python/tkinter graphical GPS client which supports NMEA, UBX, RTCM3, NTRIP and SPARTN protocols is available at: \n\n[https://github.com/semuconsulting/PyGPSClient](https://github.com/semuconsulting/PyGPSClient)\n\n---\n## <a name=\"author\">Author & License Information</a>\n\nsemuadmin@semuconsulting.com\n\n![License](https://img.shields.io/github/license/semuconsulting/pyrtcm.svg)\n\n`pyrtcm` is maintained entirely by unpaid volunteers. It receives no funding from advertising or corporate sponsorship. If you find the library useful, a small donation would be greatly appreciated!\n\n[![Donations](https://www.paypalobjects.com/en_GB/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate/?business=UL24WUA4XHNRY&no_recurring=0&item_name=The+SEMU+GNSS+Python+libraries+are+maintained+entirely+by+unpaid+volunteers.+All+donations+are+greatly+appreciated.&currency_code=GBP)\n",
    "bugtrack_url": null,
    "license": "BSD 3-Clause License (\"BSD License 2.0\", \"Revised BSD License\", \"New BSD License\", or \"Modified BSD License\")  Copyright (c) 2022, SEMU Consulting All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the <organization> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ",
    "summary": "RTCM3 protocol parser",
    "version": "1.0.20",
    "project_urls": {
        "changelog": "https://github.com/semuconsulting/pyrtcm/blob/master/RELEASE_NOTES.md",
        "documentation": "https://www.semuconsulting.com/pyrtcm/",
        "homepage": "https://github.com/semuconsulting/pyrtcm",
        "repository": "https://github.com/semuconsulting/pyrtcm"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c9f69d4b5e839690ef9246490647b8c3c661dd5e4ed369373440de7125c096b4",
                "md5": "4309468a32b78581a199c35e1666d59d",
                "sha256": "fb659826320226d25a760669961cc11be05e46e5e4c36e78eef092e3ce426865"
            },
            "downloads": -1,
            "filename": "pyrtcm-1.0.20-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4309468a32b78581a199c35e1666d59d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 41692,
            "upload_time": "2024-05-08T07:07:08",
            "upload_time_iso_8601": "2024-05-08T07:07:08.106095Z",
            "url": "https://files.pythonhosted.org/packages/c9/f6/9d4b5e839690ef9246490647b8c3c661dd5e4ed369373440de7125c096b4/pyrtcm-1.0.20-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b40523a43f6978f19bde690d35ff50f65a81fd259d938526b6e8b7c3172ec371",
                "md5": "5ccd8239bf7fade473d0580a55bda2d4",
                "sha256": "1108adf2f4cbd80b2f28339d6a68cf07d36dd8ac922a3140f328bf73850dcb21"
            },
            "downloads": -1,
            "filename": "pyrtcm-1.0.20.tar.gz",
            "has_sig": false,
            "md5_digest": "5ccd8239bf7fade473d0580a55bda2d4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 93607,
            "upload_time": "2024-05-08T07:07:09",
            "upload_time_iso_8601": "2024-05-08T07:07:09.875461Z",
            "url": "https://files.pythonhosted.org/packages/b4/05/23a43f6978f19bde690d35ff50f65a81fd259d938526b6e8b7c3172ec371/pyrtcm-1.0.20.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-08 07:07:09",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "semuconsulting",
    "github_project": "pyrtcm",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyrtcm"
}
        
Elapsed time: 0.26295s