Skip to content

Commit b7dd1f4

Browse files
authored
Merge pull request #254 from semuconsulting/RC-1.6.10
RC 1.6.10
2 parents 58286c2 + 3e1a8ea commit b7dd1f4

7 files changed

Lines changed: 60 additions & 10 deletions

File tree

RELEASE_NOTES.md

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

3+
### RELEASE 1.6.10
4+
5+
1. Minor enhancements to UBX Config Dialog confirmation signalling.
6+
1. Amend CFG-VALSET/GET/DEL Configuration Interface panel; X-type attributes (`X004`, `X008`, etc.) are now entered in
7+
conventional hexadecimal integer notation rather than little-endian hex strings, consistent with values illustrated in the Interface
8+
Specifications e.g. value for CFG_SBAS_PRNSCANMASK (`X008`) would now be entered `0x000000000003ab88` rather than `88ab030000000000`.
9+
1. Make 'Check for update on startup' 'opt-in' rather than 'opt-out'. Setting available via About dialog.
10+
311
### RELEASE 1.6.9
412

513
1. Add manually-editable `resizeable_dialog_b` configuration setting as a workaround for screen scaling issues on some platforms (e.g. Ubuntu Wayland). Fixes #250.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ classifiers = [
5252
dependencies = [
5353
"requests>=2.28.0",
5454
"Pillow>=9.0.0",
55-
"pygnssutils>=1.2.1",
55+
"pygnssutils>=1.2.2",
5656
"pyunigps>=1.0.0",
5757
"pynmeagps>=1.1.4",
58+
"pyubx2>=1.3.1",
5859
]
5960

6061
[project.scripts]

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.9"
11+
__version__ = "1.6.10"

src/pygpsclient/configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def __init__(self, app):
107107
"showsettings_b": 1,
108108
"docksettings_b": 1,
109109
**self.widget_config,
110-
"checkforupdate_b": 1,
110+
"checkforupdate_b": 0,
111111
"transient_dialog_b": 1, # whether pop-up dialogs are on top of main app window
112112
"resizeable_dialog_b": 0, # whether pop-up dialogs are all resizeable
113113
"guiupdateinterval_f": GUI_UPDATE_INTERVAL, # GUI widget update interval in seconds

src/pygpsclient/helpers.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,23 @@ def valid_geom(geom: str) -> bool:
14831483
return regexgeom.match(geom) is not None
14841484

14851485

1486+
def valid_hex(val: str, *args) -> bool:
1487+
"""
1488+
Validate hex string in Entry field.
1489+
1490+
:param str val: hexadecimal value
1491+
:return: Valid/Invalid
1492+
:rtype: bool
1493+
"""
1494+
1495+
try:
1496+
atts = args[0]
1497+
int.to_bytes(int(val, 16), atts, "little")
1498+
return True
1499+
except (TypeError, ValueError, OverflowError):
1500+
return False
1501+
1502+
14861503
def xy2ll(width: int, height: int, bounds: Area, xy: tuple) -> Point | NoneType:
14871504
"""
14881505
Convert canvas x/y to lat/lon.

src/pygpsclient/ubx_cfgval_frame.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
from pygpsclient.globals import (
4343
ERRCOL,
44+
ICON_BLANK,
4445
ICON_CONFIRMED,
4546
ICON_PENDING,
4647
ICON_SEND,
@@ -50,10 +51,12 @@
5051
TRACEMODE_WRITE,
5152
UBX_CFGVAL,
5253
VALBOOL,
54+
VALCUSTOM,
5355
VALFLOAT,
5456
VALINT,
5557
VALNONBLANK,
5658
)
59+
from pygpsclient.helpers import valid_hex
5760

5861
VALSET = 0
5962
VALDEL = 1
@@ -94,6 +97,7 @@ def __init__(self, app: Frame, parent: Frame, *args, **kwargs):
9497
self._img_pending = ImageTk.PhotoImage(Image.open(ICON_PENDING))
9598
self._img_confirmed = ImageTk.PhotoImage(Image.open(ICON_CONFIRMED))
9699
self._img_warn = ImageTk.PhotoImage(Image.open(ICON_WARNING))
100+
self._img_blank = ImageTk.PhotoImage(Image.open(ICON_BLANK))
97101
self._cfgval_cat = None
98102
self._cfgval_keyname = None
99103
self._cfgval_keyid = None
@@ -257,6 +261,7 @@ def reset(self):
257261
for i, cat in enumerate(cdb_cats):
258262
self._lbx_cat.insert(i, cat)
259263
self._cfgmode.set(2)
264+
self._lbl_send_command.config(image=self._img_blank)
260265

261266
def _on_select_mode(self, *args, **kwargs): # pylint: disable=unused-argument
262267
"""
@@ -267,6 +272,7 @@ def _on_select_mode(self, *args, **kwargs): # pylint: disable=unused-argument
267272
self._ent_val.config(state=NORMAL)
268273
else:
269274
self._ent_val.config(state=READONLY)
275+
self._lbl_send_command.config(image=self._img_blank)
270276

