pygnssutils 1.2.6__tar.gz → 1.2.8__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.
Files changed (53) hide show
  1. {pygnssutils-1.2.6/src/pygnssutils.egg-info → pygnssutils-1.2.8}/PKG-INFO +19 -54
  2. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/README.md +7 -45
  3. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/pyproject.toml +12 -9
  4. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/__init__.py +0 -2
  5. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/_version.py +1 -1
  6. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssreader.py +20 -28
  7. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssstreamer_cli.py +0 -37
  8. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_globals.py +1 -1
  9. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_helpers.py +1 -1
  10. {pygnssutils-1.2.6 → pygnssutils-1.2.8/src/pygnssutils.egg-info}/PKG-INFO +19 -54
  11. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils.egg-info/SOURCES.txt +0 -3
  12. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils.egg-info/entry_points.txt +0 -1
  13. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils.egg-info/requires.txt +6 -6
  14. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_cli.py +0 -5
  15. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_static.py +0 -18
  16. pygnssutils-1.2.6/src/pygnssutils/gnssmqttclient.py +0 -481
  17. pygnssutils-1.2.6/src/pygnssutils/gnssmqttclient_cli.py +0 -262
  18. pygnssutils-1.2.6/src/pygnssutils/mqttmessage.py +0 -74
  19. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/LICENSE +0 -0
  20. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/setup.cfg +0 -0
  21. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/exceptions.py +0 -0
  22. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/globals.py +0 -0
  23. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssntripclient.py +0 -0
  24. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssntripclient_cli.py +0 -0
  25. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssserver.py +0 -0
  26. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssserver_cli.py +0 -0
  27. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/gnssstreamer.py +0 -0
  28. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/helpers.py +0 -0
  29. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav.py +0 -0
  30. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_reader.py +0 -0
  31. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_bds.py +0 -0
  32. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_gal.py +0 -0
  33. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_glo.py +0 -0
  34. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_gps.py +0 -0
  35. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_irn.py +0 -0
  36. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_qzs.py +0 -0
  37. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rawnav_subframes_sba.py +0 -0
  38. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_conv.py +0 -0
  39. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_conv_cli.py +0 -0
  40. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_conv_met.py +0 -0
  41. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_conv_nav.py +0 -0
  42. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/rinex_conv_obs.py +0 -0
  43. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils/socket_server.py +0 -0
  44. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils.egg-info/dependency_links.txt +0 -0
  45. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/src/pygnssutils.egg-info/top_level.txt +0 -0
  46. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_gnssstreamer.py +0 -0
  47. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_rawnav.py +0 -0
  48. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_rinex.py +0 -0
  49. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_rinex_defs.py +0 -0
  50. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_rinex_parse.py +0 -0
  51. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_socketwrapper.py +0 -0
  52. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_sourcetable.py +0 -0
  53. {pygnssutils-1.2.6 → pygnssutils-1.2.8}/tests/test_stream.py +0 -0
@@ -1,9 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygnssutils
3
- Version: 1.2.6
3
+ Version: 1.2.8
4
4
  Summary: GNSS Command Line Utilities
5
- Author-email: Steve Smith <semuadmin@semuconsulting.com>
6
- Maintainer-email: Steve Smith <semuadmin@semuconsulting.com>
5
+ Author: Steve Smith
6
+ Author-email: semuadmin@semuconsulting.com
7
+ Maintainer: Steve Smith
8
+ Maintainer-email: semuadmin@semuconsulting.com
7
9
  License-Expression: BSD-3-Clause
8
10
  Project-URL: homepage, https://github.com/semuconsulting/pygnssutils
9
11
  Project-URL: documentation, https://www.semuconsulting.com/pygnssutils/
@@ -24,21 +26,22 @@ Classifier: Programming Language :: Python :: 3.11
24
26
  Classifier: Programming Language :: Python :: 3.12
25
27
  Classifier: Programming Language :: Python :: 3.13
26
28
  Classifier: Programming Language :: Python :: 3.14
29
+ Classifier: Programming Language :: Python :: 3.15
27
30
  Classifier: Topic :: Utilities
28
31
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
32
  Classifier: Topic :: Scientific/Engineering :: GIS
30
33
  Requires-Python: >=3.10
31
34
  Description-Content-Type: text/markdown
32
35
  License-File: LICENSE
33
- Requires-Dist: certifi>=2025.0.0
34
- Requires-Dist: paho-mqtt>=2.1.0
36
+ Requires-Dist: certifi>=2026.0.0
37
+ Requires-Dist: pynmeagps>=1.1.7
38
+ Requires-Dist: pyqgc>=1.0.0
39
+ Requires-Dist: pyrtcm>=1.2.0
40
+ Requires-Dist: pysbf2>=1.0.4
35
41
  Requires-Dist: pyserial>=3.5
36
42
  Requires-Dist: pyspartn>=1.0.8
