{"id":28413148,"url":"https://github.com/semuconsulting/pysbf2","last_synced_at":"2025-06-24T20:31:37.647Z","repository":{"id":294940937,"uuid":"987057958","full_name":"semuconsulting/pysbf2","owner":"semuconsulting","description":"Python library for parsing and generating Septentrio SBF GPS/GNSS protocol messages.","archived":false,"fork":false,"pushed_at":"2025-06-24T08:26:15.000Z","size":194,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-24T08:54:07.886Z","etag":null,"topics":["gnss","gps","gps-library","nmea","rtcm3","sbf-protocol","septentrio"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/semuconsulting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.bib","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"buy_me_a_coffee":"semuconsulting"}},"created_at":"2025-05-20T14:08:41.000Z","updated_at":"2025-06-24T08:24:40.000Z","dependencies_parsed_at":"2025-05-22T20:07:11.408Z","dependency_job_id":"b89b4167-477f-4afa-9c5a-b517a5a9dcac","html_url":"https://github.com/semuconsulting/pysbf2","commit_stats":null,"previous_names":["semuconsulting/pysbf2"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/semuconsulting/pysbf2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semuconsulting%2Fpysbf2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semuconsulting%2Fpysbf2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semuconsulting%2Fpysbf2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semuconsulting%2Fpysbf2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/semuconsulting","download_url":"https://codeload.github.com/semuconsulting/pysbf2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semuconsulting%2Fpysbf2/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261751608,"owners_count":23204457,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gnss","gps","gps-library","nmea","rtcm3","sbf-protocol","septentrio"],"created_at":"2025-06-03T03:47:27.933Z","updated_at":"2025-06-24T20:31:37.636Z","avatar_url":"https://github.com/semuconsulting.png","language":"Python","funding_links":["https://buymeacoffee.com/semuconsulting"],"categories":[],"sub_categories":[],"readme":"pysbf2\r\n=======\r\n\r\n[Current Status](#currentstatus) |\r\n[Installation](#installation) |\r\n[Message Categories](#msgcat) |\r\n[Reading](#reading) |\r\n[Parsing](#parsing) |\r\n[Generating](#generating) |\r\n[Serializing](#serializing) |\r\n[Examples](#examples) |\r\n[Extensibility](#extensibility) |\r\n[Known Issues](#knownissues) |\r\n[Author \u0026 License](#author)\r\n\r\n`pysbf2` is an original Python 3 parser for the SBF \u0026copy; protocol. SBF is a proprietary binary protocol implemented on Septentrio \u0026trade; GNSS receiver modules. `pysbf2` can also parse NMEA 0183 \u0026copy; and RTCM3 \u0026copy; protocols via the underlying [`pynmeagps`](https://github.com/semuconsulting/pynmeagps) and [`pyrtcm`](https://github.com/semuconsulting/pyrtcm) packages from the same author - hence it covers all the common protocols that Septentrio SBF receivers are capable of outputting.\r\n\r\nThe `psbf2` homepage is located at [https://github.com/semuconsulting/pysbf2](https://github.com/semuconsulting/pysbf2).\r\n\r\nThis is an independent project and we have no affiliation whatsoever with Septentrio.\r\n\r\n## \u003ca name=\"currentstatus\"\u003eCurrent Status\u003c/a\u003e\r\n\r\n![Status](https://img.shields.io/pypi/status/pysbf2)\r\n![Release](https://img.shields.io/github/v/release/semuconsulting/pysbf2?include_prereleases)\r\n![Build](https://img.shields.io/github/actions/workflow/status/semuconsulting/pysbf2/main.yml?branch=main)\r\n![Codecov](https://img.shields.io/codecov/c/github/semuconsulting/pysbf2)\r\n![Release Date](https://img.shields.io/github/release-date-pre/semuconsulting/pysbf2)\r\n![Last Commit](https://img.shields.io/github/last-commit/semuconsulting/pysbf2)\r\n![Contributors](https://img.shields.io/github/contributors/semuconsulting/pysbf2.svg)\r\n![Open Issues](https://img.shields.io/github/issues-raw/semuconsulting/pysbf2)\r\n\r\nThe library implements a comprehensive set of messages for Septentrio Mosaic X5 devices, but is readily [extensible](#extensibility). Refer to `SBF_MSGIDS` in [sbftypes_core.py](https://github.com/semuconsulting/pysbf2/blob/main/src/pysbf2/sbftypes_core.py#L111) for the complete dictionary of messages currently supported. SBF protocol information sourced from mosaic-X5 Reference Guide v4.14.10.\r\n\r\nSphinx API Documentation in HTML format is available at [https://www.semuconsulting.com/pysbf2/](https://www.semuconsulting.com/pysbf2/).\r\n\r\nContributions welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pysbf2/blob/master/CONTRIBUTING.md). Feel free to discuss any proposed changes beforehand in the [Discussion Channel](https://github.com/semuconsulting/pysbf2/discussions/categories/ideas).\r\n\r\n[Bug reports](https://github.com/semuconsulting/pysbf2/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) and [Feature requests](https://github.com/semuconsulting/pysbf2/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 [pysbf2 Discussions](https://github.com/semuconsulting/pysbf2/discussions) channels.\r\n\r\n---\r\n## \u003ca name=\"installation\"\u003eInstallation\u003c/a\u003e\r\n\r\n![Python version](https://img.shields.io/pypi/pyversions/pysbf2.svg?style=flat)\r\n[![PyPI version](https://img.shields.io/pypi/v/pysbf2.svg?style=flat)](https://pypi.org/project/pysbf2/)\r\n![PyPI downloads](https://img.shields.io/pypi/dm/pysbf2.svg?style=flat)\r\n\r\n`pysbf2` is compatible with Python 3.9 - 3.13. In the following, `python3` \u0026 `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`*).\r\n\r\nThe recommended way to install the latest version of `pysbf2` is with [pip](http://pypi.python.org/pypi/pip/):\r\n\r\n```shell\r\npython3 -m pip install --upgrade pysbf2\r\n```\r\n\r\nIf required, `pysbf2` can also be installed into a virtual environment, e.g.:\r\n\r\n```shell\r\npython3 -m venv env\r\nsource env/bin/activate # (or env\\Scripts\\activate on Windows)\r\npython3 -m pip install --upgrade pysbf2\r\n```\r\n\r\nFor [Conda](https://docs.conda.io/en/latest/) users, `pysbf2` is also available from [conda forge](https://github.com/conda-forge/pysbf2-feedstock):\r\n\r\n[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pysbf2/badges/version.svg)](https://anaconda.org/conda-forge/pysbf2)\r\n[![Anaconda-Server Badge](https://img.shields.io/conda/dn/conda-forge/pysbf2)](https://anaconda.org/conda-forge/pysbf2)\r\n\r\n```shell\r\nconda install -c conda-forge pysbf2\r\n```\r\n\r\n---\r\n## \u003ca name=\"reading\"\u003eReading (Streaming)\u003c/a\u003e\r\n\r\n```\r\nclass pysbf2.SBFreader.SBFReader(stream, *args, **kwargs)\r\n```\r\n\r\nYou can create a `SBFReader` object by calling the constructor with an active stream object. \r\nThe stream object can be any viable data stream which supports a `read(n) -\u003e bytes` method (e.g. File or Serial, with \r\nor 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).\r\n\r\nIndividual 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.\r\n\r\nThe constructor accepts the following optional keyword arguments:\r\n\r\n* `protfilter`: `NMEA_PROTOCOL` (1), `SBF_PROTOCOL` (2), `RTCM3_PROTOCOL` (4). Can be OR'd; default is `NMEA_PROTOCOL | SBF_PROTOCOL | RTCM3_PROTOCOL` (7)\r\n* `quitonerror`: `ERR_IGNORE` (0) = ignore errors, `ERR_LOG` (1) = log errors and continue (default), `ERR_RAISE` (2) = (re)raise errors and terminate\r\n* `validate`: `VALCKSUM` (0x01) = validate checksum (default), `VALNONE` (0x00) = ignore invalid checksum or length\r\n* `parsebitfield`: 1 = parse bitfields ('X' type properties) as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences\r\n\r\nExample -  Serial input. This example will output both SBF and NMEA messages but not RTCM3:\r\n```python\r\nfrom serial import Serial\r\nfrom pysbf2 import SBFReader, NMEA_PROTOCOL, SBF_PROTOCOL\r\nwith Serial('/dev/ttyACM0', 115200, timeout=3) as stream:\r\n  ubr = SBFReader(stream, protfilter=NMEA_PROTOCOL | SBF_PROTOCOL)\r\n  raw_data, parsed_data = ubr.read()\r\n  if parsed_data is not None:\r\n    print(parsed_data)\r\n```\r\n\r\nExample - File input (using iterator). This will only output SBF data:\r\n```python\r\nfrom pysbf2 import SBFReader, SBF_PROTOCOL\r\nwith open('SBFdata.bin', 'rb') as stream:\r\n  ubr = SBFReader(stream, protfilter=SBF_PROTOCOL)\r\n  for raw_data, parsed_data in ubr:\r\n    print(parsed_data)\r\n```\r\n\r\nExample - Socket input (using iterator). This will output SBF, NMEA and RTCM3 data:\r\n```python\r\nimport socket\r\nfrom pysbf2 import SBFReader, NMEA_PROTOCOL, SBF_PROTOCOL, RTCM3_PROTOCOL\r\nwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as stream:\r\n  stream.connect((\"localhost\", 50007))\r\n  ubr = SBFReader(stream, protfilter=NMEA_PROTOCOL | SBF_PROTOCOL | RTCM3_PROTOCOL)\r\n  for raw_data, parsed_data in ubr:\r\n    print(parsed_data)\r\n```\r\n\r\n---\r\n## \u003ca name=\"parsing\"\u003eParsing\u003c/a\u003e\r\n\r\nYou 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.\r\n\r\n**NB:** Once instantiated, a `SBFMessage` object is immutable.\r\n\r\nThe `parse()` method accepts the following optional keyword arguments:\r\n\r\n* `validate`: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length\r\n* `parsebitfield`: 1 = parse bitfields ('X' type properties) as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences\r\n\r\nExample - output (GET) message:\r\n```python\r\nfrom pysbf2 import SBFReader\r\nmsg = 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\u003e\\x00\\x00\\x10\\x00\\x8f\\x02\\x8f\\x02\\r\\t2P\\x01\\x00\\x00\\x00+\\x00z\\x00\\x88\\x00`\\x01\")\r\nprint(msg)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\n```\r\n\r\nIf `parsebitfield=False`, the message is parsed without individual bit flags, e.g.:\r\n```\r\n\u003cSBF(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'`')\u003e\r\n```\r\n\r\nThe `SBFMessage` object exposes different public attributes depending on its message type or 'identity',\r\ne.g. the `PVTCartesian` message has the following attributes:\r\n\r\n```python\r\nprint(msg)\r\nprint(msg.identity)\r\nprint(msg.X, msg.Y, msg.Z)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\nPVTCartesian\r\n3803640.1823747293, -148797.3625715144, 5100642.783697508\r\n```\r\n\r\nDecodes for various coded attributes (e.g. PVT `Type`) are provided in [`sbftypes_decodes.py`](https://github.com/semuconsulting/pysbf2/blob/main/src/pysbf2/sbftypes_decodes.py):\r\n```python\r\nfrom pysbf2 import PVT_TYPE\r\nprint(PVT_TYPE[msg.Type]) # msg.Type = 4\r\n```\r\n```\r\n\"RTK with fixed ambiguities\"\r\n```\r\n\r\nThe `payload` attribute always contains the raw payload as bytes. Attributes within repeating groups are parsed with a two-digit suffix (PRNMaskNo_01, PRNMaskNo_02, etc.).\r\n\r\n**Tip:** To iterate through a repeating group of attributes (*e.g. PRNMaskNo*), the following construct can be used:\r\n\r\n```python\r\nvals = [] # list of PRNMaskNo values from repeating group\r\nfor i in range(msg.N): # N = size of repeating group\r\n    PRNMaskNo = getattr(msg, f\"PRNMaskNo_{i+1:02d}\")\r\n    vals.append(PRNMaskNo)\r\nprint(vals)\r\n```\r\n\r\n---\r\n## \u003ca name=\"generating\"\u003eGenerating\u003c/a\u003e\r\n\r\n```\r\nclass pysbf2.SBFmessage.SBFMessage(SBFClass, msgid: int, revno: int, **kwargs)\r\n```\r\n\r\nYou can create a `SBFMessage` object by calling the constructor with the following parameters:\r\n1. message id\r\n2. revision number (optional, defaults to 0)\r\n3. (optional) a series of keyword parameters representing the message payload\r\n\r\nThe 'message class' and 'message id' parameters may be passed as lookup strings, integers or bytes.\r\n\r\nThe message payload can be defined via keyword arguments in one of three ways:\r\n1. 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.\r\n2. 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.\r\n3. If no keyword arguments are passed, the payload is assumed to be null.\r\n\r\nExample - to generate a PVTCartesian message, any of the following constructor formats will work:\r\n\r\nA. Pass entire payload as bytes:\r\n```python\r\nfrom pysbf2 import SBFMessage\r\nmsg1 = 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\u003e\\x00\\x00\\x10\\x00\\xff\\xff\\xff\\xff\\r\\t2P\\x01\\x00\\x00\\x00+\\x00\\xc4\\x04V\\x05`')\r\nprint(msg1)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\n```\r\nB. Pass individual attributes as keyword arguments:\r\n```python\r\nfrom pysbf2 import SBFMessage\r\nmsg2 = 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)\r\nprint(msg2)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\n```\r\nC. Pass selected attribute as keyword argument; the rest will be set to nominal values (in this case 0):\r\n```python\r\nfrom pysbf2 import SBFMessage\r\nmsg3 = SBFMessage(\"PVTCartesian\",TOW=208903000,WNc=2367,Mode=1,Error=0,X=3803640.1823747293,Y=-148797.3625715144,Z=5100642.783697508)\r\nprint(msg3)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\n```\r\n\r\n---\r\n## \u003ca name=\"serializing\"\u003eSerializing\u003c/a\u003e\r\n\r\nThe `SBFMessage` class implements a `serialize()` method to convert a `SBFMessage` object to a bytes array suitable for writing to an output stream.\r\n\r\ne.g. to create and send a `CFG-MSG` command which sets the NMEA GLL (*msgClass 0xf0, msgID 0x01*) message rate to 1 on the receiver's UART1 and USB ports:\r\n\r\n```python\r\nfrom serial import Serial\r\nfrom pysbf2 import SBFMessage\r\nserialOut = Serial('/dev/ttyAMA0', 115200, timeout=3)\r\nfrom pysbf2 import SBFMessage\r\nmsg = SBFMessage(\"PVTCartesian\",TOW=208903000,WNc=2367,Mode=1,Error=0,X=3803640.1823747293,Y=-148797.3625715144,Z=5100642.783697508)\r\nprint(msg)\r\noutput = msg.serialize()\r\nprint(output)\r\nserialOut.write(output)\r\n```\r\n```\r\n\u003cSBF(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)\u003e\r\nb'$@\\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'\r\n```\r\n\r\n---\r\n## \u003ca name=\"examples\"\u003eExamples\u003c/a\u003e\r\n\r\nThe following command line examples can be found in the `\\examples` folder:\r\n\r\n1. TBC\r\n\r\n---\r\n## \u003ca name=\"extensibility\"\u003eExtensibility\u003c/a\u003e\r\n\r\nThe SBF protocol is principally defined in the modules `sbftypes_*.py` as a series of dictionaries. Message payload definitions must conform to the following rules:\r\n\r\n```\r\n1. attribute names must be unique within each message class\r\n2. attribute types must be one of the valid types (I1, U2, X4, etc.)\r\n3. 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]}\r\n4. repeating or bitfield groups must be defined as a tuple ('numr', {dict}), where:\r\n   'numr' is either:\r\n     a. an integer representing a fixed number of repeats e.g. 32\r\n     b. a string representing the name of a preceding attribute containing the number of repeats e.g. 'numCh'\r\n     c. an 'X' attribute type ('X1', 'X2', 'X4', etc) representing a group of individual bit flags\r\n   {dict} is the nested dictionary of repeating items or bitfield group\r\n```\r\n\r\nRepeating attribute names are parsed with a two-digit suffix (PRNMaskNo_01, PRNMaskNo_02, etc.). Nested repeating groups are supported. See \"MeasEpoch\" way of example.\r\n\r\nAn 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.\r\n\r\n---\r\n## \u003ca name=\"knownissues\"\u003eKnown Issues\u003c/a\u003e\r\n\r\n1. The following SBF message types are not yet implemented (mainly because definitions are not currently in the public domain or are unresolved):\r\n    1. Meas3CN0HiRes\r\n    1. Meas3Doppler\r\n    1. Meas3MP\r\n    1. Meas3PP\r\n    1. Meas3Ranges\r\n    1. PVTSupport\r\n    1. PVTSupportA\r\n    1. FugroDDS\r\n\r\n---\r\n## \u003ca name=\"author\"\u003eAuthor \u0026 License Information\u003c/a\u003e\r\n\r\nsemuadmin@semuconsulting.com\r\n\r\n![GitHub License](https://img.shields.io/github/license/semuconsulting/pysbf2)\r\n\r\n`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...\r\n\r\n[![Sponsor](https://github.com/semuconsulting/pyubx2/blob/master/images/sponsor.png?raw=true)](https://buymeacoffee.com/semuconsulting)\r\n\r\n[![Freedom for Ukraine](https://github.com/semuadmin/sandpit/blob/main/src/sandpit/resources/ukraine200.jpg?raw=true)](https://u24.gov.ua/)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemuconsulting%2Fpysbf2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsemuconsulting%2Fpysbf2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemuconsulting%2Fpysbf2/lists"}