pysbf2

Python library for parsing and generating Septentrio SBF GPS/GNSS protocol messages.

https://github.com/semuconsulting/pysbf2

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.5%) to scientific vocabulary

Keywords

gnss gps gps-library nmea rtcm3 sbf-protocol septentrio
Last synced: 6 months ago · JSON representation ·

Repository

Python library for parsing and generating Septentrio SBF GPS/GNSS protocol messages.

Basic Info
  • Host: GitHub
  • Owner: semuconsulting
  • License: bsd-3-clause
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 258 KB
Statistics
  • Stars: 4
  • Watchers: 1
  • Forks: 0
  • Open Issues: 0
  • Releases: 6
Topics
gnss gps gps-library nmea rtcm3 sbf-protocol septentrio
Created 9 months ago · Last pushed 6 months ago
Metadata Files
Readme Contributing Funding License Code of conduct Citation Security

README.md

pysbf2

Current Status | Installation | Message Categories | Reading | Parsing | Generating | Serializing | Examples | Extensibility | Known Issues | Author & License

pysbf2 is an original Python 3 parser for the SBF © protocol. SBF is a proprietary binary protocol implemented on Septentrio ™ GNSS receiver modules. pysbf2 can also parse NMEA 0183 © and RTCM3 © protocols via the underlying pynmeagps and pyrtcm packages from the same author - hence it covers all the common protocols that Septentrio SBF receivers are capable of outputting.

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

This is an independent project and we have no affiliation whatsoever with Septentrio.

Current Status

Status Release Build Codecov Release Date Last Commit Contributors Open Issues

The library implements a comprehensive set of messages for Septentrio Mosaic X5 devices, but is readily extensible. Refer to SBF_MSGIDS in sbftypes_core.py for the complete dictionary of messages currently supported. SBF protocol information sourced from mosaic-X5 Reference Guide v4.14.10.

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

Contributions welcome - please refer to CONTRIBUTING.MD. Feel free to discuss any proposed changes beforehand in the Discussion Channel.

Bug reports and Feature requests - please use the templates provided. For general queries and advice, post a message to one of the pysbf2 Discussions channels.


Installation

Python version PyPI version PyPI downloads

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

shell python3 -m pip install --upgrade pysbf2

If required, pysbf2 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 pysbf2

For Conda users, pysbf2 is also available from conda forge:

Anaconda-Server Badge Anaconda-Server Badge

shell conda install -c conda-forge pysbf2


Reading (Streaming)

class pysbf2.SBFreader.SBFReader(stream, *args, **kwargs)

You can create a SBFReader object by calling the constructor with an active stream object. The stream object can be any viable data stream which supports a read(n) -> bytes method (e.g. File or Serial, with or without a buffer wrapper). pysbf2 implements an internal SocketWrapper class to allow sockets to be read in the same way as other streams (see example below).

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

The constructor accepts the following optional keyword arguments:

  • protfilter: NMEA_PROTOCOL (1), SBF_PROTOCOL (2), RTCM3_PROTOCOL (4). Can be OR'd; default is NMEA_PROTOCOL | SBF_PROTOCOL | RTCM3_PROTOCOL (7)
  • quitonerror: ERR_IGNORE (0) = ignore errors, ERR_LOG (1) = log errors and continue (default), ERR_RAISE (2) = (re)raise errors and terminate
  • validate: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length
  • parsebitfield: 1 = parse bitfields ('X' type properties) as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences

Example - Serial input. This example will output both SBF and NMEA messages but not RTCM3: python from serial import Serial from pysbf2 import SBFReader, NMEA_PROTOCOL, SBF_PROTOCOL with Serial('/dev/ttyACM0', 115200, timeout=3) as stream: ubr = SBFReader(stream, protfilter=NMEA_PROTOCOL | SBF_PROTOCOL) raw_data, parsed_data = ubr.read() if parsed_data is not None: print(parsed_data)

