Skip to content

Commit 6cdbd08

Browse files
committed
add hae/sep toggle
1 parent 275e23c commit 6cdbd08

27 files changed

Lines changed: 120 additions & 18 deletions

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ PyGPSClient is a free, open-source, multi-platform graphical GNSS/GPS testing, d
2626
* Provides [NTRIP client](#ntripconfig) facilities for both RTCM3 and SPARTN NTRIP services.
2727
* Can serve as an [NTRIP base station](#basestation) with an RTK-compatible receiver (e.g. u-blox ZED-F9P/ZED-X20P, Quectel LG/LC Series, Septentrio Mosaic Series or Unicore UM9** Series).
2828
* Supports GNSS (*and related*) device configuration via proprietary UBX, NMEA and ASCII TTY protocols, including most u-blox, Quectel, Septentrio, Unicore and Feyman GNSS devices.
29-
* **New in v1.6.7** - Experimental support for [RINEX conversion](#rinex) of raw observation, navigation and meteorology data.
29+
* **New in version >= 1.6.7** - Experimental support for [RINEX conversion](#rinex) of raw observation, navigation and meteorology data.
3030
* Can be installed using the standard `pip` Python package manager - see [installation instructions](#installation) below.
3131

3232
This is an independent project and we have no affiliation whatsoever with any GNSS manufacturer or distributor.
@@ -183,7 +183,7 @@ For more comprehensive installation instructions, please refer to [INSTALLATION.
183183
---
184184
| Widget | To show or hide the various widgets, go to Menu..View and click on the relevant hide/show option. |
185185
|---------------------------|---------------------------------------------------------------------------------------------------|
186-
|![banner widget](https://github.com/semuconsulting/PyGPSClient/blob/master/images/banner_widget.png?raw=true)| Expandable banner showing key navigation status information based on messages received from receiver. To expand or collapse the banner or serial port configuration widgets, click the ![expand icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-arrow-80-16.png?raw=true)/![expand icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-triangle-1-16.png?raw=true) buttons. Ordinarily 'track:' represents heading of motion (aka course over ground), but the field will display 'hdg:' where static heading (yaw) is available. **NB**: some fields (e.g. hdop/vdop, hacc/vacc) are only available from proprietary NMEA or UBX messages and may not be output by default. The minimum messages required to populate all available fields are: NMEA: GGA, GSA, GSV, RMC, UBX00 (proprietary); UBX: NAV-DOP, NAV-PVT, NAV-SAT; UNI: BESTNAV, SATSINFO, STADOP. |
186+
|![banner widget](https://github.com/semuconsulting/PyGPSClient/blob/master/images/banner_widget.png?raw=true)| Expandable banner showing key navigation status information based on messages received from receiver. To expand or collapse the banner or serial port configuration widgets, click the ![expand icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-arrow-80-16.png?raw=true)/![expand icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-triangle-1-16.png?raw=true) buttons. Double-click the "hae" label or value to toggle between hae (height above ellipsoid) and sep (separation) values. **NB**: some fields (e.g. hdop/vdop, hacc/vacc) are only available from proprietary NMEA or UBX messages and may not be output by default. The minimum messages required to populate all available fields are: NMEA: GGA, GSA, GSV, RMC, UBX00 (proprietary); UBX: NAV-DOP, NAV-PVT, NAV-SAT; UNI: BESTNAV, SATSINFO, STADOP. |
187187
|![console widget](https://github.com/semuconsulting/PyGPSClient/blob/master/images/console_widget.png?raw=true)| Configurable serial console widget showing incoming GNSS data streams in either parsed, binary or tabular hexadecimal formats. Double-right-click to copy contents of console to the clipboard. The scroll behaviour and number of lines retained in the console can be configured via the settings panel. Supports user-configurable color tagging of selected strings for easy identification. Color tags are loaded from the `"colortag_b":` value (`0` = disable, `1` = enable) and `"colortags_l":` list (`[string, color]` pairs) in your json configuration file (see example provided). If color is set to "HALT", streaming will halt on any match and a warning displayed. NB: color tagging does impose a small performance overhead - turning it off will improve console response times at very high transaction rates.|
188188
|![skyview widget](https://github.com/semuconsulting/PyGPSClient/blob/master/images/skyview_widget.png?raw=true)| Skyview widget showing current satellite visibility and position (elevation / azimuth). Satellite icon borders are colour-coded to distinguish between different GNSS constellations. For consistency between NMEA and UBX data sources, will display GLONASS NMEA SVID (65-96) rather than slot (1-24). |
189189
|![levelsview widget](https://github.com/semuconsulting/PyGPSClient/blob/master/images/graphview_widget.png?raw=true)| Levels view widget showing current satellite carrier-to-noise (C/No) levels for each GNSS constellation. Double-click to toggle legend. Double-right-click to toggle levels where C/No = 0 dbHz. |
@@ -322,7 +322,7 @@ The NTRIP Configuration utility allows users to receive and process NTRIP RTK Co
322322
1. For NTRIP services which require client position data via NMEA GGA sentences, select the appropriate sentence transmission interval in seconds. The default is 'None' (no GGA sentences sent). A value of 10 or 60 seconds is typical.
323323
1. If GGA sentence transmission is enabled, GGA sentences can either be populated from live navigation data (*assuming a receiver is connected and outputting valid position data*) or from fixed reference settings entered in the NTRIP configuration panel (latitude, longitude, elevation and geoid separation - all four reference settings must be provided).
324324
1. To connect to the NTRIP server, click ![connect icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-media-control-48-24.png?raw=true). To disconnect, click ![disconnect icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-media-control-50-24.png?raw=true).
325-
1. If NTRIP data is being successfully received, the banner '**corr:**' status indicator should change to 'YES' and indicate the age and reference station of the correction data (where available) ![dgps status](https://github.com/semuconsulting/PyGPSClient/blob/master/images/dgps_status.png?raw=true). Note that DGPS status is typically maintained for up to 60 seconds after loss of correction signal.
325+
1. If NTRIP data is being successfully received, the banner '**corr:**' status indicator should change to '' and indicate the age and reference station of the correction data (where available) ![dgps status](https://github.com/semuconsulting/PyGPSClient/blob/master/images/dgps_status.png?raw=true). Note that CORR status is typically maintained for up to 60 seconds after loss of correction signal.
326326
1. Some NTRIP services may output RTCM3 or SPARTN correction messages at a high rate, flooding the GUI console display. To suppress these messages in the console, de-select the 'RTCM' or'SPARTN' options in 'Protocols Shown' - the RTCM3 or SPARTN messages will continue to be processed in the background.
327327

328328
Below is a illustrative NTRIP DGPS data log, showing:
@@ -428,9 +428,7 @@ The RINEX Conversion Dialog supports the conversion of raw observation, navigati
428428

429429
**Pre-Requisites:**
430430

431-
1. A previously-saved binary datalog containing raw observation (UBX RXM-RAWX), navigation (UBX RXM-SFRBX¹) and/or meteorology (NMEA) data or RTCM3 ephemerides (1019, 1020, 1041-1046) messages. A suitable datalog can be recorded using PyGPSClient's [binary datalogging](#datalog) facility. **NB**: The file should contain at least 15-30 minutes of continuous data.
432-
433-
¹ The alpha release of the [pygnssutils RINEX NAV conversion utility](https://github.com/semuconsulting/pygnssutils#rinexconvert) currently implements GPS LNAV/CNAV, Galileo FNAV/INAV, Beidou D1/D2 and Glonass L1OF signal types. This will be enhanced in future releases.
431+
1. A previously-saved binary datalog containing raw observation (UBX RXM-RAWX), navigation (UBX RXM-SFRBX) and/or meteorology (NMEA) data or RTCM3 ephemerides (1019, 1020, 1041-1046) messages. A suitable datalog can be recorded using PyGPSClient's [binary datalogging](#datalog) facility. **NB**: The file should contain at least 15-30 minutes of continuous data.
434432

435433
**Instructions:**
436434

RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
### RELEASE 1.7.0
44

5+
1. Can now double-click to toggle between 'hae' (height above ellipsoid) and 'sep' (separation) values in banner panel.
56
1. Minimum pyubx2 version updated to 1.3.3 (adds new firmware configuration database items for u-blox X20 HPG 2.10).
67
1. Default log level amended to '0' (ERROR) rather than '-1' (CRITICAL). Any logged exception tracebacks will now appear in terminal logs by default.
7-
1. Updates to RINEX conversion dialog for pygnssutil>=1.2.3 (incorporates various bug fixes to RINEX conversion routines, but still an experimental facility).
8+
1. Updates to RINEX conversion dialog for pygnssutil>=1.2.5 (incorporates various bug fixes to RINEX conversion routines, but remains an experimental facility).
89

910
### RELEASE 1.6.10
1011

images/dgps_status.png

-5.45 KB
Loading

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ classifiers = [
5252
dependencies = [
5353
"requests>=2.34.0",
5454
"Pillow>=12.0.0",
55-
"pygnssutils>=1.2.4",
55+
"pygnssutils>=1.2.5",
5656
"pyunigps>=1.0.0",
5757
"pynmeagps>=1.1.5",
5858
"pyubx2>=1.3.3",

src/pygpsclient/about_dialog.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from PIL import Image, ImageTk
1919

2020
from pygpsclient.globals import (
21+
CLICK_CURSOR,
2122
ERRCOL,
2223
ICON_APP128,
2324
ICON_GITHUB,
@@ -112,7 +113,7 @@ def _body(self):
112113
self._frm_body,
113114
text="",
114115
width=16,
115-
cursor="hand2",
116+
cursor=CLICK_CURSOR,
116117
)
117118
self._chk_checkupdate = Checkbutton(
118119
self._frm_body,
@@ -122,18 +123,18 @@ def _body(self):
122123
self._lbl_sponsoricon = Label(
123124
self._frm_body,
124125
image=self._img_sponsor,
125-
cursor="hand2",
126+
cursor=CLICK_CURSOR,
126127
)
127128
self._lbl_github = Label(
128129
self._frm_body,
129130
text=GITHUB_URL,
130131
fg=INFOCOL,
131-
cursor="hand2",
132+
cursor=CLICK_CURSOR,
132133
)
133134
self._lbl_copyright = Label(
134135
self._frm_body,
135136
text=COPYRIGHT,
136-
cursor="hand2",
137+
cursor=CLICK_CURSOR,
137138
)
138139

139140
def _do_layout(self):

src/pygpsclient/banner_frame.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from pygpsclient.globals import (
2121
BGCOL,
22+
CLICK_CURSOR,
2223
CONNECTED,
2324
CONNECTED_FILE,
2425
CONNECTED_NTRIP,
@@ -94,6 +95,7 @@ def __init__(self, app: Frame, parent: Frame, *args, **kwargs):
9495
self._img_ntrip = ImageTk.PhotoImage(Image.open(ICON_NTRIPCONFIG))
9596
self._img_spartn = ImageTk.PhotoImage(Image.open(ICON_SPARTNCONFIG))
9697
self._img_blank = ImageTk.PhotoImage(Image.open(ICON_BLANK))
98+
self._sep = False
9799

98100
super().__init__(parent, *args, **kwargs)
99101

@@ -143,12 +145,18 @@ def _body(self):
143145
height=22,
144146
command=self._toggle_advanced,
145147
image=self._img_expand,
148+
cursor=CLICK_CURSOR,
146149
)
147150
self._lbl_lhmsl = Label(
148151
self._frm_advanced, text="hmsl:", bg=BGCOL, fg=FGCOL, anchor=N
149152
)
150153
self._lbl_lhae = Label(
151-
self._frm_advanced, text="hae:", bg=BGCOL, fg=FGCOL, anchor=N
154+
self._frm_advanced,
155+
text="hae:",
156+
bg=BGCOL,
157+
fg=FGCOL,
158+
anchor=N,
159+
cursor=CLICK_CURSOR,
152160
)
153161
self._lbl_lspd = Label(
154162
self._frm_advanced, text="speed:", bg=BGCOL, fg=FGCOL, anchor=N
@@ -195,7 +203,12 @@ def _body(self):
195203
self._frm_advanced, bg=BGCOL, fg="orange", width=13, anchor=W
196204
)
197205
self._lbl_hae = Label(
198-
self._frm_advanced, bg=BGCOL, fg="orange", width=13, anchor=W
206+
self._frm_advanced,
207+
bg=BGCOL,
208+
fg="orange",
209+
width=13,
210+
anchor=W,
211+
cursor=CLICK_CURSOR,
199212
)
200213
self._lbl_spd = Label(
201214
self._frm_advanced, bg=BGCOL, fg="deepskyblue", width=12, anchor=W
@@ -283,6 +296,8 @@ def _attach_events(self):
283296
"""
284297

285298
self.bind("<Configure>", self._on_resize)
299+
self._lbl_lhae.bind("<Double-Button-1>", self._on_sep)
300+
self._lbl_hae.bind("<Double-Button-1>", self._on_sep)
286301

287302
def _toggle_advanced(self):
288303
"""
@@ -396,7 +411,8 @@ def _update_pos(self, pos_format, units):
396411
self._lbl_llat.config(text="lat:")
397412
self._lbl_llon.config(text="lon:")
398413
self._lbl_lhmsl.config(text="hmsl:")
399-
self._lbl_lhae.config(text="hae:")
414+
lhae = "sep:" if self._sep else "hae:"
415+
self._lbl_lhae.config(text=lhae)
400416
alt_u = "ft" if units in (UI, UIK) else "m"
401417

402418
try:
@@ -423,7 +439,8 @@ def _update_pos(self, pos_format, units):
423439
self._lbl_lat.config(text=f"{lat:{deg_f}}")
424440
self._lbl_lon.config(text=f"{lon:{deg_f}}")
425441
self._lbl_hmsl.config(text=f"{alt:.4f} {alt_u}")
426-
self._lbl_hae.config(text=f"{hae:.4f} {alt_u}")
442+
haev = hae - alt if self._sep else hae
443+
self._lbl_hae.config(text=f"{haev:.4f} {alt_u}")
427444
except (TypeError, ValueError):
428445
self._lbl_lat.config(text=NA)
429446
self._lbl_lon.config(text=NA)
@@ -623,9 +640,18 @@ def _set_fontsize(self):
623640
):
624641
ctl.config(font=scale_font(self.width, FONTBASE - 4, FONTSCALE)[0])
625642

643+
def _on_sep(self, event): # pylint: disable=unused-argument
644+
"""
645+
Toggle hae/sep display.
646+
647+
:param event event: mouse click event
648+
"""
649+
650+
self._sep = not self._sep
651+
626652
def _on_resize(self, event): # pylint: disable=unused-argument
627653
"""
628-
Resize frame
654+
Resize frame.
629655
630656
:param event event: resize event
631657
"""

src/pygpsclient/dynamic_config_frame.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
)
6363

6464
from pygpsclient.globals import (
65+
CLICK_CURSOR,
6566
ERRCOL,
6667
INFOCOL,
6768
NMEA_CFGOTHER,
@@ -207,13 +208,15 @@ def _body(self):
207208
width=50,
208209
command=self._on_set_cfg,
209210
font=self.__app.font_md,
211+
cursor=CLICK_CURSOR,
210212
)
211213
self._btn_refresh = Button(
212214
self,
213215
image=self.__container.img_redraw,
214216
width=40,
215217
command=self._on_refresh,
216218
font=self.__app.font_md,
219+
cursor=CLICK_CURSOR,
217220
)
218221
self._lbl_command = Label(self, text="", anchor=W)
219222
self._frm_container = Frame(self)

src/pygpsclient/globals.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
)
7676
BSR = "backslashreplace"
7777
CLASS = "cls"
78+
CLICK_CURSOR = "hand2" # cursor displayed for clickable widgets
7879
CMDINITDELAY = 3000 # initial delay before sending commands to new connection
7980
CMDPAUSE = 100 # pause between sent commands in ms
8081
COLORTAGS = "colortags"
@@ -247,7 +248,7 @@
247248
SPONSOR_URL = "https://buymeacoffee.com/semuconsulting"
248249
SQRT2 = 0.7071067811865476 # square root of 2
249250
STATUS_PRIORITY = {INFOCOL: 0, "blue": 0, OKCOL: 2, "green": 1, ERRCOL: 3, "red": 3}
250-
STATUS_TIMEOUT = 20 # timeout for stale status messages in seconds
251+
STATUS_TIMEOUT = 15 # timeout for stale status messages in seconds
251252
TIME0 = datetime(1970, 1, 1) # basedate for time()
252253
TIMEOUTS = ("0.1", "0.2", "0.5", "1", "2", "5", "10", "20", "None", "0")
253254
# map nmea talker to gnss_id

src/pygpsclient/gpx_dialog.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from pygpsclient.canvas_subclasses import CanvasGraph
3838
from pygpsclient.globals import (
3939
BGCOL,
40+
CLICK_CURSOR,
4041
CUSTOM,
4142
ERRCOL,
4243
FGCOL,
@@ -170,6 +171,7 @@ def _body(self):
170171
image=self.img_load,
171172
width=40,
172173
command=self._on_load,
174+
cursor=CLICK_CURSOR,
173175
)
174176
self._lbl_maptype = Label(self._frm_controls, text="Map Type")
175177
self._spn_maptype = Spinbox(
@@ -203,6 +205,7 @@ def _body(self):
203205
image=self.img_redraw,
204206
width=40,
205207
command=self._on_redraw,
208+
cursor=CLICK_CURSOR,
206209
)
207210

208211
def _do_layout(self):

src/pygpsclient/importmap_dialog.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from pygpsclient.canvas_map import CanvasMap
4242
from pygpsclient.globals import (
4343
BGCOL,
44+
CLICK_CURSOR,
4445
ERRCOL,
4546
IMPORT,
4647
INFOCOL,
@@ -92,18 +93,21 @@ def _body(self):
9293
image=self.img_load,
9394
width=40,
9495
command=self._on_load,
96+
cursor=CLICK_CURSOR,
9597
)
9698
self._btn_import = Button(
9799
self._frm_controls,
98100
image=self.img_send,
99101
width=40,
100102
command=self._on_import,
103+
cursor=CLICK_CURSOR,
101104
)
102105
self._btn_redraw = Button(
103106
self._frm_controls,
104107
image=self.img_redraw,
105108
width=40,
106109
command=self._on_redraw,
110+
cursor=CLICK_CURSOR,
107111
)
108112
self._chk_first = Checkbutton(
109113
self._frm_controls, text="First?", variable=self._first

0 commit comments

Comments
 (0)