SkillAgentSearch skills...

Pyspartn

Python library for parsing SPARTN protocol messages.

Install / Use

/learn @semuconsulting/Pyspartn
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

pyspartn

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

pyspartn is an original Python 3 parser for the SPARTN © GPS/GNSS protocol. SPARTN is an open-source PPP-RTK GNSS protocol published by u-blox.

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

This is an independent project and we have no affiliation whatsoever with u-blox.

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

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

Status Release Build Codecov Release Date Last Commit Contributors Open Issues

The SPARTNReader class is capable of parsing individual SPARTN transport-layer messages from a binary data stream containing solely SPARTN data, with their associated metadata (message type/subtype, payload length, encryption parameters, etc.).

The SPARTNMessage class implements optional decrypt and decode algorithms for individual OCB, HPAC, GAD, BPAC and EAS-DYN message types.

Note that u-blox discontinued their encrypted L-Band and MQTT SPARTN services in October 2025. At time of writing, the subscription-based u-blox Thingstream Point Perfect Flex © NTRIP (IP) service is the principal source of SPARTN PPP-RTK correction data for most users.

Information sourced from public domain protocol specification SPARTN Protocol v2.0.3 (November 2025) © 2025 u-blox AG. All rights reserved.

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

Contributions welcome - please refer to CONTRIBUTING.MD.

Bug reports and Feature requests - please use the templates provided. For general queries and advice, please use the Discussion Forum.

No Copilot


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

Python version PyPI version PyPI downloads

pyspartn is compatible with Python >= 3.10.

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 pyspartn is with pip:

python3 -m pip install --upgrade pyspartn

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

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

pyspartn can utilise the Python cryptography package to decrypt encrypted SPARTN message payloads¹ ², but as of version 1.0.8 this is not installed by default. To enable SPARTN decryption support, install the cryptography package separately:

python3 -m pip install --upgrade cryptography

¹ The boolean attribute pyspartn.HASCRYPTO can be used to test if decryption support is available at runtime.

² On some 32-bit Linux platforms (e.g. Raspberry Pi OS 32), it may be necessary to install Rust compiler support in order to install the cryptography package which pyspartn depends on to decrypt SPARTN message payloads. See cryptography install README.

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

Anaconda-Server Badge Anaconda-Server Badge

conda install -c conda-forge pyspartn

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

class pyspartn.spartnreader.SPARTNReader(stream, **kwargs)

You can create a SPARTNReader 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). pyspartn implements an internal SocketWrapper class to allow sockets to be read in the same way as other streams.

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

The constructor accepts the following optional keyword arguments:

  • validate: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length.
  • quitonerror: ERR_IGNORE (0) = ignore errors, ERR_LOG (1) = log errors and continue (default), ERR_RAISE (2) = (re)raise errors and terminate.
  • decode: True (1) = decode payload, False (0, default) = do not decode payload (parse transport layer only).
  • key: decryption key for encrypted payloads (eaf=1). See Encrypted Payloads below.
  • basedate: decryption basedate for encrypted payloads where timeTagtype=0.
  • timetags: a dictionary of 32-bit gnssTimeTag values accumulated from the current datastream, which can be used to decrypt specific message subtypes.

Example - Serial input, without decoding:

from serial import Serial
from pyspartn import SPARTNReader
with Serial('/dev/tty.usbmodem14101', 38400, timeout=3) as stream:
   spr = SPARTNReader(stream, decode=False)
   raw_data, parsed_data = spr.read()
   if parsed_data is not None:
      print(parsed_data)

Example - File input (using iterator), with decoding:

from pyspartn import SPARTNReader
with open('spartndata.log', 'rb') as stream:
   spr = SPARTNReader(stream, decode=True)
   for raw_data, parsed_data in spr:
      print(parsed_data)

Example - Socket input (using iterator):

import socket
from pyspartn import SPARTNReader
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as stream:
   stream.connect(("localhost", 50007))
   spr = SPARTNReader(stream, decode=True)
   for raw_data, parsed_data in spr:
      print(parsed_data)

Encrypted Payloads

Legacy SPARTN message sources (e.g. the now-discontinued Thingstream PointPerfect © MQTT and L-Band services) used encrypted payloads (eaf=1). In order to decrypt and decode these payloads, a valid decryption key is required. Keys are typically 32-character hexadecimal strings valid for a 4 week period.

In addition to the key, the SPARTN decryption algorithm requires a 32-bit gnssTimeTag value. The provision of this 32-bit gnssTimeTag depends on the incoming data stream:

  • Some SPARTN message types (e.g. HPAC and a few OCB messages) include the requisite 32-bit gnssTimeTag in the message header (denoted by timeTagtype=1). Others (e.g. GAD and most OCB messages) use an ambiguous 16-bit gnssTimeTag value for reasons of brevity (denoted by timeTagtype=0). In these circumstances, a nominal 'basedate' must be provided by the user, representing the UTC datetime on which the datastream was originally created to the nearest half day, in order to convert the 16-bit gnssTimeTag to an unambiguous 32-bit value.
  • If you're parsing data in real time, this basedate can be left at the default datetime.now(timezone.utc).
  • If you're parsing historical data, you will need to provide a basedate representing the UTC datetime on which the data stream was originally created, to the nearest half day.
  • If a nominal basedate of TIMEBASE (datetime(2010, 1, 1, 0, 0, tzinfo=timezone.utc)) is provided, pyspartn.SPARTNReader can attempt to derive the requisite gnssTimeTag value from any 32-bit gnssTimetag in a preceding message of the same subtype in the same data stream, but *unless and u
View on GitHub
GitHub Stars10
CategoryDevelopment
Updated1d ago
Forks4

Languages

Python

Security Score

95/100

Audited on Mar 27, 2026

No findings