Example - File input (using iterator). This will only output SBF data: python from pysbf2 import SBFReader, SBF_PROTOCOL with open('SBFdata.bin', 'rb') as stream: ubr = SBFReader(stream, protfilter=SBF_PROTOCOL) for raw_data, parsed_data in ubr: print(parsed_data)

Example - Socket input (using iterator). This will output SBF, NMEA and RTCM3 data: python import socket from pysbf2 import SBFReader, NMEA_PROTOCOL, SBF_PROTOCOL, RTCM3_PROTOCOL with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as stream: stream.connect(("localhost", 50007)) ubr = SBFReader(stream, protfilter=NMEA_PROTOCOL | SBF_PROTOCOL | RTCM3_PROTOCOL) for raw_data, parsed_data in ubr: print(parsed_data)


Parsing

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

NB: Once instantiated, a SBFMessage object is immutable.

The parse() method accepts the following optional keyword arguments:

  • validate: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length
  • parsebitfield: 1 = parse bitfields ('X' type properties) as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences

Example - output (GET) message: python from pysbf2 import SBFReader msg = SBFReader.parse(b"$@^b\xa6\x0f`\x00X\x9bs\x0c?\t\x01\x00\x1d\x0eX\x17\xfc\x04MA\xe6\xe4\x8b\xe6\xea)\x02\xc1\x98\x19(\xb2\x18uSA\xa6\xddABQ\x90\x018\xb4\x86q:\xc0\x93\x85\xbb\xf9\x02\x95\xd0\xe3\xaf\xe6nKl\xde?\x03\xe0V>\x00\x00\x10\x00\x8f\x02\x8f\x02\r\t2P\x01\x00\x00\x00+\x00z\x00\x88\x00`\x01") print(msg) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Type=1, Reserved1=0, AutoSet=0, 2D=0, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=48.466453552246094, Vx=3.0890401831129566e-05, Vy=0.000921349273994565, Vz=-0.004076451063156128, COG=-20000000000.0, RxClkBias=0.47535978155315045, RxClkDrift=0.20983891189098358, TimeSystem=0, Datum=0, NrSV=16, WACorrInfo=0, ReferenceID=655, MeanCorrAge=655, SignalInfo=1345456397, RAIMIntegrity=1, GalHPCAFail=0, GalIonStorm=0, Reserved2=0, NrBases=0, PPPSeedAge=0, Reserved3=0, PPPSeedType=0, Latency=43, HAccuracy=122, VAccuracy=136, BaseARP=0, PhaseCtrOffset=0, Reserved4=8, ARPOffset=1)>

If parsebitfield=False, the message is parsed without individual bit flags, e.g.: <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Mode=b'\x01', Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=48.466453552246094, Vx=3.0890401831129566e-05, Vy=0.000921349273994565, Vz=-0.004076451063156128, COG=-20000000000.0, RxClkBias=0.47535978155315045, RxClkDrift=0.20983891189098358, TimeSystem=0, Datum=0, NrSV=16, WACorrInfo=0, ReferenceID=655, MeanCorrAge=655, SignalInfo=1345456397, AlertFlag=b'\x01', NrBases=0, PPPInfo=b'\x00\x00', Latency=43, HAccuracy=122, VAccuracy=136, Misc=b'`')>

The SBFMessage object exposes different public attributes depending on its message type or 'identity', e.g. the PVTCartesian message has the following attributes:

python print(msg) print(msg.identity) print(msg.X, msg.Y, msg.Z) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Type=1, Reserved1=0, AutoSet=0, 2D=0, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=48.466453552246094, Vx=3.0890401831129566e-05, Vy=0.000921349273994565, Vz=-0.004076451063156128, COG=-20000000000.0, RxClkBias=0.47535978155315045, RxClkDrift=0.20983891189098358, TimeSystem=0, Datum=0, NrSV=16, WACorrInfo=0, ReferenceID=655, MeanCorrAge=655, SignalInfo=1345456397, RAIMIntegrity=1, GalHPCAFail=0, GalIonStorm=0, Reserved2=0, NrBases=0, PPPSeedAge=0, Reserved3=0, PPPSeedType=0, Latency=43, HAccuracy=122, VAccuracy=136, BaseARP=0, PhaseCtrOffset=0, Reserved4=8, ARPOffset=1)> PVTCartesian 3803640.1823747293, -148797.3625715144, 5100642.783697508

