Skip to content

Commit b1d48fb

Browse files
committed
add NMEA $PAIR support
1 parent cb1133b commit b1d48fb

File tree

5 files changed

+32
-13
lines changed

5 files changed

+32
-13
lines changed

INSTALLATION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Though by no means mandatory, it is [generally considered best practice](https:/
2626
1. Use different versions of the same package across applications.
2727
1. Keep your application dependencies clean and organized.
2828

29-
Some platforms (e.g. Ubuntu Linux) **enforce** the use of virtual environments via a so-called 'Externally Managed Environment' constraint². Attempting to install a package into the global environment will result in an `error: externally-managed-environment` error.
29+
Some platforms (e.g. Ubuntu Linux and Homebrew-installed Python environments) **enforce** the use of virtual environments via a so-called 'Externally Managed Environment' constraint². Attempting to install a package into the global environment will result in an `error: externally-managed-environment` error.
3030

3131
¹ In practice, 'global' generally means the user's home environment. Installing into the platform's global system environment typically results in a `Defaulting to user installation because normal site-packages is not writeable` warning.
3232

RELEASE_NOTES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ FIXES:
77
1. Fix Chart update issue #210
88
2. Fix Exit button not invoking on_exit() clean up routines (causing any in-progress GPX track recording to be unterminated).
99
3. Fix `IndexError` when loading GPX tracks with no `<time></time>` elements - a synthetic timestamp sequence wil be used instead.
10+
4. Fix incorrect type formatting for some NMEA commands in NMEA Dynamic Configuration panel.
1011

1112
ENHANCEMENTS:
1213

@@ -25,7 +26,9 @@ ENHANCEMENTS:
2526
On Linux platforms which do not support sqlite3 extensions out of the box, it may be possible to compile from source a suitable version of [Python](https://github.com/semuconsulting/PyGPSClient/blob/master/examples/python_compile.sh) and/or [libspatialite](https://github.com/semuconsulting/PyGPSClient/blob/master/examples/libspatialite_compile.sh).
2627
2. BSD 3-Clause license attribution clarified in all modules.
2728
3. Enhance elevation profile and metadata rendering in GPX track viewer. Add support for route and waypoint elements in addition to track.
28-
4. Various minor improvements to file exception handling.
29+
4. Enhance NMEA Dynamic Configuration dialog to support additional NMEA command types, including Quectel proprietary $PAIR (Quectel LC29H/LC79H), Garmin $PGRM, Locosys %PINV (limited) and u-Blox $PUBX (requires pynmeagps>=1.0.53).
30+
5. Add support
31+
5. Various minor improvements to file exception handling.
2932

3033
### RELEASE 1.5.13
3134

src/pygpsclient/dynamic_config_frame.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"""
1818

1919
import logging
20+
import traceback
2021
from tkinter import (
2122
ALL,
2223
END,
@@ -38,7 +39,12 @@
3839
)
3940

4041
from PIL import Image, ImageTk
41-
from pynmeagps import NMEA_PAYLOADS_POLL_PROP, NMEA_PAYLOADS_SET_PROP, NMEAMessage
42+
from pynmeagps import (
43+
NMEA_MSGIDS_PROP,
44+
NMEA_PAYLOADS_POLL_PROP,
45+
NMEA_PAYLOADS_SET_PROP,
46+
NMEAMessage,
47+
)
4248
from pyubx2 import (
4349
POLL,
4450
SET,
@@ -79,6 +85,7 @@
7985

8086
# following CFG types excluded from selection...
8187
CFG_EXCLUDED = (
88+
"LSC", # Locosys - many variants not implemented
8289
"CFG-DAT-NUM", # deprecated
8390
"CFG-GEOFENCE", # 'variable by size' groups not yet implemented - use pyubx2
8491
"CFG-NMEAv0", # deprecated
@@ -194,7 +201,7 @@ def _body(self):
194201
command=self._on_refresh,
195202
font=self.__app.font_md,
196203
)
197-
self._lbl_command = Label(self, text="", anchor=W)
204+
self._lbl_command = Label(self, text="", width=30, anchor=W)
198205
self._frm_container = Frame(self)
199206
self._can_container = Canvas(self._frm_container)
200207
self._frm_attrs = Frame(self._can_container)
@@ -258,7 +265,7 @@ def reset(self):
258265
self._lbx_cfg_cmd.delete(0, END)
259266
if self._protocol == NMEA:
260267
for i, cmd in enumerate(NMEA_PAYLOADS_SET_PROP):
261-
if cmd[0:3] == "QTM" and cmd not in CFG_EXCLUDED:
268+
if cmd not in CFG_EXCLUDED:
262269
self._lbx_cfg_cmd.insert(i, cmd)
263270
else:
264271
for i, cmd in enumerate(UBX_PAYLOADS_SET):
@@ -296,11 +303,15 @@ def _on_select_cfg(self, *args, **kwargs): # pylint: disable=unused-argument
296303
self._expected_response = None
297304
idx = self._lbx_cfg_cmd.curselection()
298305
self._cfg_id = self._lbx_cfg_cmd.get(idx)
299-
self._lbl_command.config(text=self._cfg_id)
300306
if self._protocol == NMEA:
307+
cfgid = self._cfg_id.rsplit("_", 1)[0]
308+
pde = NMEA_MSGIDS_PROP[cfgid].replace("Sets/Gets", "")
309+
pdesc = f"{cfgid} {pde}"
301310
pdic = NMEA_PAYLOADS_SET_PROP[self._cfg_id]
302311
else: # UBX
312+
pdesc = self._cfg_id
303313
pdic = UBX_PAYLOADS_SET[self._cfg_id]
314+
self._lbl_command.config(text=f"{pdesc}")
304315
self._clear_widgets()
305316
self._add_widgets(pdic, 1, 0)
306317
self.update()
@@ -330,6 +341,8 @@ def _on_set_cfg(self, *args, **kwargs): # pylint: disable=unused-argument
330341
# strip off any variant suffix from cfg_id
331342
# e.g. "QTMCFGUART_CURR" -> "QTMCFGUART"
332343
cfg_id = self._cfg_id.rsplit("_", 1)[0]
344+
if cfg_id[0:3] == "UBX": # strip id from msgId
345+
cfg_id = cfg_id[0:3]
333346
msg = NMEAMessage("P", cfg_id, SET, **vals)
334347
penddlg = NMEA_CFGOTHER
335348
pendcfg = ("P" + cfg_id,)
@@ -341,7 +354,7 @@ def _on_set_cfg(self, *args, **kwargs): # pylint: disable=unused-argument
341354

342355
# send message, update status and await response
343356
self.__container.send_command(msg)
344-
# self.logger.debug(f"command {msg.serialize()}")
357+
self.logger.debug(f"command {msg.serialize()}")
345358
self._lbl_send_command.config(image=self._img_pending)
346359
self.__container.set_status(
347360
f"{self._cfg_id} SET message sent",
@@ -351,6 +364,7 @@ def _on_set_cfg(self, *args, **kwargs): # pylint: disable=unused-argument
351364
self._expected_response = SET
352365

353366
except ValueError as err:
367+
self.logger.debug(traceback.format_exc())
354368
self.__container.set_status(
355369
f"INVALID! {nam}, {att}: {err}",
356370
ERRCOL,

src/pygpsclient/helpers.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,13 @@ def stringvar2val(val: str, att: str) -> object:
11271127
:rtype: object (int, float or bytes)
11281128
"""
11291129

1130-
if atttyp(att) in ("E", "I", "L", "U"): # integer
1130+
if att in ("DE", "LA", "LN"): # NMEA float
1131+
val = float(val)
1132+
elif att in ("CH", "DT", "HX", "LAD", "LND", "TM"): # NMEA str, hex
1133+
pass
1134+
elif att == "IN": # NMEA int
1135+
val = int(val)
1136+
elif atttyp(att) in ("E", "I", "L", "U"): # integer
11311137
if val.find(".") != -1: # ignore scaling decimals
11321138
val = val[0 : val.find(".")]
11331139
val = int(val)
@@ -1141,10 +1147,6 @@ def stringvar2val(val: str, att: str) -> object:
11411147
val = bytes(val, "utf-8")
11421148
elif atttyp(att) == "R": # float
11431149
val = float(val)
1144-
elif atttyp(att) in ("IN", "HX"): # NMEA int
1145-
val = int(val)
1146-
elif atttyp(att) in ("DE", "LA", "LN"): # NMEA float
1147-
val = float(val)
11481150

11491151
return val
11501152

src/pygpsclient/map_canvas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ def zoom_bounds(
604604
"""
605605

606606
if location is None:
607-
return
607+
return None
608608
xoff = 90 / 2**zoom
609609
yoff = xoff * height / width
610610
return Area(

0 commit comments

Comments
 (0)