271277
def _on_select_cat(self, *args, **kwargs): # pylint: disable=unused-argument
272278
"""
@@ -285,6 +291,7 @@ def _on_select_cat(self, *args, **kwargs): # pylint: disable=unused-argument
285291
self._lbx_parm.insert(idx, keyname)
286292
idx += 1
287293
self._cfgval.set("")
294+
self._lbl_send_command.config(image=self._img_blank)
288295

289296
def _on_select_parm(self, *args, **kwargs): # pylint: disable=unused-argument
290297
"""
@@ -299,6 +306,7 @@ def _on_select_parm(self, *args, **kwargs): # pylint: disable=unused-argument
299306
self._cfgkeyid.set(hex(keyid))
300307
self._cfgatt.set(att)
301308
self._cfgval.set("")
309+
self._lbl_send_command.config(image=self._img_blank)
302310
except TclError:
303311
pass
304312

@@ -307,6 +315,7 @@ def _on_send_config(self, *args, **kwargs): # pylint: disable=unused-argument
307315
Config interface send button has been clicked.
308316
"""
309317

318+
self._lbl_send_command.config(image=self._img_blank)
310319
if self._cfgval_keyname is not None:
311320
if self._cfgmode.get() == VALSET:
312321
self._do_valset()
@@ -341,12 +350,15 @@ def _do_valset(self):
341350
layers = 1
342351
try:
343352
if att in ("C", "X"): # byte or char
344-
self._ent_val.validate(VALNONBLANK)
345-
if len(val) == atts * 2: # 2 hex chars per byte
346-
val = bytearray.fromhex(val)
347-
else:
348-
valid = False
349-
353+
valid = self._ent_val.validate(
354+
VALCUSTOM,
355+
func=valid_hex,
356+
args=[
357+
atts,
358+
],
359+
)
360+
if valid:
361+
val = int.to_bytes(int(val, 16), atts, "little")
350362
elif att in ("E", "U"): # unsigned integer
351363
self._ent_val.validate(VALINT)
352364
val = int(val)
@@ -451,7 +463,9 @@ def update_status(self, msg: UBXMessage): # pylint: disable=unused-argument
451463
val = getattr(msg, self._cfgval_keyname, None)
452464
if val is not None:
453465
if isinstance(val, bytes):
454-
val = val.hex()
466+
atts = attsiz(self._cfgatt.get())
467+
vali = int.from_bytes(val, "little")
468+
val = f"0x{vali:0{atts*2}x}"
455469
self._cfgval.set(val)
456470
self.__container.status_label = ("CFG-VALGET GET message received", OKCOL)
457471

tests/test_static.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
unused_sats,
7878
val2sphp,
7979
valid_geom,
80+
valid_hex,
8081
xy2ll,
8182
)
8283
from pygpsclient.mapquest_handler import (
@@ -963,6 +964,15 @@ def testhdg2yaw(self):
963964
self.assertEqual(hdg2yaw(375.0),15.0)
964965
self.assertEqual(hdg2yaw(715.0),-5.0)
965966

967+
def testvalidhex(self):
968+
969+
self.assertTrue(valid_hex("0x11223344", 4))
970+
self.assertFalse(valid_hex("0x112233zz", 4))
971+
self.assertFalse(valid_hex("0x1122334455667788", 4))
972+
self.assertTrue(valid_hex("0x1122334455667788", 8))
973+
self.assertFalse(valid_hex("asdfttwergazz", 4))
974+
self.assertFalse(valid_hex("", 4))
975+
966976
if __name__ == "__main__":
967977
# import sys;sys.argv = ['', 'Test.testName']
968978
unittest.main()

0 commit comments

Comments
 (0)