Decodes for various coded attributes (e.g. PVT Type or MeasEpoch SigIdxLo) are provided in sbftypes_decodes.py: python from pysbf2 import PVT_TYPE print(PVT_TYPE[msg.Type]) # msg.Type = 4 "RTK with fixed ambiguities" ```python from pysbf2 import SIGNALTYPE sigtype = SIGNALTYPE[msg.SigIdxLo02] # msg.SigIdxLo02 = 2 print(f"Frequency = {sigtype[2]} MHz, RINEX Code = {sigtype[3]}")

Frequency = 1227.6 MHz, RINEX Code = 2W ```

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

Tip: To iterate through a repeating group of attributes (e.g. PRNMaskNo), the following construct can be used:

python vals = [] # list of PRNMaskNo values from repeating group for i in range(msg.N): # N = size of repeating group PRNMaskNo = getattr(msg, f"PRNMaskNo_{i+1:02d}") vals.append(PRNMaskNo) print(vals)


Generating

class pysbf2.SBFmessage.SBFMessage(SBFClass, msgid: int, revno: int, **kwargs)

You can create a SBFMessage object by calling the constructor with the following parameters: 1. message id 2. revision number (optional, defaults to 0) 3. (optional) a series of keyword parameters representing the message payload

The 'message class' and 'message id' parameters may be passed as lookup strings, integers or bytes.

The message payload can be defined via keyword arguments in one of three ways: 1. A single keyword argument of payload containing the full payload as a sequence of bytes (any other keyword arguments will be ignored). NB the payload keyword argument must be used for message types which have a 'variable by size' repeating group. 2. One or more keyword arguments corresponding to individual message attributes. Any attributes not explicitly provided as keyword arguments will be set to a nominal value according to their type. 3. If no keyword arguments are passed, the payload is assumed to be null.

Example - to generate a PVTCartesian message, any of the following constructor formats will work:

A. Pass entire payload as bytes: python from pysbf2 import SBFMessage msg1 = SBFMessage("PVTCartesian", payload=b'X\x9bs\x0c?\t\x01\x00\x1d\x0eX\x17\xfc\x04MA\xe6\xe4\x8b\xe6\xea)\x02\xc1\x98\x19(\xb2\x18uSA\xa6\xddABQ\x90\x018\xb4\x86q:\xc0\x93\x85\xbb\xf9\x02\x95\xd0\xe3\xaf\xe6nKl\xde?\x03\xe0V>\x00\x00\x10\x00\xff\xff\xff\xff\r\t2P\x01\x00\x00\x00+\x00\xc4\x04V\x05`') print(msg1) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Type=1, Reserved1=0, AutoSet=0, 2D=0, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=48.466453552246094, Vx=3.0890401831129566e-05, Vy=0.000921349273994565, Vz=-0.004076451063156128, COG=-20000000000.0, RxClkBias=0.47535978155315045, RxClkDrift=0.20983891189098358, TimeSystem=0, Datum=0, NrSV=16, WACorrInfo=0, ReferenceID=65535, MeanCorrAge=65535, SignalInfo=1345456397, RAIMIntegrity=1, GalHPCAFail=0, GalIonStorm=0, Reserved2=0, NrBases=0, PPPSeedAge=0, Reserved3=0, PPPSeedType=0, Latency=43, HAccuracy=1220, VAccuracy=1366, BaseARP=0, PhaseCtrOffset=0, Reserved4=8, ARPOffset=1)> B. Pass individual attributes as keyword arguments: python from pysbf2 import SBFMessage msg2 = SBFMessage("PVTCartesian",TOW=208903000,WNc=2367,Mode=1,Error=0,X=3803640.1823747293,Y=-148797.3625715144,Z=5100642.783697508,Undulation=48.466453552246094,Vx=3.0890401831129566e-05,Vy=0.000921349273994565,Vz=-0.004076451063156128,COG=-20000000000.0,RxClkBias=0.47535978155315045,RxClkDrift=0.20983891189098358,TimeSystem=0,Datum=0,NrSV=16,WACorrInfo=0,ReferenceID=65535,MeanCorrAge=65535,SignalInfo=1345456397,AlertFlag=1,NrBases=0,PPPInfo=0,Latency=43,HAccuracy=1220,VAccuracy=1366,Misc=96) print(msg2) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Type=0, Reserved1=0, AutoSet=0, 2D=0, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=48.466453552246094, Vx=3.0890401831129566e-05, Vy=0.000921349273994565, Vz=-0.004076451063156128, COG=-20000000000.0, RxClkBias=0.47535978155315045, RxClkDrift=0.20983891189098358, TimeSystem=0, Datum=0, NrSV=16, WACorrInfo=0, ReferenceID=65535, MeanCorrAge=65535, SignalInfo=1345456397, RAIMIntegrity=0, GalHPCAFail=0, GalIonStorm=0, Reserved2=0, NrBases=0, PPPSeedAge=0, Reserved3=0, PPPSeedType=0, Latency=43, HAccuracy=1220, VAccuracy=1366, BaseARP=0, PhaseCtrOffset=0, Reserved4=0, ARPOffset=0)> C. Pass selected attribute as keyword argument; the rest will be set to nominal values (in this case 0): python from pysbf2 import SBFMessage msg3 = SBFMessage("PVTCartesian",TOW=208903000,WNc=2367,Mode=1,Error=0,X=3803640.1823747293,Y=-148797.3625715144,Z=5100642.783697508) print(msg3) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Type=0, Reserved1=0, AutoSet=0, 2D=0, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=0.0, Vx=0.0, Vy=0.0, Vz=0.0, COG=0.0, RxClkBias=0.0, RxClkDrift=0.0, TimeSystem=0, Datum=0, NrSV=0, WACorrInfo=0, ReferenceID=0, MeanCorrAge=0, SignalInfo=0, RAIMIntegrity=0, GalHPCAFail=0, GalIonStorm=0, Reserved2=0, NrBases=0, PPPSeedAge=0, Reserved3=0, PPPSeedType=0, Latency=0, HAccuracy=0, VAccuracy=0, BaseARP=0, PhaseCtrOffset=0, Reserved4=0, ARPOffset=0)>


