Skip to content

Commit 37e06df

Browse files
authored
Merge pull request #240 from semuconsulting/RC-1.6.3
RC 1.6.3 - Add Unicore binary data output support
2 parents 59b79d9 + f4b3bc8 commit 37e06df

17 files changed

Lines changed: 311 additions & 60 deletions

INSTALLATION.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,13 @@ TBC. Anyone conversant with PowerShell is welcome to contribute an equivalent in
243243
244244
## <a name="troubleshooting">Troubleshooting</a>
245245
246-
1. The optional `rasterio` package is only available as an [sdist](#sdist-vs-wheel) on some Linux / ARM platforms (including Raspberry Pi OS), and the consequent [GDAL](https://gdal.org/en/stable/) build and configuration requirements may be problematic e.g. `WARNING:root:Failed to get options via gdal-config`. Refer to [rasterio installation](https://rasterio.readthedocs.io/en/stable/installation.html) and [GDAL installation](https://gdal.org/en/stable/) for assistance but - *be warned* - the process is **not** for the faint-hearted.
246+
1. `[Errno 13] could not open port /dev/tty**** [Errno 13] permission denied /dev/tty****` error on Linux when attempting to access serial port. Refer to [User Privileges](#userpriv).
247+
248+
1. The optional `rasterio` package is only available as an [sdist](#sdist-vs-wheel) on some Linux / ARM platforms and the consequent [GDAL](https://gdal.org/en/stable/) build and configuration requirements may be problematic e.g. `WARNING:root:Failed to get options via gdal-config`. Refer to [rasterio installation](https://rasterio.readthedocs.io/en/stable/installation.html) and [GDAL installation](https://gdal.org/en/stable/) for assistance but - *be warned* - the process is **not** for the faint-hearted.
247249
248250
In practice, `rasterio` is only required for automatic extents detection in PyGPSClient's Import Custom Map facility. As a workaround, extents can be entered manually, or you can try importing maps on a different platform and then copy-and-paste the relevant `usermaps_l` extents configuration to the target platform.
249251

250-
1. The optional `cryptography` package is only available as an [sdist](#sdist-vs-wheel) on some 32-bit Linux / ARM platforms (including Raspberry Pi OS), and the consequent OpenSSL build requirements may be problematic e.g. `Building wheel for cryptography (PEP 517): finished with status 'error'`. Refer to [cryptography installation](https://github.com/semuconsulting/pyspartn/blob/main/cryptography_installation/README.md) for assistance.
252+
1. The optional `cryptography` package is only available as an [sdist](#sdist-vs-wheel) on some 32-bit Linux / ARM platforms and the consequent OpenSSL build requirements may be problematic e.g. `Building wheel for cryptography (PEP 517): finished with status 'error'`. Refer to [cryptography installation](https://github.com/semuconsulting/pyspartn/blob/main/cryptography_installation/README.md) for assistance.
251253

252254
---
253255
## <a name="license">License</a>

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
PyGPSClient is a free, open-source, multi-platform graphical GNSS/GPS testing, diagnostic and configuration application written entirely by volunteers in Python and tkinter.
2222
* Runs on any platform which supports a Python 3 interpreter (>=3.10) and tkinter (>=8.6) GUI framework, including Windows, MacOS, Linux and Raspberry Pi OS. Accommodates low resolution screens (>= 640x480) via resizable and/or scrollable panels.
23-
* Supports NMEA, UBX, SBF, QGC, RTCM3, NTRIP, SPARTN, MQTT and TTY (ASCII) protocols¹.
23+
* Supports NMEA, UBX (u-blox binary), SBF (Septentrio binary), UNI (Unicore binary), QGC (Quectel binary), RTCM3, NTRIP, SPARTN, MQTT and TTY (ASCII) protocols¹.
2424
* Capable of reading from a variety of GNSS data streams: Serial (USB / UART), Socket (TCP / UDP), binary data stream (terminal or file capture) and binary recording (e.g. u-center \*.ubx).
2525
* Provides [NTRIP](#ntripconfig) client facilities.
2626
* Can serve as an [NTRIP base station](#basestation) with an RTK-compatible receiver (e.g. u-blox ZED-F9P/ZED-X20P, Quectel LG290P/LG580P/LC29H, Septentrio Mosaic G5/X5 or Unicore UM98n).
@@ -116,7 +116,7 @@ For more comprehensive installation instructions, please refer to [INSTALLATION.
116116
1. To immediately disconnect and terminate all running threads, click Ctrl-K ("Kill Switch").
117117
1. To exit the application, click
118118
![exit icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-door-6-24.png?raw=true), or press Ctrl-Q, or click the application window's close window icon.
119-
1. Protocols Shown - Select which protocols to display; NMEA, UBX, SBF, QGC, RTCM3, SPARTN or TTY (NB: this only changes the displayed protocols - to change the actual protocols output by the receiver, use the [UBX Configuration Dialog](#ubxconfig)).
119+
1. Protocols Shown - Select which protocols to display; NMEA, UBX (*u-blox binary*), SBF (*Septentrio binary*), UNI (*Unicore binary*), QGC (*Quectel binary*), RTCM3, SPARTN or TTY (*ASCII text*) (NB: this only changes the displayed protocols - to change the actual protocols output by the receiver, use the relevant configuration command(s)).
120120
- **NB:** Serial connection must be stopped before changing to or from TTY (terminal) protocol.
121121
- **NB:** Enabling TTY (terminal) mode will disable all other protocols.
122122
1. Console Display - Select console display format (Parsed, Binary, Hex Tabular, Hex String, Parsed+Hex Tabular - see Console Widget below).
@@ -457,7 +457,7 @@ The `pygnssutils` and `pyubxutils` libraries which underpin many of the function
457457

458458
For further details, refer to the `pygnssutils` homepage at [https://github.com/semuconsulting/pygnssutils](https://github.com/semuconsulting/pygnssutils) or `pyubxutils` homepage at [https://github.com/semuconsulting/pyubxutils](https://github.com/semuconsulting/pyubxutils).
459459

460-
--
460+
---
461461
## <a name="knownissues">Known Issues</a>
462462

463463
1. Most budget USB-UART adapters (e.g. FT232, CH345, CP2102) have a bandwidth limit of around 3MB/s and may not work reliably above 115200 baud, even if the receiver supports higher baud rates. If you're using an adapter and notice significant message corruption, try reducing the baud rate to a maximum 115200.

RELEASE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# PyGPSClient Release Notes
22

3+
### RELEASE 1.6.3
4+
5+
1. Add support for Unicore UNI binary data output messages via `pyunigps>=0.1.3` and `pygnssutils>=1.1.22`.
6+
37
### RELEASE 1.6.2
48

59
1. Add support for Unicore Secondary Antenna and Attitude (IMU) NMEA sentences e.g. UM98n "GGAH", "HPD" (requires pynmeagps>=1.1.0).

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ classifiers = [
4949
"Topic :: Scientific/Engineering :: GIS",
5050
]
5151

52-
dependencies = ["requests>=2.28.0", "Pillow>=9.0.0", "pygnssutils>=1.1.21"]
52+
dependencies = [
53+
"requests>=2.28.0",
54+
"Pillow>=9.0.0",
55+
"pygnssutils>=1.1.22",
56+
"pyunigps>=0.1.4",
57+
]
5358

5459
[project.scripts]
5560
pygpsclient = "pygpsclient.__main__:main"

src/pygpsclient/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
:license: BSD 3-Clause
99
"""
1010

11-
__version__ = "1.6.2"
11+
__version__ = "1.6.3"

src/pygpsclient/app.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@
4848
from types import NoneType
4949

5050
from pygnssutils import GNSSMQTTClient, GNSSNTRIPClient, MQTTMessage
51-
from pygnssutils.gnssreader import ( # UNI_PROTOCOL, # TODO
51+
from pygnssutils.gnssreader import (
5252
NMEA_PROTOCOL,
5353
POLL,
5454
QGC_PROTOCOL,
5555
RTCM3_PROTOCOL,
5656
SBF_PROTOCOL,
5757
UBX_PROTOCOL,
58+
UNI_PROTOCOL,
5859
)
5960
from pygnssutils.socket_server import ClientHandler, ClientHandlerTLS, SocketServer
6061
from pynmeagps import NMEAMessage
@@ -63,6 +64,7 @@
6364
from pysbf2 import SBFMessage
6465
from pyspartn import SPARTNMessage
6566
from pyubx2 import UBXMessage
67+
from pyunigps import UNIMessage
6668
from serial import SerialException, SerialTimeoutException
6769

6870
from pygpsclient._version import __version__ as VERSION
@@ -97,7 +99,6 @@
9799
STATUSPRIORITY,
98100
TTY_PROTOCOL,
99101
UNDO,
100-
UNI_PROTOCOL,
101102
)
102103
from pygpsclient.gnss_status import GNSSStatus
103104
from pygpsclient.helpers import (
@@ -913,8 +914,8 @@ def process_data(self, raw_data: bytes, parsed_data: object, marker: str = ""):
913914
msgprot = SBF_PROTOCOL
914915
elif isinstance(parsed_data, QGCMessage):
915916
msgprot = QGC_PROTOCOL
916-
# elif isinstance(parsed_data, UNIMessage):
917-
# msgprot = UNI_PROTOCOL
917+
elif isinstance(parsed_data, UNIMessage):
918+
msgprot = UNI_PROTOCOL
918919
elif isinstance(parsed_data, UBXMessage):
919920
msgprot = UBX_PROTOCOL
920921
elif isinstance(parsed_data, RTCMMessage):

src/pygpsclient/chart_frame.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
BGCOL,
4141
ERRCOL,
4242
FGCOL,
43+
INFOCOL,
4344
PLOTCOLS,
4445
READONLY,
4546
TRACEMODE_WRITE,
@@ -48,6 +49,7 @@
4849
WIDGETU6,
4950
)
5051
from pygpsclient.helpers import time2str
52+
from pygpsclient.strings import CONTENTCOPIED
5153

5254
OL_WID = 1
5355
LBLCOL = "white"
@@ -623,6 +625,7 @@ def _on_clipboard(self, event): # pylint: disable=unused-argument
623625
self.__master.clipboard_clear()
624626
self.__master.clipboard_append(csv)
625627
self.__master.update()
628+
self.__app.status_label = (CONTENTCOPIED.format("chart"), INFOCOL)
626629

627630
def _on_resize(self, event): # pylint: disable=unused-argument
628631
"""

src/pygpsclient/console_frame.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@
4343
FORMAT_BOTH,
4444
FORMAT_HEXSTR,
4545
FORMAT_HEXTAB,
46+
INFOCOL,
4647
WIDGETU3,
4748
)
48-
from pygpsclient.strings import HALTTAGWARN
49+
from pygpsclient.strings import CONTENTCOPIED, HALTTAGWARN
4950

5051
HALT = "HALT"
5152
CONSOLELINES = 20
@@ -242,6 +243,7 @@ def _on_clipboard(self, event): # pylint: disable=unused-argument
242243
self.__master.clipboard_clear()
243244
self.__master.clipboard_append(self.txt_console.get("1.0", END))
244245
self.__master.update()
246+
self.__app.status_label = (CONTENTCOPIED.format("console"), INFOCOL)
245247

246248
def _on_resize(self, event): # pylint: disable=unused-argument
247249
"""

src/pygpsclient/globals.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
PNTCOL = "#FF8000" # default plot point color
5454

5555
# Protocols to be used in protocol mask (others defined in pygnssutils.gnss_reader.py)
56-
UNI_PROTOCOL = 32 # provisional - awaiting pygnssutils.gnssreader updates for Unicore
5756
SPARTN_PROTOCOL = 256
5857
MQTT_PROTOCOL = 512
5958
TTY_PROTOCOL = 1024
@@ -252,7 +251,7 @@
252251
TRACK = "track"
253252
TRACEMODE_WRITE = "write"
254253
TTYOK = ("OK", "$R:")
255-
TTYERR = ("ERROR", "$R?")
254+
TTYERR = ("ERROR", "$R?", "FAIL", "CAN'T FOUND DEVICE")
256255
TTYMARKER = "TTY<<"
257256
UBXPRESETS = "ubxpresets"
258257
UBXSIMULATOR = "ubxsimulator"
@@ -424,11 +423,31 @@
424423
"PVTGeodetic7": "RTK FIXED",
425424
"PVTGeodetic8": "RTK FLOAT",
426425
"PVTGeodetic10": "PPP",
426+
"BESTNAV0": "NO FIX",
427+
"BESTNAV1": "FIXEDPOS", # FIXEDPOS Position fixed by the FIX POSITION command
428+
"BESTNAV2": "FIXEDHMSL", # FIXEDHEIGHT Not supported currently
429+
"BESTNAV8": "DOPP", # DOPPLER_VELOCITY Velocity computed using instantaneous Doppler
430+
"BESTNAV16": "3D", # SINGLE Single point positioning
431+
"BESTNAV17": "RTK FLOAT", # SRDIFF Pseudorange differential solution
432+
"BESTNAV18": "SBAS", # SBAS SBAS positioning
433+
"BESTNAV32": "RTK FLOAT", # L1_FLOAT L1 float solution
434+
"BESTNAV33": "RTK FLOAT", # IONOFREE_FLOAT Ionosphere-free float solution
435+
"BESTNAV34": "RTK FLOAT", # NARROW_FLOAT Narrow-lane float solution
436+
"BESTNAV48": "RTK FIXED", # L1_INT L1 fixed solution
437+
"BESTNAV49": "RTK FIXED", # WIDE_INT Wide-lane fixed solution
438+
"BESTNAV50": "RTK FIXED", # NARROW_INT Narrow-lane fixed solution
439+
"BESTNAV52": "DR", # INS Inertial navigation solution
440+
"BESTNAV53": "3D+DR", # INS_PSRSP Integrated solution of INS and single point pos
441+
"BESTNAV54": "RTK+DR", # INS_PSRDIFF Integrated solution of INS and pseudorange diff pos
442+
"BESTNAV55": "RTK FLOAT+DR", # INS_RTKFLOAT Integrated solution of INS and RTK float
443+
"BESTNAV56": "RTK FIXED+DR", # INS_RTKFIXED Integrated solution of INS and RTK fix
444+
"BESTNAV68": "RTK FIXED+DR", # INS_RTKFIXED Integrated solution of INS and RTK fix
445+
"BESTNAV69": "PPP", # PPP
427446
}
428447
"""
429448
Map of fix values to descriptions.
430-
The keys in this map are a concatenation of NMEA/UBX
431-
message identifier and attribute value e.g.
449+
The keys in this map are a concatenation of
450+
message identity and attribute value e.g.
432451
GGA1: GGA + quality = 1
433452
NAV-STATUS3: NAV-STATUS + gpsFix = 3
434453
(valid for NMEA >=4)

src/pygpsclient/helpers.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from typing import Any, Literal
4343

4444
from pygnssutils import version as PGVERSION
45-
from pynmeagps import WGS84_SMAJ_AXIS, NMEAMessage, haversine
45+
from pynmeagps import WGS84_SMAJ_AXIS, NMEAMessage, haversine, leapsecond
4646
from pynmeagps import version as NMEAVERSION
4747
from pyqgc import version as QGCVERSION
4848
from pyrtcm import version as RTCMVERSION
@@ -59,6 +59,7 @@
5959
atttyp,
6060
)
6161
from pyubx2 import version as UBXVERSION
62+
from pyunigps import version as UNIVERSION
6263
from requests import get
6364

6465
from pygpsclient._version import __version__ as VERSION
@@ -107,6 +108,7 @@
107108
"pygnssutils": PGVERSION,
108109
"pyubx2": UBXVERSION,
109110
"pysbf2": SBFVERSION,
111+
"pyunigps": UNIVERSION,
110112
"pyqgc": QGCVERSION,
111113
"pynmeagps": NMEAVERSION,
112114
"pyrtcm": RTCMVERSION,
@@ -1445,20 +1447,24 @@ def valid_geom(geom: str) -> bool:
14451447
return regexgeom.match(geom) is not None
14461448

14471449

1448-
def wnotow2date(wno: int, tow: int) -> datetime:
1450+
def wnotow2date(wno: int, tow: int, ls: int | NoneType = None) -> datetime:
14491451
"""
1450-
Get datetime from GPS Week number (Wno) and Time of Week (Tow).
1452+
Get datetime from GPS Week number (Wno), Time of Week (Tow)
1453+
and leapsecond offset.
14511454
14521455
GPS Epoch 0 = 6th Jan 1980
14531456
14541457
:param int wno: week number
14551458
:param int tow: time of week
1459+
:param int ls: leapsecond offset
14561460
:return: datetime
14571461
:rtype: datetime
14581462
"""
14591463

1464+
if ls is None:
1465+
ls = leapsecond(datetime.now())
14601466
dat = GPSEPOCH0 + timedelta(days=wno * 7)
1461-
dat += timedelta(seconds=tow)
1467+
dat += timedelta(seconds=tow - ls)
14621468
return dat
14631469

14641470

0 commit comments

Comments
 (0)