Skip to content

Commit c9a4117

Browse files
authored
Merge pull request #108 from semuconsulting/RELEASE-CANDIDATE-1.4.8
Release candidate 1.4.8
2 parents 3a3a5a4 + 0d7c9e6 commit c9a4117

File tree

11 files changed

+90
-77
lines changed

11 files changed

+90
-77
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"editor.formatOnSave": true,
55
"modulename": "pygpsclient",
66
"distname": "pygpsclient",
7-
"moduleversion": "1.4.7",
7+
"moduleversion": "1.4.8",
88
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ Below is a illustrative SPARTN DGPS data log, showing:
253253

254254
The Socket Server / NTRIP Caster facility is capable of operating in either of two modes;
255255
1. SOCKET SERVER - an open, unauthenticated TCP socket server available to any socket client including, for example, another instance of PyGPSClient or the [`gnssdump` CLI utility](https://github.com/semuconsulting/pygnssutils#gnssdump). In this mode it will broadcast the host's currently connected GNSS data stream (NMEA, UBX, RTCM3). The default port is 50012.
256-
2. NTRIP CASTER - a simple implementation of an authenticated NTRIP caster available to any NTRIP client including, for example, the PyGPSClient NTRIP Client facility or the [`gnssntripclient` CLI utility](https://github.com/semuconsulting/pygnssutils#gnssntripclient). Login credentials for the NTRIP caster are set via the `"ntripclientuser_s":` and `"ntripclientpassword_s":` settings in the *.json confirmation file (they can also be set via PyGPSClient command line arguments `--ntripuser`, `--ntrippassword`, or by setting environment variables `PYGPSCLIENT_USER`, `PYGPSCLIENT_PASSWORD`). Default settings are as follows: bind address: 0.0.0.0, port: 2101, mountpoint: pygnssutils, user: anon, password: password.
256+
2. NTRIP CASTER - a simple implementation of an authenticated NTRIP caster available to any NTRIP client including, for example, the PyGPSClient NTRIP Client facility or the [`gnssntripclient` CLI utility](https://github.com/semuconsulting/pygnssutils#gnssntripclient). Login credentials for the NTRIP caster are set via the `"ntripcasteruser_s":` and `"ntripcasterpassword_s":` settings in the *.json confirmation file (they can also be set via PyGPSClient command line arguments `--ntripcasteruser`, `--ntripcasterpassword`, or by setting environment variables `NTRIPCASTER_USER`, `NTRIPCASTER_PASSWORD`). Default settings are as follows: bind address: 0.0.0.0, port: 2101, mountpoint: pygnssutils, user: anon, password: password.
257257

258258
By default, the server/caster binds to the host address '0.0.0.0' (IPv4) or '::' (IPv6) i.e. all available IP addresses on the host machine. This can be overridden via the settings panel or a host environment variable `PYGPSCLIENT_BINDADDRESS`. A label on the settings panel indicates the number of connected clients, and the server/caster status is indicated in the topmost banner: running with no clients: ![transmit icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-noclient-10-24.png?raw=true), running with clients: ![transmit icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-transmit-10-24.png?raw=true).
259259

@@ -389,7 +389,7 @@ To run the application, if the Python 3 scripts (bin) directory is in your PATH,
389389
pygpsclient
390390
```
391391

392-
`pygpsclient` also accepts optional command line arguments for a variety of configurable parameters. Type the following for help:
392+
`pygpsclient` also accepts optional command line arguments for a variety of configurable parameters. These will override any saved configuration file settings. Type the following for help:
393393
```shell
394394
pygpsclient -h
395395
```

RELEASE_NOTES.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# PyGPSClient Release Notes
22

3-
### RELEASE CANDIDATE v1.4.7
3+
### RELEASE CANDIDATE v1.4.8
4+
5+
FIXES:
6+
7+
1. Fix parsing of command line arguments (NB: command line arguments and/or environment variables will now take temporary precedence over saved config file settings)
8+
1. Fix 'unhashable type' error when first displaying mountpoint data in NTRIP client panel
9+
10+
### RELEASE v1.4.7
411

512
ENHANCEMENTS:
613

@@ -374,7 +381,7 @@ ENHANCEMENTS:
374381

375382
1. **New BETA Socket / NTRIP Server feature**. Capable of operating in two modes - either (a) as an open, unauthenticated TCP socket server, or (b) as an authenticated NTRIP server.
376383
3. In open socket server mode, the output socket stream can be accessed by any TCP socket client capable of parsing raw GNSS data, including another instance of PyGPSClient or `gnssdump` (the CLI utility installed with `pyubx2`) running on another machine (*assuming the traffic is permitted through any firewalls*).
377-
4. In NTRIP server mode, the socket stream can be accessed by any authenticated NTRIP client. The sourcetable contains a single entry corresponding to the PyGPSClient host. The server authentication credentials are set via two environment variables `PYGPSCLIENT_USER` and `PYGPSCLIENT_PASSWORD`.
384+
4. In NTRIP server mode, the socket stream can be accessed by any authenticated NTRIP client. The sourcetable contains a single entry corresponding to the PyGPSClient host. The server authentication credentials are set via two environment variables `NTRIPCASTER_USER` and `NTRIPCASTER_PASSWORD`.
378385
5. In either mode, the maximum number of clients is arbitrarily limited to 5. A label on the settings panel indicates the number of connected clients - this turns red when the maximum has been reached.
379386
6. The socket host address is `0.0.0.0` (i.e. binds to all available IP addresses on the host machine). The socket port defaults to `50010` but is configurable via the settings panel (`2101` is the convention for NTRIP servers but is not mandated).
380387
7. The default configuration for the socket server is set in `globals.py` as `SOCKSERVER_HOST`, `SOCKSERVER_PORT` and `SOCKSERVER_MAX_CLIENTS`.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "pygpsclient"
77
authors = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }]
88
maintainers = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }]
99
description = "GNSS Diagnostic and UBX Configuration GUI Application"
10-
version = "1.4.7"
10+
version = "1.4.8"
1111
license = { file = "LICENSE" }
1212
keywords = [
1313
"PyGPSClient",

src/pygpsclient/__main__.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515

1616
from pygpsclient._version import __version__ as VERSION
1717
from pygpsclient.app import App
18-
from pygpsclient.globals import CONFIGFILE, EPILOG
18+
from pygpsclient.globals import (
19+
CONFIGFILE,
20+
DEFAULT_PASSWORD,
21+
DEFAULT_REGION,
22+
DEFAULT_USER,
23+
EPILOG,
24+
)
1925

2026

2127
def main():
@@ -24,14 +30,14 @@ def main():
2430
arp = ArgumentParser(
2531
epilog=EPILOG,
2632
formatter_class=ArgumentDefaultsHelpFormatter,
27-
description="Config file will override other command line arguments",
33+
description="Command line arguments will override configuration file",
2834
)
2935
arp.add_argument("-V", "--version", action="version", version="%(prog)s " + VERSION)
3036
arp.add_argument(
3137
"-C",
3238
"--config",
3339
required=False,
34-
help="Fully-qualified path to config file",
40+
help="Fully-qualified path to configuration file",
3541
default=CONFIGFILE,
3642
)
3743
arp.add_argument(
@@ -64,7 +70,7 @@ def main():
6470
"--mqttclientregion",
6571
required=False,
6672
help="MQTT Client Region",
67-
default=getenv("MQTTCLIENTREGION", "eu"),
73+
default=getenv("MQTTCLIENTREGION", DEFAULT_REGION),
6874
)
6975
arp.add_argument(
7076
"--mqttclientmode",
@@ -73,16 +79,16 @@ def main():
7379
default=getenv("MQTTCLIENTMODE", "0"),
7480
)
7581
arp.add_argument(
76-
"--ntripuser",
82+
"--ntripcasteruser",
7783
required=False,
7884
help="NTRIP Caster authentication user",
79-
default=getenv("PYGPSCLIENT_USER", "anon"),
85+
default=getenv("NTRIPCASTER_USER", DEFAULT_USER),
8086
)
8187
arp.add_argument(
82-
"--ntrippassword",
88+
"--ntripcasterpassword",
8389
required=False,
8490
help="NTRIP Caster authentication password",
85-
default=getenv("PYGPSCLIENT_PASSWORD", "password"),
91+
default=getenv("NTRIPCASTER_PASSWORD", DEFAULT_PASSWORD),
8692
)
8793

8894
kwargs = vars(arp.parse_args())

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.4.7"
11+
__version__ = "1.4.8"

src/pygpsclient/app.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
CLASS,
4545
CONFIGFILE,
4646
CONNECTED,
47+
DEFAULT_PASSWORD,
48+
DEFAULT_REGION,
49+
DEFAULT_USER,
4750
DISCONNECTED,
4851
DLG,
4952
DLGTNTRIP,
@@ -124,23 +127,23 @@ def __init__(self, master, *args, **kwargs): # pylint: disable=too-many-stateme
124127
# user-defined serial port can be passed as environment variable
125128
# or command line keyword argument
126129
self._configfile = kwargs.pop("config", CONFIGFILE)
127-
self.user_port = kwargs.pop("userport", getenv("PYGPSCLIENT_USERPORT", ""))
128-
self.spartn_user_port = kwargs.pop(
130+
user_port = kwargs.pop("userport", getenv("PYGPSCLIENT_USERPORT", ""))
131+
spartn_user_port = kwargs.pop(
129132
"spartnport", getenv("PYGPSCLIENT_SPARTNPORT", "")
130133
)
131-
self.mqapikey = kwargs.pop("mqapikey", getenv("MQAPIKEY", ""))
132-
self.mqttclientid = kwargs.pop("mqttclientid", getenv("MQTTCLIENTID", ""))
133-
self.mqttclientregion = kwargs.pop(
134-
"mqttclientregion", getenv("MQTTCLIENTREGION", "eu")
134+
mqapikey = kwargs.pop("mqapikey", getenv("MQAPIKEY", ""))
135+
mqttclientid = kwargs.pop("mqttclientid", getenv("MQTTCLIENTID", ""))
136+
mqttclientregion = kwargs.pop(
137+
"mqttclientregion", getenv("MQTTCLIENTREGION", DEFAULT_REGION)
135138
)
136-
self.mqttclientmode = int(
139+
mqttclientmode = int(
137140
kwargs.pop("mqttclientmode", getenv("MQTTCLIENTMODE", "0"))
138141
)
139-
self.ntripcaster_user = kwargs.pop(
140-
"ntripuser", getenv("PYGPSCLIENT_USER", "anon")
142+
ntripcaster_user = kwargs.pop(
143+
"ntripcasteruser", getenv("NTRIPCASTER_USER", DEFAULT_USER)
141144
)
142-
self.ntripcaster_password = kwargs.pop(
143-
"ntrippassword", getenv("PYGPSCLIENT_USER", "password")
145+
ntripcaster_password = kwargs.pop(
146+
"ntripcasterpassword", getenv("NTRIPCASTER_PASSWORD", DEFAULT_PASSWORD)
144147
)
145148

146149
Frame.__init__(self, self.__master, *args, **kwargs)
@@ -168,7 +171,6 @@ def __init__(self, master, *args, **kwargs): # pylint: disable=too-many-stateme
168171
self.rtcm_handler = RTCM3Handler(self)
169172
self.ntrip_handler = GNSSNTRIPClient(self, verbosity=0)
170173
self.spartn_handler = GNSSMQTTClient(self, verbosity=0)
171-
self.saved_config = {}
172174
self._conn_status = DISCONNECTED
173175
self._rtk_conn_status = DISCONNECTED
174176
self._socket_thread = None
@@ -179,13 +181,30 @@ def __init__(self, master, *args, **kwargs): # pylint: disable=too-many-stateme
179181
# Load configuration from file if it exists
180182
self._colortags = []
181183
self._ubxpresets = []
184+
self.saved_config = {}
182185
(_, config, configerr) = self.file_handler.load_config(self._configfile)
183186
if configerr == "": # load succeeded
184187
self.saved_config = config
185188
# update configs needed to instantiate widgets and protocol handlers
186189
self.update_widgets()
187-
else: # load failed - invalid json or attribute types
188-
self.saved_config = {}
190+
191+
# temporarily override saved config with any command line arguments / env variables
192+
if user_port != "":
193+
self.saved_config["userport_s"] = user_port
194+
if spartn_user_port != "":
195+
self.saved_config["spartnport_s"] = spartn_user_port
196+
if mqapikey != "":
197+
self.saved_config["mqapikey_s"] = mqapikey
198+
if mqttclientid != "":
199+
self.saved_config["mqttclientid_s"] = mqttclientid
200+
if mqttclientregion != DEFAULT_REGION:
201+
self.saved_config["mqttclientregion_s"] = mqttclientregion
202+
if mqttclientmode != 0:
203+
self.saved_config["mqttclientmode_n"] = mqttclientmode
204+
if ntripcaster_user != DEFAULT_USER:
205+
self.saved_config["ntripcasteruser_s"] = ntripcaster_user
206+
if ntripcaster_password != DEFAULT_PASSWORD:
207+
self.saved_config["ntripcasterpassword_s"] = ntripcaster_password
189208

190209
# update NTRIP and SPARTN client handlers with initial config
191210
self.update_NTRIP_handler()
@@ -497,10 +516,10 @@ def update_NTRIP_handler(self):
497516
"ntripclientversion_s", "2.0"
498517
)
499518
ntripsettings["ntripuser"] = self.saved_config.get(
500-
"ntripclientuser_s", "anon"
519+
"ntripclientuser_s", DEFAULT_USER
501520
)
502521
ntripsettings["ntrippassword"] = self.saved_config.get(
503-
"ntripclientpassword_s", "password"
522+
"ntripclientpassword_s", DEFAULT_PASSWORD
504523
)
505524
ntripsettings["ggainterval"] = self.saved_config.get(
506525
"ntripclientggainterval_n", -1
@@ -530,15 +549,11 @@ def update_SPARTN_handler(self):
530549
spartnsettings["port"] = self.saved_config.get(
531550
"mqttclientport_n", SPARTN_OUTPORT
532551
)
533-
spartnsettings["clientid"] = self.saved_config.get(
534-
"mqttclientid_s", self.mqttclientid
535-
)
552+
spartnsettings["clientid"] = self.saved_config.get("mqttclientid_s", "")
536553
spartnsettings["region"] = self.saved_config.get(
537-
"mgttclientregion_s", self.mqttclientregion
538-
)
539-
spartnsettings["mode"] = self.saved_config.get(
540-
"mgttclientmode_n", self.mqttclientmode
554+
"mgttclientregion_s", DEFAULT_REGION
541555
)
556+
spartnsettings["mode"] = self.saved_config.get("mgttclientmode_n", 0)
542557
spartnsettings["topic_ip"] = self.saved_config.get("mgttclienttopicip_b", 1)
543558
spartnsettings["topic_mga"] = self.saved_config.get(
544559
"mgttclienttopicmga_b", 1
@@ -548,11 +563,11 @@ def update_SPARTN_handler(self):
548563
)
549564
spartnsettings["tlscrt"] = self.saved_config.get(
550565
"mgttclienttlscrt_s",
551-
path.join(Path.home(), f"device-{self.mqttclientid}-pp-cert.crt"),
566+
path.join(Path.home(), "device-mqttclientid-pp-cert.crt"),
552567
)
553568
spartnsettings["tlskey"] = self.saved_config.get(
554569
"mgttclienttlskey_s",
555-
path.join(Path.home(), f"device-{self.mqttclientid}-pp-key.pem"),
570+
path.join(Path.home(), "device-mqttclientid-pp-key.pem"),
556571
)
557572
spartnsettings["output"] = self.spartn_inqueue
558573
self.spartn_handler.settings = spartnsettings
@@ -756,7 +771,11 @@ def on_ntrip_read(self, event): # pylint: disable=unused-argument
756771

757772
try:
758773
raw_data, parsed_data = self.ntrip_inqueue.get(False)
759-
if raw_data is not None and parsed_data is not None:
774+
if (
775+
raw_data is not None
776+
and parsed_data is not None
777+
and isinstance(raw_data, bytes)
778+
):
760779
if protocol(raw_data) == RTCM3_PROTOCOL:
761780
if self.conn_status == CONNECTED:
762781
self.gnss_outqueue.put(raw_data)

src/pygpsclient/globals.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@
6060
CRLF = b"\x0d\x0a"
6161
DDD = "DD.D"
6262
DEFAULT_BUFSIZE = 4096
63+
DEFAULT_PASSWORD = "password" # nosec
6364
DEFAULT_PORT = 50010
65+
DEFAULT_REGION = "eu"
6466
DEFAULT_SERVER = "localhost"
67+
DEFAULT_USER = "anon"
6568
DIRNAME = path.dirname(__file__)
6669
DISCONNECTED = 0
6770
DLG = "dlg"

src/pygpsclient/scatter_frame.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
PLANAR = "Planar"
2929
HAVERSINE = "Great Circle"
3030
SQRT2 = 0.7071067811865476
31+
PNTCOL = "orange"
3132

3233

3334
class ScatterViewFrame(Frame):
@@ -50,7 +51,6 @@ def __init__(self, app, *args, **kwargs):
5051

5152
def_w, def_h = WIDGETU2
5253

53-
self.dot_col = "orange"
5454
self.width = kwargs.get("width", def_w)
5555
self.height = kwargs.get("height", def_h)
5656
self.fg_col = FGCOL
@@ -148,17 +148,15 @@ def _draw_mean(self, lbl_font: font):
148148
height = lbl_font.metrics("linespace")
149149
lat = f"Lat {self.mean.lat:14.10f}"
150150
lon = f"Lon {self.mean.lon:15.10f}"
151+
self.canvas.create_text(5, 10, text=lat, fill=PNTCOL, font=lbl_font, anchor="w")
151152
self.canvas.create_text(
152-
5, 10, text=lat, fill=self.fg_col, font=lbl_font, anchor="w"
153-
)
154-
self.canvas.create_text(
155-
5, 10 + height, text=lon, fill=self.fg_col, font=lbl_font, anchor="w"
153+
5, 10 + height, text=lon, fill=PNTCOL, font=lbl_font, anchor="w"
156154
)
157155
self.canvas.create_text(
158156
5,
159157
10 + height * 2,
160158
text=self._calc,
161-
fill=self.fg_col,
159+
fill=PNTCOL,
162160
font=lbl_font,
163161
anchor="w",
164162
)
@@ -220,9 +218,7 @@ def draw_point(self, center: Point, position: Point):
220218
center_y = self.height / 2
221219
pt_x = center_x + pos_x
222220
pt_y = center_y - pos_y
223-
self.canvas.create_circle(
224-
pt_x, pt_y, 2, fill=self.dot_col, outline=self.dot_col
225-
)
221+
self.canvas.create_circle(pt_x, pt_y, 2, fill=PNTCOL, outline=PNTCOL)
226222

227223
def _ave_pos(self):
228224
"""

src/pygpsclient/serverconfig_frame.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
from pyubx2 import UBXMessage, llh2ecef
4242

4343
from pygpsclient.globals import (
44+
DEFAULT_PASSWORD,
45+
DEFAULT_USER,
4446
DISCONNECTED,
4547
ICON_CONTRACT,
4648
ICON_EXPAND,
@@ -406,18 +408,10 @@ def reset(self):
406408
self.fixedlon.set(self._saved_config.get("ntripcasterfixedlon_f", 0))
407409
self.fixedalt.set(self._saved_config.get("ntripcasterfixedalt_f", 0))
408410
self.user.set(
409-
self._saved_config.get(
410-
"ntripcasteruser_s",
411-
self._saved_config.get("ntripcasteruser", self.__app.ntripcaster_user),
412-
)
411+
self._saved_config.get("ntripcasteruser_s", DEFAULT_USER),
413412
)
414413
self.password.set(
415-
self._saved_config.get(
416-
"ntripcasterpassword_s",
417-
self._saved_config.get(
418-
"ntripcasterpassword", self.__app.ntripcaster_password
419-
),
420-
)
414+
self._saved_config.get("ntripcasterpassword_s", DEFAULT_PASSWORD),
421415
)
422416
self.clients = 0
423417
self._sock_port_temp = self.sock_port.get()

0 commit comments

Comments
 (0)