37
- Requires-Dist: pyubx2>=1.3.6
38
- Requires-Dist: pynmeagps>=1.1.5
39
- Requires-Dist: pysbf2>=1.0.4
43
+ Requires-Dist: pyubx2>=1.3.7
40
44
  Requires-Dist: pyubxutils>=1.0.6
41
- Requires-Dist: pyqgc>=1.0.0
42
45
  Requires-Dist: pyunigps>=1.0.0
43
46
  Dynamic: license-file
44
47
 
@@ -51,7 +54,6 @@ pygnssutils
51
54
  [gnssstreamer CLI](#gnssstreamer) |
52
55
  [gnssserver CLI](#gnssserver) |
53
56
  [gnssntripclient CLI](#gnssntripclient) |
54
- [gnssmqttclient CLI](#gnssmqttclient) |
55
57
  [socketserver](#socketserver) |
56
58
  [RINEX Conversion](#rinexconvert) |
57
59
  [RTK Demonstration](#rtkdemo) |
@@ -71,17 +73,14 @@ pygnssutils is an original series of Python GNSS utility classes and CLI tools b
71
73
 
72
74
  Originally developed in support of the [PyGPSClient](https://github.com/semuconsulting/PyGPSClient) GUI GNSS application, the utilities provided by pygnssutils can also be used in their own right:
73
75
 
74
- 1. `GNSSReader` class. This is essentially an amalgamation of the `*Reader` classes in all the subsidiary parsers listed above, allowing the user to seamlessly stream any of NMEA, UBX, SBF, UNI, QGC, RTCM3 and SPARTN message protocols concurrently from a single stream.
76
+ 1. `GNSSReader` class. This is essentially an amalgamation of the `*Reader` classes in all the subsidiary parsers listed above, allowing the user to seamlessly stream any of NMEA, UBX, SBF, UNI, QGC and RTCM3 message protocols concurrently from a single stream.
75
77
  1. `GNSSStreamer` class and its associated [`gnssstreamer`](#gnssstreamer) (*formerly `gnssdump`*) CLI utility. This is essentially a configurable bidirectional input/output wrapper around the `GNSSReader` class with flexible message formatting, filtering and output handling options for NMEA, UBX, SBF, UNI, QGC and RTCM3 protocols.
76
78
  1. `GNSSSocketServer` class and its associated [`gnssserver`](#gnssserver) CLI utility. This implements a TCP Socket Server for GNSS data streams which is also capable of being run as a simple NTRIP Server/Caster.
77
79
  1. `GNSSNTRIPClient` class and its associated [`gnssntripclient`](#gnssntripclient) CLI utility. This implements
78
80
  a simple NTRIP Client which receives RTCM3 or SPARTN correction data from an NTRIP Server and (optionally) sends this to a
79
81
  designated output stream.
80
- 1. `GNSSMQTTClient` class and its associated [`gnssmqttclient`](#gnssmqttclient) CLI utility. This implements
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
- designated output stream.
83
82
  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: RINEX conversion is currently an experimental work in progress (*contributions and feedback welcome*)**
83
+ 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 feature (*contributions and feedback welcome*)**
85
84
 
86
85
  The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnssutils](https://github.com/semuconsulting/pygnssutils).
87
86
 
@@ -97,18 +96,18 @@ The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnss
97
96
 
98
97
  Sphinx API Documentation in HTML format is available at [https://www.semuconsulting.com/pygnssutils](https://www.semuconsulting.com/pygnssutils).
99
98
 
100
- Contributions welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pygnssutils/blob/main/CONTRIBUTING.md).
99
+ Contributions _**from human beings**_ welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pygnssutils/blob/main/CONTRIBUTING.md).
101
100
 
102
101
  [Bug reports](https://github.com/semuconsulting/pygnssutils/blob/main/.github/ISSUE_TEMPLATE/bug_report.md) and [Feature requests](https://github.com/semuconsulting/pygnssutils/blob/main/.github/ISSUE_TEMPLATE/feature_request.md) - please use the templates provided. For general queries and advice, post a message to one of the [pygnssutils Discussions](https://github.com/semuconsulting/pygnssutils/discussions) channels.
103
102
 
104
- ![No Copilot](https://github.com/semuconsulting/PyGPSClient/blob/master/images/nocopilot100.png?raw=true)
103
+ ![No Copilot](https://github.com/semuconsulting/PyGPSClient/blob/main/images/nocopilot100.png?raw=true)
105
104
 
106
105
  ---
107
106
  ## <a name="installation">Installation</a>
108
107
 
109
108
  ![Python version](https://img.shields.io/pypi/pyversions/pygnssutils.svg?style=flat)
110
109
  [![PyPI version](https://img.shields.io/pypi/v/pygnssutils.svg?style=flat)](https://pypi.org/project/pygnssutils/)
111
- [![PyPI downloads](https://github.com/semuconsulting/pygpsclient/blob/master/images/clickpy_top10.svg?raw=true)](https://clickpy.clickhouse.com/dashboard/pygnssutils)
110
+ [![PyPI downloads](https://github.com/semuconsulting/pygpsclient/blob/main/images/clickpy_top10.svg?raw=true)](https://clickpy.clickhouse.com/dashboard/pygnssutils)
112
111
 
113
112
  `pygnssutils` is compatible with Python>=3.10.
114
113
 
@@ -182,7 +181,6 @@ class pygnssutils.gnssstreamer.GNSSStreamer(**kwargs)
182
181
  - 0 = none (default)
183
182
  - 1 = RTK NTRIP RTCM caster
184
183
  - 2 = RTK NTRIP SPARTN caster
185
- - 3 = RTK MQTT SPARTN source (see [gnssmqttclient](#gnssmqttclient) for MQTT client configuration details)
186
184
  - 4 = serial port
187
185
  - 5 = binary file.
188
186
 
@@ -472,41 +470,6 @@ gnssntripclient -h
472
470
 
473
471
  Refer to the [Sphinx API documentation](https://www.semuconsulting.com/pygnssutils/pygnssutils.html#module-pygnssutils.gnssntripclient) for further details.
474
472
 
475
- ---
476
- ## <a name="gnssmqttclient">GNSSMQTTClient and gnssmqttclient CLI</a>
477
- ```
478
- class pygnssutils.gnssmqttclient.GNSSMQTTClient(app=None, **kwargs)
479
- ```
480
-
481
- The `GNSSMQTTClient` class provides a basic SPARTN IP (MQTT) Client capability and forms the basis of a [`gnssmqttclient`](#gnssmqttclient) CLI utility. It receives RTK correction data from a SPARTN IP (MQTT) location service (e.g. the u-blox / Thingstream PointPerfect service) and (optionally) sends this to a designated output stream.
482
-
483
- ### CLI Usage:
484
-
485
- The `clientid` provided by the location service may be set as environment variable `MQTTCLIENTID`. If this environment variable is set and the TLS certificate (\*.crt) and key (\*.pem) files provided by the location service are placed in the user's `HOME` directory, the utility can use these as default settings and may be invoked without any arguments.
486
-
487
- Assuming the Python 3 scripts (bin) directory is in your PATH, the CLI utility may be invoked from the shell thus (press CTRL-C to terminate):
488
-
489
- ```shell
490
- gnssmqttclient --clientid yourclientid --server pp.services.u-blox.com --port 8883 --region eu --mode 0 --topic_ip 1 --topic_mga 1 --topic_key 1 --tlscrt '/Users/{your-user}/device-{your-clientid}-pp-cert.crt' --tlskey '/Users/{your-user}/device-{your-client-id}-pp-key.pem'} --spartndecode 0 --clioutput 0 --verbosity 2
491
- ```
492
- ```
493
- 2024-08-15 09:14:50.544 - INFO - pygnssutils.gnssmqttclient - Starting MQTT client with arguments {'server': 'pp.services.u-blox.com', 'port': 8883, 'clientid': 'your-client-id', 'region': 'eu', 'mode': 0, 'topic_ip': 1, 'topic_mga': 1, 'topic_key': 1, 'tlscrt': '/Users/myuser/device-your-client-id-pp-cert.crt', 'tlskey': '/Users/myuser/device-your-client-id-pp-key.pem', 'spartndecode': 0, 'output': None}.
494
- 2024-08-15 09:14:50.840 - INFO - pygnssutils.gnssmqttclient - RXM-SPARTN-KEY
495
- 2024-08-15 09:14:50.854 - INFO - pygnssutils.gnssmqttclient - MGA-INI-TIME-UTC
496
- 2024-08-15 09:14:50.858 - INFO - pygnssutils.gnssmqttclient - MGA-GPS-EPH
497
- ...
498
- ```
499
-
500
- Command line arguments can be stored in a configuration file and invoked using the `-C` or `--config` argument. The location of the configuration file can be set in environment variable `GNSSMQTTCLIENT_CONF`.
501
-
502
- For help and full list of optional arguments, type:
503
-
504
- ```shell
505
- gnssmqttclient -h
506
- ```
507
-
508
- Refer to the [pyspartn documentation](https://github.com/semuconsulting/pyspartn?tab=readme-ov-file#reading) for further details on decrypting encrypted (`eaf=1`) SPARTN payloads.
509
-
510
473
  ---
511
474
  ## <a name="socketserver">SocketServer</a>
512
475
 
@@ -671,6 +634,8 @@ semuadmin@semuconsulting.com
671
634
 
672
635
  ![License](https://img.shields.io/github/license/semuconsulting/pygnssutils.svg)
673
636
 
637
+ [![ORCID iD icon](https://orcid.org/sites/default/files/images/orcid_16x16.png) https://orcid.org/0009-0002-5751-8719](https://orcid.org/0009-0002-5751-8719)
638
+
674
639
  `pygnssutils` 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...
675
640
 
676
641
  [![Sponsor](https://github.com/semuconsulting/pyubx2/blob/master/images/sponsor.png?raw=true)](https://buymeacoffee.com/semuconsulting)
@@ -7,7 +7,6 @@ pygnssutils
7
7
  [gnssstreamer CLI](#gnssstreamer) |
8
8
  [gnssserver CLI](#gnssserver) |
9
9
  [gnssntripclient CLI](#gnssntripclient) |
10
- [gnssmqttclient CLI](#gnssmqttclient) |
11
10
  [socketserver](#socketserver) |
12
11
  [RINEX Conversion](#rinexconvert) |
13
12
  [RTK Demonstration](#rtkdemo) |
@@ -27,17 +26,14 @@ pygnssutils is an original series of Python GNSS utility classes and CLI tools b
27
26
 
28
27
  Originally developed in support of the [PyGPSClient](https://github.com/semuconsulting/PyGPSClient) GUI GNSS application, the utilities provided by pygnssutils can also be used in their own right:
29
28
 
30
- 1. `GNSSReader` class. This is essentially an amalgamation of the `*Reader` classes in all the subsidiary parsers listed above, allowing the user to seamlessly stream any of NMEA, UBX, SBF, UNI, QGC, RTCM3 and SPARTN message protocols concurrently from a single stream.
29
+ 1. `GNSSReader` class. This is essentially an amalgamation of the `*Reader` classes in all the subsidiary parsers listed above, allowing the user to seamlessly stream any of NMEA, UBX, SBF, UNI, QGC and RTCM3 message protocols concurrently from a single stream.
31
30
  1. `GNSSStreamer` class and its associated [`gnssstreamer`](#gnssstreamer) (*formerly `gnssdump`*) CLI utility. This is essentially a configurable bidirectional input/output wrapper around the `GNSSReader` class with flexible message formatting, filtering and output handling options for NMEA, UBX, SBF, UNI, QGC and RTCM3 protocols.
32
31
  1. `GNSSSocketServer` class and its associated [`gnssserver`](#gnssserver) CLI utility. This implements a TCP Socket Server for GNSS data streams which is also capable of being run as a simple NTRIP Server/Caster.
33
32
  1. `GNSSNTRIPClient` class and its associated [`gnssntripclient`](#gnssntripclient) CLI utility. This implements
34
33
  a simple NTRIP Client which receives RTCM3 or SPARTN correction data from an NTRIP Server and (optionally) sends this to a
35
34
  designated output stream.
36
- 1. `GNSSMQTTClient` class and its associated [`gnssmqttclient`](#gnssmqttclient) CLI utility. This implements
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
- designated output stream.
39
35
  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: RINEX conversion is currently an experimental work in progress (*contributions and feedback welcome*)**
36
+ 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 feature (*contributions and feedback welcome*)**
41
37
 
42
38
  The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnssutils](https://github.com/semuconsulting/pygnssutils).
43
39
 
@@ -53,18 +49,18 @@ The pygnssutils homepage is located at [https://github.com/semuconsulting/pygnss
53
49
 
54
50
  Sphinx API Documentation in HTML format is available at [https://www.semuconsulting.com/pygnssutils](https://www.semuconsulting.com/pygnssutils).
55
51
 
56
- Contributions welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pygnssutils/blob/main/CONTRIBUTING.md).
52
+ Contributions _**from human beings**_ welcome - please refer to [CONTRIBUTING.MD](https://github.com/semuconsulting/pygnssutils/blob/main/CONTRIBUTING.md).
57
53
 
58
54
  [Bug reports](https://github.com/semuconsulting/pygnssutils/blob/main/.github/ISSUE_TEMPLATE/bug_report.md) and [Feature requests](https://github.com/semuconsulting/pygnssutils/blob/main/.github/ISSUE_TEMPLATE/feature_request.md) - please use the templates provided. For general queries and advice, post a message to one of the [pygnssutils Discussions](https://github.com/semuconsulting/pygnssutils/discussions) channels.
59
55
 
60
- ![No Copilot](https://github.com/semuconsulting/PyGPSClient/blob/master/images/nocopilot100.png?raw=true)
56
+ ![No Copilot](https://github.com/semuconsulting/PyGPSClient/blob/main/images/nocopilot100.png?raw=true)
61
57
 
62
58
  ---
63
59
  ## <a name="installation">Installation</a>
64
60
 
65
61
  ![Python version](https://img.shields.io/pypi/pyversions/pygnssutils.svg?style=flat)
66
62
  [![PyPI version](https://img.shields.io/pypi/v/pygnssutils.svg?style=flat)](https://pypi.org/project/pygnssutils/)
67
- [![PyPI downloads](https://github.com/semuconsulting/pygpsclient/blob/master/images/clickpy_top10.svg?raw=true)](https://clickpy.clickhouse.com/dashboard/pygnssutils)
63
+ [![PyPI downloads](https://github.com/semuconsulting/pygpsclient/blob/main/images/clickpy_top10.svg?raw=true)](https://clickpy.clickhouse.com/dashboard/pygnssutils)
68
64
 
69
65
  `pygnssutils` is compatible with Python>=3.10.
70
66
 
@@ -138,7 +134,6 @@ class pygnssutils.gnssstreamer.GNSSStreamer(**kwargs)
138
134
  - 0 = none (default)
139
135
  - 1 = RTK NTRIP RTCM caster
140
136
  - 2 = RTK NTRIP SPARTN caster
141
- - 3 = RTK MQTT SPARTN source (see [gnssmqttclient](#gnssmqttclient) for MQTT client configuration details)
142
137
  - 4 = serial port
143
138
  - 5 = binary file.
144
139
 
@@ -428,41 +423,6 @@ gnssntripclient -h
428
423
 
429
424
  Refer to the [Sphinx API documentation](https://www.semuconsulting.com/pygnssutils/pygnssutils.html#module-pygnssutils.gnssntripclient) for further details.
430
425
 
431
- ---
432
- ## <a name="gnssmqttclient">GNSSMQTTClient and gnssmqttclient CLI</a>
433
- ```
434
- class pygnssutils.gnssmqttclient.GNSSMQTTClient(app=None, **kwargs)
435
- ```
436
-
437
- The `GNSSMQTTClient` class provides a basic SPARTN IP (MQTT) Client capability and forms the basis of a [`gnssmqttclient`](#gnssmqttclient) CLI utility. It receives RTK correction data from a SPARTN IP (MQTT) location service (e.g. the u-blox / Thingstream PointPerfect service) and (optionally) sends this to a designated output stream.
438
-
439
- ### CLI Usage:
440
-
441
- The `clientid` provided by the location service may be set as environment variable `MQTTCLIENTID`. If this environment variable is set and the TLS certificate (\*.crt) and key (\*.pem) files provided by the location service are placed in the user's `HOME` directory, the utility can use these as default settings and may be invoked without any arguments.
442
-
443
- Assuming the Python 3 scripts (bin) directory is in your PATH, the CLI utility may be invoked from the shell thus (press CTRL-C to terminate):
444
-
445
- ```shell
446
- gnssmqttclient --clientid yourclientid --server pp.services.u-blox.com --port 8883 --region eu --mode 0 --topic_ip 1 --topic_mga 1 --topic_key 1 --tlscrt '/Users/{your-user}/device-{your-clientid}-pp-cert.crt' --tlskey '/Users/{your-user}/device-{your-client-id}-pp-key.pem'} --spartndecode 0 --clioutput 0 --verbosity 2
447
- ```
448
- ```
449
- 2024-08-15 09:14:50.544 - INFO - pygnssutils.gnssmqttclient - Starting MQTT client with arguments {'server': 'pp.services.u-blox.com', 'port': 8883, 'clientid': 'your-client-id', 'region': 'eu', 'mode': 0, 'topic_ip': 1, 'topic_mga': 1, 'topic_key': 1, 'tlscrt': '/Users/myuser/device-your-client-id-pp-cert.crt', 'tlskey': '/Users/myuser/device-your-client-id-pp-key.pem', 'spartndecode': 0, 'output': None}.
450
- 2024-08-15 09:14:50.840 - INFO - pygnssutils.gnssmqttclient - RXM-SPARTN-KEY
451
- 2024-08-15 09:14:50.854 - INFO - pygnssutils.gnssmqttclient - MGA-INI-TIME-UTC
452
- 2024-08-15 09:14:50.858 - INFO - pygnssutils.gnssmqttclient - MGA-GPS-EPH
453
- ...
454
- ```
455
-
456
- Command line arguments can be stored in a configuration file and invoked using the `-C` or `--config` argument. The location of the configuration file can be set in environment variable `GNSSMQTTCLIENT_CONF`.
457
-
458
- For help and full list of optional arguments, type:
459
-
460
- ```shell
461
- gnssmqttclient -h
462
- ```
463
-
464
- Refer to the [pyspartn documentation](https://github.com/semuconsulting/pyspartn?tab=readme-ov-file#reading) for further details on decrypting encrypted (`eaf=1`) SPARTN payloads.
465
-
466
426
  ---
467
427
  ## <a name="socketserver">SocketServer</a>
468
428
 
@@ -627,6 +587,8 @@ semuadmin@semuconsulting.com
627
587
 
628
588
  ![License](https://img.shields.io/github/license/semuconsulting/pygnssutils.svg)
629
589
 
590
+ [![ORCID iD icon](https://orcid.org/sites/default/files/images/orcid_16x16.png) https://orcid.org/0009-0002-5751-8719](https://orcid.org/0009-0002-5751-8719)
591
+
630
592
  `pygnssutils` 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...
631
593
 
632
594
  [![Sponsor](https://github.com/semuconsulting/pyubx2/blob/master/images/sponsor.png?raw=true)](https://buymeacoffee.com/semuconsulting)
@@ -5,8 +5,11 @@ build-backend = "setuptools.build_meta:__legacy__"
5
5
  [project]
6
6
  name = "pygnssutils"
7
7
  dynamic = ["version"]
8
- authors = [{ name = "Steve Smith", email = "semuadmin@semuconsulting.com" }]
9
- maintainers = [{ name = "Steve Smith", email = "semuadmin@semuconsulting.com" }]
8
+ authors = [{ name = "Steve Smith" }, { email = "semuadmin@semuconsulting.com" }]
9
+ maintainers = [
10
+ { name = "Steve Smith" },
11
+ { email = "semuadmin@semuconsulting.com" },
12
+ ]
10
13
  description = "GNSS Command Line Utilities"
11
14
  license = "BSD-3-Clause"
12
15
  license-files = ["LICENSE"]
@@ -28,21 +31,22 @@ classifiers = [
28
31
  "Programming Language :: Python :: 3.12",
29
32
  "Programming Language :: Python :: 3.13",
30
33
  "Programming Language :: Python :: 3.14",
34
+ "Programming Language :: Python :: 3.15",
31
35
  "Topic :: Utilities",
32
36
  "Topic :: Software Development :: Libraries :: Python Modules",
33
37
  "Topic :: Scientific/Engineering :: GIS",
34
38
  ]
35
39
 
36
40
  dependencies = [
37
- "certifi>=2025.0.0",
38
- "paho-mqtt>=2.1.0",
41
+ "certifi>=2026.0.0",
42
+ "pynmeagps>=1.1.7",
43
+ "pyqgc>=1.0.0",
44
+ "pyrtcm>=1.2.0",
45
+ "pysbf2>=1.0.4",
39
46
  "pyserial>=3.5",
40
47
  "pyspartn>=1.0.8",
41
- "pyubx2>=1.3.6",
42
- "pynmeagps>=1.1.5",
43
- "pysbf2>=1.0.4",
48
+ "pyubx2>=1.3.7",
44
49
  "pyubxutils>=1.0.6",
45
- "pyqgc>=1.0.0",
46
50
  "pyunigps>=1.0.0",
47
51
  ]
48
52
 
@@ -50,7 +54,6 @@ dependencies = [
50
54
  gnssstreamer = "pygnssutils.gnssstreamer_cli:main"
51
55
  gnssserver = "pygnssutils.gnssserver_cli:main"
52
56
  gnssntripclient = "pygnssutils.gnssntripclient_cli:main"
53
- gnssmqttclient = "pygnssutils.gnssmqttclient_cli:main"
54
57
  pyrinexconv = "pygnssutils.rinex_conv_cli:main"
55
58
 
56
59
  [project.urls]
@@ -12,7 +12,6 @@ from pyubxutils.ubxsimulator import UBXSimulator
12
12
  from pygnssutils._version import __version__
13
13
  from pygnssutils.exceptions import GNSSError, GNSSStreamError, ParameterError
14
14
  from pygnssutils.globals import *
15
- from pygnssutils.gnssmqttclient import GNSSMQTTClient
16
15
  from pygnssutils.gnssntripclient import GNSSNTRIPClient
17
16
  from pygnssutils.gnssreader import (
18
17
  NMEA_PROTOCOL,
@@ -26,7 +25,6 @@ from pygnssutils.gnssreader import (
26
25
  from pygnssutils.gnssserver import GNSSSocketServer
27
26
  from pygnssutils.gnssstreamer import GNSSStreamer
28
27
  from pygnssutils.helpers import *
29
- from pygnssutils.mqttmessage import *
30
28
  from pygnssutils.rawnav import *
31
29
  from pygnssutils.rinex_conv import RinexConverter
32
30
 
@@ -8,4 +8,4 @@ Created on 2 Oct 2020
8
8
  :license: BSD 3-Clause
9
9
  """
10
10
 
11
- __version__ = "1.2.6"
11
+ __version__ = "1.2.8"
@@ -13,7 +13,7 @@ Returns both the raw binary data (as bytes) and the parsed data.
13
13
 
14
14
  - 'protfilter' governs which protocols (NMEA, UBX, SBF, QGC, UNI or RTCM3) are processed.
15
15
  - 'msgfilter' governs which individual message types are processed.
16
- - `parsing` governs whether payloads are fully or partially parsed.
16
+ - `parsing` governs whether individual payloads are parsed.
17
17
  - 'quitonerror' governs how errors are handled.
18
18
  - 'msgmode' indicates the type of UBX datastream (output GET, input SET, query POLL).
19
19
  If msgmode is set to SETPOLL, input/query mode will be automatically detected by parser.
@@ -318,8 +318,7 @@ class GNSSReader:
318
318
 
319
319
  raw_data = None
320
320
  parsed_data = None
321
- parsing = True
322
- while parsing: # loop until end of valid message or EOF
321
+ while True: # loop until end of valid message or EOF
323
322
  try:
324
323
 
325
324
  raw_data = None
@@ -336,38 +335,34 @@ class GNSSReader:
336
335
  # if protocol filter passes UBX, return message,
337
336
  # otherwise discard and continue
338
337
  if self._protfilter & UBX_PROTOCOL:
339
- parsing = False
340
- else:
341
- continue
338
+ break
339
+ continue
342
340
  # if it's an NMEA message (b'\x24\x..)
343
- elif bytehdr in NMEA_HDR:
341
+ if bytehdr in NMEA_HDR:
344
342
  raw_data, parsed_data = self._parse_nmea(bytehdr)
345
343
  # if protocol filter passes NMEA, return message,
346
344
  # otherwise discard and continue
347
345
  if self._protfilter & NMEA_PROTOCOL:
348
- parsing = False
349
- else:
350
- continue
346
+ break
347
+ continue
351
348
  # if it's an SBF message (b'\x24\x40')
352
- elif bytehdr in SBF_HDR:
349
+ if bytehdr in SBF_HDR:
353
350
  raw_data, parsed_data = self._parse_sbf(bytehdr)
354
351
  # if protocol filter passes SBF, return message,
355
352
  # otherwise discard and continue
356
353
  if self._protfilter & SBF_PROTOCOL:
357
- parsing = False
358
- else:
359
- continue
354
+ break
355
+ continue
360
356
  # if it's an QGCmessage (b'\x51\x47')
361
- elif bytehdr in QGC_HDR:
357
+ if bytehdr in QGC_HDR:
362
358
  raw_data, parsed_data = self._parse_qgc(bytehdr)
363
359
  # if protocol filter passes QGC, return message,
364
360
  # otherwise discard and continue
365
361
  if self._protfilter & QGC_PROTOCOL:
366
- parsing = False
367
- else:
368
- continue
362
+ break
363
+ continue
369
364
  # if it's an UNImessage (b'\xaa\x44\xb5')
370
- elif bytehdr in UNI_HDR[:2]:
365
+ if bytehdr in UNI_HDR[:2]:
371
366
  byte3 = self._read_bytes(1)
372
367
  bytehdr += byte3
373
368
  if bytehdr != UNI_HDR:
@@ -376,21 +371,18 @@ class GNSSReader:
376
371
  # if protocol filter passes UNI, return message,
377
372
  # otherwise discard and continue
378
373
  if self._protfilter & UNI_PROTOCOL:
379
- parsing = False
380
- else:
381
- continue
374
+ break
375
+ continue
382
376
  # if it's a RTCM3 message
383
377
  # (byte1 = 0xd3; byte2 = 0b000000**)
384
- elif byte1 == b"\xd3" and (byte2[0] & ~0x03) == 0:
378
+ if byte1 == b"\xd3" and (byte2[0] & ~0x03) == 0:
385
379
  raw_data, parsed_data = self._parse_rtcm3(bytehdr)
386
380
  # if protocol filter passes RTCM, return message,
387
381
  # otherwise discard and continue
388
382
  if self._protfilter & RTCM3_PROTOCOL:
389
- parsing = False
390
- else:
391
- continue
392
- else:
393
- raise GNSSStreamError(f"Unknown protocol header {bytehdr}.")
383
+ break
384
+ continue
385
+ raise GNSSStreamError(f"Unknown protocol header {bytehdr}.")
394
386
 
395
387
  except EOFError:
396
388
  return (None, None)
@@ -17,7 +17,6 @@ Supported output channels:
17
17
  Supported input channels:
18
18
  - NTRIP RTCM client
19
19
  - NTRIP SPARTN client
20
- - MQTT SPARTN client
21
20
  - serial stream
22
21
  - file stream
23
22
 
@@ -57,7 +56,6 @@ from pygnssutils.globals import (
57
56
  FORMAT_PARSED,
58
57
  FORMAT_PARSEDSTRING,
59
58
  INPUT_FILE,
60
- INPUT_MQTT_SPARTN,
61
59
  INPUT_NONE,
62
60
  INPUT_NTRIP_RTCM,
63
61
  INPUT_NTRIP_SPARTN,
@@ -73,7 +71,6 @@ from pygnssutils.globals import (
73
71
  OUTPUT_TEXT_FILE,
74
72
  UBXSIMULATOR,
75
73
  )
76
- from pygnssutils.gnssmqttclient import GNSSMQTTClient
77
74
  from pygnssutils.gnssntripclient import GNSSNTRIPClient
78
75
  from pygnssutils.gnssreader import (
79
76
  ERR_LOG,
@@ -162,34 +159,6 @@ def _setup_input_ntrip(app: object, datatype: str, **kwargs) -> object:
162
159
  return gnc
163
160
 
164
161
 
165
- def _setup_input_mqtt(app: object, datatype: str, **kwargs) -> object:
166
- """
167
- Set up MQTT SPARTN client as input data source.
168
-
169
- :param app: calling application (i.e. gnssstreamer)
170
- :param datatype: "MQTT"
171
- :returns: reference to MQTT client
172
- :rtype: GNSSMQTTClient
173
- """
174
-
175
- # pylint: disable=unused-argument
176
-
177
- prot, hostname, port, path = parse_url(kwargs["input"])
178
- prot = 1 if prot == "https" else 0
179
-
180
- gmq = GNSSMQTTClient(app)
181
- gmq.start(
182
- server=hostname,
183
- port=port,
184
- clientid=kwargs.get("rtkuser", "anon"),
185
- region=path.lower(), # e.g. "eu"
186
- mode=0, # IP (as opposed to 1 = L-Band)
187
- output=kwargs["inqueue"], # send SPARTN data to receiver
188
- )
189
-
190
- return gmq
191
-
192
-
193
162
  def _setup_input_stream(app: object, datatype: str, **kwargs) -> object:
194
163
  """
195
164
  Set up serial stream as input data source.
@@ -379,8 +348,6 @@ def _run_streamer(stream, **kwargs):
379
348
  _setup_input_ntrip(gns, "RTCM", **kwargs)
380
349
  elif cliinput == INPUT_NTRIP_SPARTN:
381
350
  _setup_input_ntrip(gns, "SPARTN", **kwargs)
382
- elif cliinput == INPUT_MQTT_SPARTN:
383
- _setup_input_mqtt(gns, "MQTT", **kwargs)
384
351
  elif cliinput == INPUT_SERIAL:
385
352
  _setup_input_stream(gns, "SERIAL", **kwargs)
386
353
  elif cliinput == INPUT_FILE:
@@ -568,7 +535,6 @@ def main():
568
535
  f"CLI input type {INPUT_NONE} = none, "
569
536
  f"{INPUT_NTRIP_RTCM} = RTK NTRIP RTCM, "
570
537
  f"{INPUT_NTRIP_SPARTN} = RTK NTRIP SPARTN, "
571
- f"{INPUT_MQTT_SPARTN} = RTK MQTT SPARTN, "
572
538
  f"{INPUT_SERIAL} = serial port, "
573
539
  f"{INPUT_FILE} = binary file"
574
540
  ),
@@ -577,7 +543,6 @@ def main():
577
543
  INPUT_NONE,
578
544
  INPUT_NTRIP_RTCM,
579
545
  INPUT_NTRIP_SPARTN,
580
- INPUT_MQTT_SPARTN,
581
546
  INPUT_SERIAL,
582
547
  INPUT_FILE,
583
548
  ],
@@ -592,8 +557,6 @@ def main():
592
557
  "(e.g. 'http://rtk2go.com:2101/MOUNTPOINT'); "
593
558
  f"If cliinput = {INPUT_NTRIP_SPARTN}, format = full url "
594
559
  "(e.g. 'https://ppntrip.services.u-blox.com:2102/EU'); "
595
- f"If cliinput = {INPUT_MQTT_SPARTN}, format = full url "
596
- "(e.g. 'https://pp.services.u-blox.com:8883/eu', where /path signifies region); "
597
560
  f"If cliinput = {INPUT_SERIAL}, format = port@baudrate (e.g. '/dev/tty.ACM1@38400'); "
598
561
  f"If cliinput = {INPUT_FILE}, format = file name (e.g. '/home/myuser/ubxconfig.ubx'). "
599
562
  "NB: gnssstreamer will have exclusive use of any serial port."
@@ -52,7 +52,7 @@ NEQUICK = "NEQUICK"
52
52
  NMEA = "nmea"
53
53
  OBS = "O"
54
54
  OMEGADOTREF = -2.6e-9
55
- PYRINEXCONV_VERSION = "0.1.7 Alpha"
55
+ PYRINEXCONV_VERSION = "0.2.0 Beta"
56
56
  QZS = "J"
57
57
  RINEX_CANCELLED = 2
58
58
  RINEX_ERROR = 99
@@ -1355,7 +1355,7 @@ def format_licenseofuse(lou: str = "") -> str:
1355
1355
 
1356
1356
  if lou == "":
1357
1357
  return ""
1358
- return f"{license:<{DATAWIDTH}}LICENSE OF USE\n"
1358
+ return f"{lou:<{DATAWIDTH}}LICENSE OF USE\n"
1359
1359
 
1360
1360
 
1361
1361
  def format_stationinfo(station: str = "") -> str: