pygnssutils 1.2.2__tar.gz → 1.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pygnssutils-1.2.2/src/pygnssutils.egg-info → pygnssutils-1.2.4}/PKG-INFO +8 -10
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/README.md +4 -6
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/pyproject.toml +3 -3
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/_version.py +1 -1
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/globals.py +1 -1
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rawnav.py +150 -72
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_conv.py +23 -2
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_conv_cli.py +36 -1
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_conv_met.py +2 -2
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_conv_nav.py +265 -138
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_conv_obs.py +15 -10
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_globals.py +19 -12
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_helpers.py +96 -34
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_subframes_bds.py +18 -12
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_subframes_gal.py +4 -3
- pygnssutils-1.2.4/src/pygnssutils/rinex_subframes_glo.py +136 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/rinex_subframes_gps.py +11 -8
- {pygnssutils-1.2.2 → pygnssutils-1.2.4/src/pygnssutils.egg-info}/PKG-INFO +8 -10
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils.egg-info/SOURCES.txt +2 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils.egg-info/requires.txt +3 -3
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_rinex.py +82 -41
- pygnssutils-1.2.4/tests/test_rinex_defs.py +148 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/LICENSE +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/setup.cfg +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/__init__.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/exceptions.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssmqttclient.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssmqttclient_cli.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssntripclient.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssntripclient_cli.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssreader.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssserver.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssserver_cli.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssstreamer.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/gnssstreamer_cli.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/helpers.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/mqttmessage.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils/socket_server.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils.egg-info/dependency_links.txt +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils.egg-info/entry_points.txt +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/src/pygnssutils.egg-info/top_level.txt +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_cli.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_gnssstreamer.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_rawnav.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_socketwrapper.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_sourcetable.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_static.py +0 -0
- {pygnssutils-1.2.2 → pygnssutils-1.2.4}/tests/test_stream.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pygnssutils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: GNSS Command Line Utilities
|
|
5
5
|
Author-email: Steve Smith <semuadmin@semuconsulting.com>
|
|
6
6
|
Maintainer-email: Steve Smith <semuadmin@semuconsulting.com>
|
|
@@ -34,11 +34,11 @@ Requires-Dist: certifi>=2025.0.0
|
|
|
34
34
|
Requires-Dist: paho-mqtt>=2.1.0
|
|
35
35
|
Requires-Dist: pyserial>=3.5
|
|
36
36
|
Requires-Dist: pyspartn>=1.0.8
|
|
37
|
-
Requires-Dist: pyubx2>=1.3.
|
|
38
|
-
Requires-Dist: pynmeagps>=1.1.
|
|
37
|
+
Requires-Dist: pyubx2>=1.3.3
|
|
38
|
+
Requires-Dist: pynmeagps>=1.1.5
|
|
39
39
|
Requires-Dist: pysbf2>=1.0.4
|
|
40
40
|
Requires-Dist: pyubxutils>=1.0.6
|
|
41
|
-
Requires-Dist: pyqgc>=0.
|
|
41
|
+
Requires-Dist: pyqgc>=1.0.0
|
|
42
42
|
Requires-Dist: pyunigps>=1.0.0
|
|
43
43
|
Dynamic: license-file
|
|
44
44
|
|
|
@@ -81,7 +81,7 @@ designated output stream.
|
|
|
81
81
|
a simple SPARTN IP (MQTT) Client which receives SPARTN correction data from an SPARTN IP location service and (optionally) sends this to a
|
|
82
82
|
designated output stream.
|
|
83
83
|
1. `SocketServer` class based on the native Python `ThreadingTCPServer`. Capable of operating in two modes - Socket Server or NTRIP Caster. Provides two alternate client request handler classes - `ClientHandler` (HTTP) or `ClientHandlerTLS` (HTTPS).
|
|
84
|
-
1. `RinexConverter` class and its associated [`pyrinexconv`](#rinexconvert) CLI utility. This implements a binary GNSS data log file to RINEX text file conversion facility. **NB:
|
|
84
|
+
1. `RinexConverter` class and its associated [`pyrinexconv`](#rinexconvert) CLI utility. This implements a binary GNSS data log file to RINEX text file conversion facility. **NB: RINEX conversion is currently an experimental work in progress (*contributions and feedback welcome*)**
|
|
85
85
|
|
|
86
86
|
The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnssutils](https://github.com/semuconsulting/pygnssutils).
|
|
87
87
|
|
|
@@ -543,17 +543,15 @@ class pygnssutils.rinex_conv.RinexConvertor(app, rinex_version, rinex_type, gnss
|
|
|
543
543
|
|
|
544
544
|
A command line utility and Python class `RinexConverter` to convert binary GNSS data logs to RINEX text file format.
|
|
545
545
|
|
|
546
|
-
**NB:
|
|
546
|
+
**NB: RINEX conversion is an experimental work in progress (*contributions and feedback welcome*). The current ALPHA release implements the following functionality:**
|
|
547
547
|
|
|
548
548
|
1. RINEX versions 3.05 and 4.02.
|
|
549
549
|
1. Convert binary UBX RXM-RAW or RXM-RAWX (raw observation) data from u-blox receivers (e.g. ZED-F9P) to RINEX Observation file format.
|
|
550
|
-
1. Convert binary RXM-SFRBX (navigation subframe) data from u-blox receivers to RINEX Navigation file format. **Currently supports GPS LNAV
|
|
550
|
+
1. Convert binary RXM-SFRBX (navigation subframe) data from u-blox receivers to RINEX Navigation file format. **Currently supports GPS LNAV/CNAV, GAL FNAV/INAV, BDS D1/D2 & GLO L1OF**, but the underlying `RinexConverterNavigation` class will be enhanced in future releases.
|
|
551
551
|
1. Convert RTCM3 Ephemerides messages (1019, 1020, 1041-1046) from any source (including NTRIP caster or RTK base station receiver) to RINEX Navigation file format.
|
|
552
552
|
1. Convert NMEA MWD (wind speed and direction) and XDR (temperature and pressure) sensor data to RINEX Meteorology file format.
|
|
553
553
|
|
|
554
|
-
A Graphical User Interface for this utility
|
|
555
|
-
|
|
556
|
-
The intention behind this preview release is to **gauge the wider appetite for further development** of a cross-platform Python RINEX conversion utility and enhance functionality in a future release, as and when time permits. **CONTRIBUTORS WELCOME**.
|
|
554
|
+
A Graphical User Interface for this utility has been added to [PyGPSClient](https://github.com/semuconsulting/PyGPSClient).
|
|
557
555
|
|
|
558
556
|
Assuming the u-blox receiver is already configured to output raw observation (UBX-RXM-RAWX) and navigation subframe (UBX-RXM-SFRBX) data, a suitable input log file can be created using the pygnssutils `gnssstreamer` CLI utility e.g. ...
|
|
559
557
|
|
|
@@ -37,7 +37,7 @@ designated output stream.
|
|
|
37
37
|
a simple SPARTN IP (MQTT) Client which receives SPARTN correction data from an SPARTN IP location service and (optionally) sends this to a
|
|
38
38
|
designated output stream.
|
|
39
39
|
1. `SocketServer` class based on the native Python `ThreadingTCPServer`. Capable of operating in two modes - Socket Server or NTRIP Caster. Provides two alternate client request handler classes - `ClientHandler` (HTTP) or `ClientHandlerTLS` (HTTPS).
|
|
40
|
-
1. `RinexConverter` class and its associated [`pyrinexconv`](#rinexconvert) CLI utility. This implements a binary GNSS data log file to RINEX text file conversion facility. **NB:
|
|
40
|
+
1. `RinexConverter` class and its associated [`pyrinexconv`](#rinexconvert) CLI utility. This implements a binary GNSS data log file to RINEX text file conversion facility. **NB: RINEX conversion is currently an experimental work in progress (*contributions and feedback welcome*)**
|
|
41
41
|
|
|
42
42
|
The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnssutils](https://github.com/semuconsulting/pygnssutils).
|
|
43
43
|
|
|
@@ -499,17 +499,15 @@ class pygnssutils.rinex_conv.RinexConvertor(app, rinex_version, rinex_type, gnss
|
|
|
499
499
|
|
|
500
500
|
A command line utility and Python class `RinexConverter` to convert binary GNSS data logs to RINEX text file format.
|
|
501
501
|
|
|
502
|
-
**NB:
|
|
502
|
+
**NB: RINEX conversion is an experimental work in progress (*contributions and feedback welcome*). The current ALPHA release implements the following functionality:**
|
|
503
503
|
|
|
504
504
|
1. RINEX versions 3.05 and 4.02.
|
|
505
505
|
1. Convert binary UBX RXM-RAW or RXM-RAWX (raw observation) data from u-blox receivers (e.g. ZED-F9P) to RINEX Observation file format.
|
|
506
|
-
1. Convert binary RXM-SFRBX (navigation subframe) data from u-blox receivers to RINEX Navigation file format. **Currently supports GPS LNAV
|
|
506
|
+
1. Convert binary RXM-SFRBX (navigation subframe) data from u-blox receivers to RINEX Navigation file format. **Currently supports GPS LNAV/CNAV, GAL FNAV/INAV, BDS D1/D2 & GLO L1OF**, but the underlying `RinexConverterNavigation` class will be enhanced in future releases.
|
|
507
507
|
1. Convert RTCM3 Ephemerides messages (1019, 1020, 1041-1046) from any source (including NTRIP caster or RTK base station receiver) to RINEX Navigation file format.
|
|
508
508
|
1. Convert NMEA MWD (wind speed and direction) and XDR (temperature and pressure) sensor data to RINEX Meteorology file format.
|
|
509
509
|
|
|
510
|
-
A Graphical User Interface for this utility
|
|
511
|
-
|
|
512
|
-
The intention behind this preview release is to **gauge the wider appetite for further development** of a cross-platform Python RINEX conversion utility and enhance functionality in a future release, as and when time permits. **CONTRIBUTORS WELCOME**.
|
|
510
|
+
A Graphical User Interface for this utility has been added to [PyGPSClient](https://github.com/semuconsulting/PyGPSClient).
|
|
513
511
|
|
|
514
512
|
Assuming the u-blox receiver is already configured to output raw observation (UBX-RXM-RAWX) and navigation subframe (UBX-RXM-SFRBX) data, a suitable input log file can be created using the pygnssutils `gnssstreamer` CLI utility e.g. ...
|
|
515
513
|
|
|
@@ -38,11 +38,11 @@ dependencies = [
|
|
|
38
38
|
"paho-mqtt>=2.1.0",
|
|
39
39
|
"pyserial>=3.5",
|
|
40
40
|
"pyspartn>=1.0.8",
|
|
41
|
-
"pyubx2>=1.3.
|
|
42
|
-
"pynmeagps>=1.1.
|
|
41
|
+
"pyubx2>=1.3.3",
|
|
42
|
+
"pynmeagps>=1.1.5",
|
|
43
43
|
"pysbf2>=1.0.4",
|
|
44
44
|
"pyubxutils>=1.0.6",
|
|
45
|
-
"pyqgc>=0.
|
|
45
|
+
"pyqgc>=1.0.0",
|
|
46
46
|
"pyunigps>=1.0.0",
|
|
47
47
|
]
|
|
48
48
|
|
|
@@ -121,7 +121,7 @@ LOGLIMIT = 10485760 # max size of logfile in bytes
|
|
|
121
121
|
NOGGA = -1
|
|
122
122
|
"""No GGA sentence to be sent (for NTRIP caster)"""
|
|
123
123
|
EPILOG = (
|
|
124
|
-
"© 2022 semuadmin (Steve Smith) BSD 3-Clause license"
|
|
124
|
+
"© 2022-2026 semuadmin (Steve Smith) BSD 3-Clause license"
|
|
125
125
|
" - https://github.com/semuconsulting/pygnssutils/"
|
|
126
126
|
)
|
|
127
127
|
"""CLI argument parser epilog"""
|
|
@@ -47,11 +47,11 @@ navigation data:
|
|
|
47
47
|
|
|
48
48
|
https://www.u-blox.com/sites/default/files/ZED-F9P_IntegrationManual_UBX-18010802.pdf
|
|
49
49
|
|
|
50
|
-
NB: Alpha
|
|
50
|
+
NB: Alpha release currently implements:
|
|
51
51
|
- GPS LNAV, CNAV
|
|
52
52
|
- GAL FNAV, INAV
|
|
53
|
-
- BDS D1
|
|
54
|
-
|
|
53
|
+
- BDS D1, D2
|
|
54
|
+
- GLO L1OF
|
|
55
55
|
|
|
56
56
|
Created on 20 Apr 2026
|
|
57
57
|
|
|
@@ -60,7 +60,7 @@ Created on 20 Apr 2026
|
|
|
60
60
|
:license: BSD 3-Clause
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
|
-
# pylint: disable=
|
|
63
|
+
# pylint: disable=unused-argument, unused-variable, too-many-arguments, too-many-positional-arguments
|
|
64
64
|
|
|
65
65
|
import struct
|
|
66
66
|
from logging import getLogger
|
|
@@ -79,8 +79,8 @@ from pygnssutils.rinex_globals import (
|
|
|
79
79
|
QZS,
|
|
80
80
|
SBA,
|
|
81
81
|
UBXRINEXGNSS,
|
|
82
|
-
UBXRINEXOBSCODE,
|
|
83
82
|
)
|
|
83
|
+
from pygnssutils.rinex_helpers import get_obscode_ubx
|
|
84
84
|
|
|
85
85
|
IS1 = "_is1"
|
|
86
86
|
"""IS1 field name suffix (between MSB and ISB)"""
|
|
@@ -120,7 +120,7 @@ class RawNav:
|
|
|
120
120
|
self,
|
|
121
121
|
gnss: Literal["G", "R", "E", "C", "J", "S", "I"],
|
|
122
122
|
svid: int,
|
|
123
|
-
|
|
123
|
+
sigcode: str,
|
|
124
124
|
**kwargs, # pylint: disable=unused-argument
|
|
125
125
|
):
|
|
126
126
|
"""
|
|
@@ -128,17 +128,18 @@ class RawNav:
|
|
|
128
128
|
|
|
129
129
|
:param Literal["G","R","E","C","J","S","I"] gnss: GNSS code
|
|
130
130
|
:param int svid: RINEX SV id e.g. 14
|
|
131
|
-
:param str
|
|
131
|
+
:param str sigcode: RINEX signal code e.g. "1C"
|
|
132
132
|
:param dict kwargs: optional keyword arguments
|
|
133
133
|
"""
|
|
134
134
|
|
|
135
135
|
self._logger = getLogger(__name__)
|
|
136
136
|
self._gnss = gnss
|
|
137
137
|
self._svid = svid
|
|
138
|
-
self.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
self._sigcode = sigcode
|
|
139
|
+
if gnss != "R":
|
|
140
|
+
self.wn = -1
|
|
141
|
+
self.toc = -1
|
|
142
|
+
self.tow = -1
|
|
142
143
|
self._subframeacq = 0
|
|
143
144
|
self._msb = {}
|
|
144
145
|
self._isb = {}
|
|
@@ -290,7 +291,7 @@ class RawNav:
|
|
|
290
291
|
|
|
291
292
|
stg = (
|
|
292
293
|
f"<RAWNAV({self.identity}, gnss={self._gnss}, svid={self._svid}, "
|
|
293
|
-
f"sigid={self.
|
|
294
|
+
f"sigid={self._sigcode}, sfracq={self._subframeacq}, "
|
|
294
295
|
)
|
|
295
296
|
for i, att in enumerate(self.__dict__):
|
|
296
297
|
if att[0] != "_": # only show public attributes
|
|
@@ -310,7 +311,7 @@ class RawNav:
|
|
|
310
311
|
:rtype: str
|
|
311
312
|
"""
|
|
312
313
|
|
|
313
|
-
return f"{self._gnss}{self._svid:02d}{self.
|
|
314
|
+
return f"{self._gnss}{self._svid:02d}{self._sigcode}"
|
|
314
315
|
|
|
315
316
|
@property
|
|
316
317
|
def gnss(self) -> str:
|
|
@@ -343,18 +344,18 @@ class RawNav:
|
|
|
343
344
|
:rtype: str
|
|
344
345
|
"""
|
|
345
346
|
|
|
346
|
-
return f"{self._gnss}{self._svid
|
|
347
|
+
return f"{self._gnss}{self._svid:>2}" # no leading zero
|
|
347
348
|
|
|
348
349
|
@property
|
|
349
|
-
def
|
|
350
|
+
def sigcode(self) -> str:
|
|
350
351
|
"""
|
|
351
|
-
Getter for signal
|
|
352
|
+
Getter for signal code in RINEX format.
|
|
352
353
|
|
|
353
|
-
:return: signal
|
|
354
|
+
:return: signal code e.g. '1C'
|
|
354
355
|
:rtype: str
|
|
355
356
|
"""
|
|
356
357
|
|
|
357
|
-
return self.
|
|
358
|
+
return self._sigcode
|
|
358
359
|
|
|
359
360
|
@property
|
|
360
361
|
def subframeacq(self) -> int:
|
|
@@ -411,37 +412,37 @@ class RawNavReader:
|
|
|
411
412
|
gnss = UBXRINEXGNSS[data.gnssId]
|
|
412
413
|
svid = data.svId
|
|
413
414
|
numw = data.numWords
|
|
414
|
-
|
|
415
|
+
sigcode = get_obscode_ubx(data.gnssId, data.sigId)
|
|
415
416
|
except KeyError as err:
|
|
416
417
|
raise RINEXProcessingError(
|
|
417
418
|
f"Unrecognised GNSS or Signal code: {data.gnssId=}, {data.sigId=}"
|
|
418
419
|
) from err
|
|
419
420
|
|
|
420
421
|
if gnss == GPS:
|
|
421
|
-
sfrdata = self._process_rxm_sfrbx_gps(gnss, svid,
|
|
422
|
+
sfrdata = self._process_rxm_sfrbx_gps(gnss, svid, sigcode, numw, data)
|
|
422
423
|
elif gnss == GAL:
|
|
423
|
-
sfrdata = self._process_rxm_sfrbx_gal(gnss, svid,
|
|
424
|
+
sfrdata = self._process_rxm_sfrbx_gal(gnss, svid, sigcode, numw, data)
|
|
424
425
|
elif gnss == BDS:
|
|
425
|
-
sfrdata = self._process_rxm_sfrbx_bds(gnss, svid,
|
|
426
|
+
sfrdata = self._process_rxm_sfrbx_bds(gnss, svid, sigcode, numw, data)
|
|
426
427
|
elif gnss == GLO:
|
|
427
|
-
sfrdata = self._process_rxm_sfrbx_glo(gnss, svid,
|
|
428
|
+
sfrdata = self._process_rxm_sfrbx_glo(gnss, svid, sigcode, numw, data)
|
|
428
429
|
elif gnss == SBA:
|
|
429
|
-
sfrdata = self._process_rxm_sfrbx_sba(gnss, svid,
|
|
430
|
+
sfrdata = self._process_rxm_sfrbx_sba(gnss, svid, sigcode, numw, data)
|
|
430
431
|
elif gnss == QZS:
|
|
431
|
-
sfrdata = self._process_rxm_sfrbx_qzs(gnss, svid,
|
|
432
|
+
sfrdata = self._process_rxm_sfrbx_qzs(gnss, svid, sigcode, numw, data)
|
|
432
433
|
elif gnss == IRN:
|
|
433
|
-
sfrdata = self._process_rxm_sfrbx_irn(gnss, svid,
|
|
434
|
+
sfrdata = self._process_rxm_sfrbx_irn(gnss, svid, sigcode, numw, data)
|
|
434
435
|
return sfrdata
|
|
435
436
|
|
|
436
437
|
def _process_rxm_sfrbx_gps(
|
|
437
|
-
self, gnss: str, svid: int,
|
|
438
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
438
439
|
) -> dict[str, str | int | float | NoneType]:
|
|
439
440
|
"""
|
|
440
441
|
Reassemble GPS subframe from individual UBX RXM-SFRBX dwrds.
|
|
441
442
|
|
|
442
443
|
:param str gnss: RINEX gnss code
|
|
443
444
|
:param int svid: SV
|
|
444
|
-
:param str
|
|
445
|
+
:param str sigcode: RINEX sig code e.g. '1C'
|
|
445
446
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
446
447
|
:return: dict of subframe attributes
|
|
447
448
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -450,21 +451,19 @@ class RawNavReader:
|
|
|
450
451
|
|
|
451
452
|
subframe = 0
|
|
452
453
|
subframeid = 0
|
|
453
|
-
# dataid = 0
|
|
454
454
|
subframepageid = 0
|
|
455
455
|
|
|
456
456
|
# for GPS LNAV, subframe = 10 * 30 bits, with each 32-bit dwrd padded with 2 bits at end
|
|
457
|
-
if
|
|
457
|
+
if sigcode == "1C": # GPS LNAV
|
|
458
458
|
for i in range(numw):
|
|
459
459
|
wrd = getattr(data, f"dwrd_{i+1:02d}") & 0xFFFFFFFC >> 2
|
|
460
460
|
subframe += wrd << (30 * (numw - 1 - i))
|
|
461
461
|
subframeid = (subframe >> 248) & 0b111
|
|
462
|
-
# dataid = subframe >> 234 & 0b11
|
|
463
462
|
if subframeid in (4, 5):
|
|
464
463
|
subframepageid = subframe >> 232 & 0b111111
|
|
465
464
|
|
|
466
465
|
# for GPS CNAV, subframe = 3 * 100 bits, final 20 bits of 320 bit dwrd is padding
|
|
467
|
-
elif
|
|
466
|
+
elif sigcode in ("2L", "2S", "5I", "5Q"): # GPS CNAV
|
|
468
467
|
for i in range(numw):
|
|
469
468
|
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
470
469
|
subframe += wrd << (32 * (numw - 1 - i))
|
|
@@ -477,22 +476,21 @@ class RawNavReader:
|
|
|
477
476
|
return {
|
|
478
477
|
"gnss": gnss,
|
|
479
478
|
"svid": svid,
|
|
480
|
-
"
|
|
481
|
-
# "dataid": dataid,
|
|
479
|
+
"sigcode": sigcode,
|
|
482
480
|
"subframeid": subframeid,
|
|
483
481
|
"subframepageid": subframepageid,
|
|
484
482
|
"subframe": subframe,
|
|
485
483
|
}
|
|
486
484
|
|
|
487
485
|
def _process_rxm_sfrbx_gal(
|
|
488
|
-
self, gnss: str, svid: int,
|
|
486
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
489
487
|
) -> dict[str, str | int | float | NoneType]:
|
|
490
488
|
"""
|
|
491
489
|
Reassemble GALILEO subframe from individual UBX RXM-SFRBX dwrds.
|
|
492
490
|
|
|
493
491
|
:param str gnss: RINEX gnss code
|
|
494
492
|
:param int svid: SV
|
|
495
|
-
:param str
|
|
493
|
+
:param str sigcode: RINEX sigid e.g. '5I'
|
|
496
494
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
497
495
|
:return: dict of subframe attributes
|
|
498
496
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -505,7 +503,7 @@ class RawNavReader:
|
|
|
505
503
|
|
|
506
504
|
# for GAL FNAV, subframe = 244 bits,
|
|
507
505
|
# 8 * 32 bit dwrds with 12 bits padding at end
|
|
508
|
-
if
|
|
506
|
+
if sigcode == "5I": # GAL FNAV
|
|
509
507
|
for i in range(numw):
|
|
510
508
|
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
511
509
|
subframe += wrd << (32 * (numw - 1 - i))
|
|
@@ -517,7 +515,7 @@ class RawNavReader:
|
|
|
517
515
|
# for GAL INAV, subframe = 256 bits, 8 * 32 bit dwrds,
|
|
518
516
|
# with word data separated into 112 msb and 16 lsb
|
|
519
517
|
# (see GAL_INAV_SUBFRAME)
|
|
520
|
-
elif
|
|
518
|
+
elif sigcode in ("1B", "7I"): # GAL INAV
|
|
521
519
|
supsubframe = 0
|
|
522
520
|
for i in range(numw):
|
|
523
521
|
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
@@ -532,21 +530,21 @@ class RawNavReader:
|
|
|
532
530
|
return {
|
|
533
531
|
"gnss": gnss,
|
|
534
532
|
"svid": svid,
|
|
535
|
-
"
|
|
533
|
+
"sigcode": sigcode,
|
|
536
534
|
"subframeid": subframeid,
|
|
537
535
|
"subframepageid": subframepageid,
|
|
538
536
|
"subframe": subframe,
|
|
539
537
|
}
|
|
540
538
|
|
|
541
539
|
def _process_rxm_sfrbx_bds(
|
|
542
|
-
self, gnss: str, svid: int,
|
|
540
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
543
541
|
) -> dict[str, str | int | float | NoneType]:
|
|
544
542
|
"""
|
|
545
543
|
Reassemble BEIDOU subframe from individual UBX RXM-SFRBX dwrds.
|
|
546
544
|
|
|
547
545
|
:param str gnss: RINEX gnss code
|
|
548
546
|
:param int svid: SV
|
|
549
|
-
:param str
|
|
547
|
+
:param str sigcode: RINEX sig code e.g. '2I'
|
|
550
548
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
551
549
|
:return: dict of subframe attributes
|
|
552
550
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -558,7 +556,7 @@ class RawNavReader:
|
|
|
558
556
|
subframepageid = 0
|
|
559
557
|
d1d2 = 0
|
|
560
558
|
|
|
561
|
-
if
|
|
559
|
+
if sigcode in ("2I", "6I", "7I"): # BDS D1/D2
|
|
562
560
|
if data.sigId in (1, 3, 10): # D2
|
|
563
561
|
d1d2 = 2
|
|
564
562
|
else: # D1
|
|
@@ -572,16 +570,16 @@ class RawNavReader:
|
|
|
572
570
|
elif d1d2 == 2 and subframeid in (1,):
|
|
573
571
|
subframepageid = subframe >> 254 & 0b1111
|
|
574
572
|
|
|
575
|
-
elif
|
|
573
|
+
elif sigcode == "1D": # BDS CNV1
|
|
576
574
|
pass # TODO
|
|
577
575
|
|
|
578
|
-
elif
|
|
576
|
+
elif sigcode == "5D": # BDS CNV2
|
|
579
577
|
pass # TODO
|
|
580
578
|
|
|
581
579
|
return {
|
|
582
580
|
"gnss": gnss,
|
|
583
581
|
"svid": svid,
|
|
584
|
-
"
|
|
582
|
+
"sigcode": sigcode,
|
|
585
583
|
"d1d2": d1d2,
|
|
586
584
|
"subframeid": subframeid,
|
|
587
585
|
"subframepageid": subframepageid,
|
|
@@ -589,14 +587,14 @@ class RawNavReader:
|
|
|
589
587
|
}
|
|
590
588
|
|
|
591
589
|
def _process_rxm_sfrbx_glo(
|
|
592
|
-
self, gnss: str, svid: int,
|
|
590
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
593
591
|
) -> dict[str, str | int | float | NoneType]:
|
|
594
592
|
"""
|
|
595
593
|
Reassemble GLONASS subframe from individual UBX RXM-SFRBX dwrds.
|
|
596
594
|
|
|
597
595
|
:param str gnss: RINEX gnss code
|
|
598
596
|
:param int svid: SV
|
|
599
|
-
:param str
|
|
597
|
+
:param str sigcode: RINEX sigid e.g. '1C'
|
|
600
598
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
601
599
|
:return: dict of subframe attributes
|
|
602
600
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -606,35 +604,38 @@ class RawNavReader:
|
|
|
606
604
|
subframe = 0
|
|
607
605
|
subframeid = 0
|
|
608
606
|
subframepageid = 0
|
|
607
|
+
freqid = data.freqId
|
|
609
608
|
|
|
610
|
-
# for GLO, subframe = 85 bits,
|
|
611
|
-
#
|
|
612
|
-
|
|
609
|
+
# for GLO, subframe = 85 bits,
|
|
610
|
+
# 3 * 32 bit dwrds with 11 bits padding at end,
|
|
611
|
+
# plus a receiver-generated 4th dwrd containing superframe and frame ids
|
|
612
|
+
if sigcode in ("1C",): # GLO L1OF
|
|
613
613
|
for i in range(numw):
|
|
614
614
|
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
615
615
|
subframe += wrd << (32 * (numw - 1 - i))
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
616
|
+
# strip 4th dwrd, leaving 85 bit subframe
|
|
617
|
+
subframe = (subframe >> 43) & 0x1FFFFFFFFFFFFFFFFFFFFF # 2**85-1
|
|
618
|
+
subframeid = (subframe >> 80) & 0b01111
|
|
619
619
|
|
|
620
620
|
return {
|
|
621
621
|
"gnss": gnss,
|
|
622
622
|
"svid": svid,
|
|
623
|
-
"
|
|
623
|
+
"sigcode": sigcode,
|
|
624
624
|
"subframeid": subframeid,
|
|
625
625
|
"subframepageid": subframepageid,
|
|
626
626
|
"subframe": subframe,
|
|
627
|
+
"freqid": freqid,
|
|
627
628
|
}
|
|
628
629
|
|
|
629
630
|
def _process_rxm_sfrbx_sba(
|
|
630
|
-
self, gnss: str, svid: int,
|
|
631
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
631
632
|
) -> dict[str, str | int | float | NoneType]:
|
|
632
633
|
"""
|
|
633
634
|
Reassemble SBAS subframe from individual UBX RXM-SFRBX dwrds.
|
|
634
635
|
|
|
635
636
|
:param str gnss: RINEX gnss code
|
|
636
637
|
:param int svid: SV
|
|
637
|
-
:param str
|
|
638
|
+
:param str sigcode: RINEX sigcode e.g. '1C'
|
|
638
639
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
639
640
|
:return: dict of subframe attributes
|
|
640
641
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -642,22 +643,39 @@ class RawNavReader:
|
|
|
642
643
|
"""
|
|
643
644
|
|
|
644
645
|
subframe = 0
|
|
645
|
-
tow = 0
|
|
646
646
|
subframeid = 0
|
|
647
647
|
subframepageid = 0
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
648
|
+
svid -= 100 # adjust SV ID range
|
|
649
|
+
|
|
650
|
+
# for SBAS, subframe = 250 bits,
|
|
651
|
+
# 8 * 32 bit dwrds with 6 bits padding at end
|
|
652
|
+
if sigcode == "1C": # SBAS L1C/A
|
|
653
|
+
for i in range(numw):
|
|
654
|
+
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
655
|
+
subframe += wrd << (32 * (numw - 1 - i))
|
|
656
|
+
subframe = (
|
|
657
|
+
subframe >> 12
|
|
658
|
+
) & 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # (2**250 - 1)
|
|
659
|
+
subframeid = (subframe >> 236) & 0b111111
|
|
660
|
+
|
|
661
|
+
return {
|
|
662
|
+
"gnss": gnss,
|
|
663
|
+
"svid": svid,
|
|
664
|
+
"sigcode": sigcode,
|
|
665
|
+
"subframeid": subframeid,
|
|
666
|
+
"subframepageid": subframepageid,
|
|
667
|
+
"subframe": subframe,
|
|
668
|
+
}
|
|
651
669
|
|
|
652
670
|
def _process_rxm_sfrbx_qzs(
|
|
653
|
-
self, gnss: str, svid: int,
|
|
671
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
654
672
|
) -> dict[str, str | int | float | NoneType]:
|
|
655
673
|
"""
|
|
656
674
|
Reassemble QZSS subframe from individual UBX RXM-SFRBX dwrds.
|
|
657
675
|
|
|
658
676
|
:param str gnss: RINEX gnss code
|
|
659
677
|
:param int svid: SV
|
|
660
|
-
:param str
|
|
678
|
+
:param str sigcode: RINEX sigcode e.g. '1C'
|
|
661
679
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
662
680
|
:return: dict of subframe attributes
|
|
663
681
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -665,22 +683,65 @@ class RawNavReader:
|
|
|
665
683
|
"""
|
|
666
684
|
|
|
667
685
|
subframe = 0
|
|
668
|
-
tow = 0
|
|
669
686
|
subframeid = 0
|
|
670
687
|
subframepageid = 0
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
688
|
+
svid -= 192 # adjust SV ID range
|
|
689
|
+
|
|
690
|
+
# for QZSS L1C/A, subframe = 10 * 30 bits, with each 32-bit dwrd padded with 2 bits at end
|
|
691
|
+
# same as GPS LNAV
|
|
692
|
+
if sigcode == "1C": # QZSS L1C/A
|
|
693
|
+
for i in range(numw):
|
|
694
|
+
wrd = getattr(data, f"dwrd_{i+1:02d}") & 0xFFFFFFFC >> 2
|
|
695
|
+
subframe += wrd << (30 * (numw - 1 - i))
|
|
696
|
+
subframeid = (subframe >> 248) & 0b111
|
|
697
|
+
if subframeid in (4, 5):
|
|
698
|
+
subframepageid = subframe >> 232 & 0b111111
|
|
699
|
+
|
|
700
|
+
# for QZSS L1S, subframe = 250 bits, 8 * 32 bit dwrds with 6 bits padding at end
|
|
701
|
+
# same as SBAS L1C/A
|
|
702
|
+
if sigcode == "1Z": # QZSS L1S
|
|
703
|
+
for i in range(numw):
|
|
704
|
+
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
705
|
+
subframe += wrd << (32 * (numw - 1 - i))
|
|
706
|
+
subframe = (
|
|
707
|
+
subframe >> 12
|
|
708
|
+
) & 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # (2**250 - 1)
|
|
709
|
+
subframeid = (subframe >> 236) & 0b111111
|
|
710
|
+
|
|
711
|
+
# for QZSS L2C, L5I, subframe = 3 * 100 bits, final 20 bits of 320 bit dwrd is padding
|
|
712
|
+
# same as GPS CNAV
|
|
713
|
+
elif sigcode in (
|
|
714
|
+
"2L",
|
|
715
|
+
"2S",
|
|
716
|
+
"5I",
|
|
717
|
+
): # QZSS L2C, L5I
|
|
718
|
+
for i in range(numw):
|
|
719
|
+
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
720
|
+
subframe += wrd << (32 * (numw - 1 - i))
|
|
721
|
+
subframe = (
|
|
722
|
+
(subframe >> 20)
|
|
723
|
+
& 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
724
|
+
) # (2**300 - 1)
|
|
725
|
+
subframeid = (subframe >> 280) & 0b111111
|
|
726
|
+
|
|
727
|
+
return {
|
|
728
|
+
"gnss": gnss,
|
|
729
|
+
"svid": svid,
|
|
730
|
+
"sigcode": sigcode,
|
|
731
|
+
"subframeid": subframeid,
|
|
732
|
+
"subframepageid": subframepageid,
|
|
733
|
+
"subframe": subframe,
|
|
734
|
+
}
|
|
674
735
|
|
|
675
736
|
def _process_rxm_sfrbx_irn(
|
|
676
|
-
self, gnss: str, svid: int,
|
|
737
|
+
self, gnss: str, svid: int, sigcode: str, numw: int, data: UBXMessage
|
|
677
738
|
) -> dict[str, str | int | float | NoneType]:
|
|
678
739
|
"""
|
|
679
740
|
Reassemble IRNSS (NAVIC) subframe from individual UBX RXM-SFRBX dwrds.
|
|
680
741
|
|
|
681
742
|
:param str gnss: RINEX gnss code
|
|
682
743
|
:param int svid: SV
|
|
683
|
-
:param str
|
|
744
|
+
:param str sigcode: RINEX sigcode e.g. '5A'
|
|
684
745
|
:param UBXMessage data: parsed UBX RXM-SFRBX message
|
|
685
746
|
:return: dict of subframe attributes
|
|
686
747
|
:rtype: dict[str, str | int | float | NoneType]
|
|
@@ -688,9 +749,26 @@ class RawNavReader:
|
|
|
688
749
|
"""
|
|
689
750
|
|
|
690
751
|
subframe = 0
|
|
691
|
-
tow = 0
|
|
692
752
|
subframeid = 0
|
|
693
753
|
subframepageid = 0
|
|
694
|
-
|
|
695
|
-
#
|
|
696
|
-
|
|
754
|
+
|
|
755
|
+
# for IRN L5A, subframe = 3 * 100 bits, final 20 bits of 320 bit dwrd is padding
|
|
756
|
+
# same as GPS CNAV
|
|
757
|
+
if sigcode in ("5A",): # IRN L5A
|
|
758
|
+
for i in range(numw):
|
|
759
|
+
wrd = getattr(data, f"dwrd_{i+1:02d}")
|
|
760
|
+
subframe += wrd << (32 * (numw - 1 - i))
|
|
761
|
+
subframe = (
|
|
762
|
+
(subframe >> 20)
|
|
763
|
+
& 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
764
|
+
) # (2**300 - 1)
|
|
765
|
+
subframeid = (subframe >> 280) & 0b111111
|
|
766
|
+
|
|
767
|
+
return {
|
|
768
|
+
"gnss": gnss,
|
|
769
|
+
"svid": svid,
|
|
770
|
+
"sigcode": sigcode,
|
|
771
|
+
"subframeid": subframeid,
|
|
772
|
+
"subframepageid": subframepageid,
|
|
773
|
+
"subframe": subframe,
|
|
774
|
+
}
|