Serializing

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

python from serial import Serial from pysbf2 import SBFMessage serialOut = Serial('/dev/ttyAMA0', 115200, timeout=3) from pysbf2 import SBFMessage msg = SBFMessage("PVTCartesian",TOW=208903000,WNc=2367,Mode=1,Error=0,X=3803640.1823747293,Y=-148797.3625715144,Z=5100642.783697508) print(msg) output = msg.serialize() print(output) serialOut.write(output) <SBF(PVTCartesian, TOW=10:01:25, WNc=2367, Mode=1, Error=0, X=3803640.1823747293, Y=-148797.3625715144, Z=5100642.783697508, Undulation=0.0, Vx=0.0, Vy=0.0, Vz=0.0, COG=0.0, RxClkBias=0.0, RxClkDrift=0.0, TimeSystem=0, Datum=0, NrSV=0, WACorrInfo=0, ReferenceID=0, MeanCorrAge=0, SignalInfo=0, AlertFlag=0, NrBases=0, PPPInfo=0, Latency=0, HAccuracy=0, VAccuracy=0, Misc=0)> b'$@\x81u\xa6\x0f`\x00X\x9bs\x0c?\t\x01\x00\x1d\x0eX\x17\xfc\x04MA\xe6\xe4\x8b\xe6\xea)\x02\xc1\x98\x19(\xb2\x18uSA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'


Examples

The following command line examples can be found in the \examples folder:

  1. TBC

Extensibility

The SBF protocol is principally defined in the modules sbftypes_*.py as a series of dictionaries. Message payload definitions must conform to the following rules:

1. attribute names must be unique within each message class 2. attribute types must be one of the valid types (I1, U2, X4, etc.) 3. if the attribute is scaled, attribute type is list of [attribute type as string (I1, U2, etc.), scaling factor as float] e.g. {"lat": [I4, 1e-7]} 4. 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. 'numCh' c. an 'X' attribute type ('X1', 'X2', 'X4', etc) representing a group of individual bit flags {dict} is the nested dictionary of repeating items or bitfield group

Repeating attribute names are parsed with a two-digit suffix (PRNMaskNo01, PRNMaskNo02, etc.). Nested repeating groups are supported. See "MeasEpoch" way of example.

An SBF message's content (payload) is uniquely defined by its ID (message ID and revision number); accommodating the message simply requires the addition of an appropriate dictionary entry to the sbftypes_blocks.py module.


Known Issues

  1. The following SBF message types are not yet implemented (mainly because definitions are not currently in the public domain):
    1. Meas3CN0HiRes
    2. Meas3Doppler
    3. Meas3MP
    4. Meas3PP
    5. Meas3Ranges
    6. PVTSupport
    7. PVTSupportA
    8. FugroDDS

Author & License Information

semuadmin@semuconsulting.com

GitHub License

pysbf2 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{pysbf2,
  author       = {{SEMU Consulting}},
  howpublished = {GitHub repository},
  note         = {Viewed last: xxxx:xx:xx},
  title        = {Python library for reading, parsing and generating SBF (proprietary Septentrio GNSS/GPS protocol) messages.},
  year         = {2025},
  url          = {https://github.com/semuconsulting/pysbf2},
}

GitHub Events

Total
  • Release event: 3
  • Watch event: 2
  • Delete event: 2
  • Push event: 29
  • Public event: 1
  • Pull request review event: 2
  • Pull request event: 6
  • Create event: 5
Last Year
  • Release event: 3
  • Watch event: 2
  • Delete event: 2
  • Push event: 29
  • Public event: 1
  • Pull request review event: 2
  • Pull request event: 6
  • Create event: 5

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 11
  • Total Committers: 1
  • Avg Commits per committer: 11.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 11
  • Committers: 1
  • Avg Commits per committer: 11.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
semuadmin 2****n 11

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 0
  • Total pull requests: 4
  • Average time to close issues: N/A
  • Average time to close pull requests: about 21 hours
  • Total issue authors: 0
  • Total pull request authors: 1
  • Average comments per issue: 0
  • Average comments per pull request: 0.0
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 4
  • Average time to close issues: N/A
  • Average time to close pull requests: about 21 hours
  • Issue authors: 0
  • Pull request authors: 1
  • Average comments per issue: 0
  • Average comments per pull request: 0.0
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
  • semuadmin (9)
Top Labels
Issue Labels
Pull Request Labels
enhancement (9) bug (6)

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 4,109 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 8
pypi.org: pysbf2

SBF protocol parser and generator

  • Documentation: https://pysbf2.readthedocs.io/
  • License: BSD 3-Clause License ("BSD License 2.0", "Revised BSD License", "New BSD License", or "Modified BSD License") Copyright (c) 2020, 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.
  • Latest release: 1.0.0
    published 7 months ago
  • Versions: 8
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 4,109 Last month
Rankings
Dependent packages count: 9.1%
Average: 30.2%
Dependent repos count: 51.3%
Last synced: 6 months ago

Dependencies

.github/workflows/checkpr.yml actions
  • actions/checkout v4 composite
  • actions/setup-python v5 composite
.github/workflows/main.yml actions
  • actions/checkout v4 composite
  • actions/setup-python v5 composite
pyproject.toml pypi
  • pynmeagps >= 1.0.50
  • pyrtcm >= 1.1.6