diff --git a/INSTALLATION.md b/INSTALLATION.md index d9c8e920..180c37f4 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -115,7 +115,7 @@ sudo pacman -S tk libspatialite To access the serial port (`/dev/tty*`) on most Linux platforms, you will need to be a member of whichever group or "`Gid`" the `/dev/tty*` device belongs to. Failure to do this will typically result in an error `[Errno 13] could not open port /dev/ttyACM0 [Errno 13] permission denied /dev/ttyACM0` -To check and set the necessary group permissions (*substitute* `ttyACM0` *for your particular serial port*): +To check and set the necessary group permissions (*substitute your particular serial port for* `ttyACM0`): ```shell stat /dev/ttyACM0 | grep Gid @@ -148,6 +148,7 @@ source pygpsclient/bin/activate # (or .\pygpsclient\Scripts\activate on Windows) python3 -m pip install --upgrade pygpsclient pygpsclient ``` +**NB**: It is recommended to use the form `python3 -m pip install` (*or less ambiguously `python3.*`, where `*` is the Python minor version e.g. `python3.13`*) rather than simply `pip3 install`, particularly if you have multiple Python environments on your platform. To deactivate the virtual environment: diff --git a/README.md b/README.md index 0e662ba6..e3bbd44b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [TTY Commands](#ttycommands) | [Load/Save/Record Commands](#recorder) | [NTRIP Client](#ntripconfig) | -[Socket Server / NTRIP Caster](#socketserver) | +[NTRIP Caster/Socket Server](#socketserver) | [GPX Track Viewer](#gpxviewer) | [Mapquest API Key](#mapquestapi) | [User-defined Presets](#userdefined) | @@ -23,7 +23,7 @@ PyGPSClient is a free, open-source, multi-platform graphical GNSS/GPS testing, d * Supports NMEA, UBX (u-blox binary), SBF (Septentrio binary), UNI (Unicore binary), QGC (Quectel binary), RTCM3, NTRIP, SPARTN, MQTT and TTY (ASCII) protocols¹. * 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). * Provides [NTRIP](#ntripconfig) client facilities. -* 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). +* 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 G5/X5 or Unicore UM9** Series). * 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. * Can be installed using the standard `pip` Python package manager - see [installation instructions](#installation) below. @@ -40,7 +40,7 @@ This is an independent project and we have no affiliation whatsoever with any GN 1. [Glossary of GNSS Terms and Abbreviations](https://www.semuconsulting.com/gnsswiki/glossary/). 1. [GNSS Positioning - A Reviser](https://www.semuconsulting.com/gnsswiki/) - a general overview of GNSS, OSR, SSR, RTK, NTRIP and SPARTN positioning and error correction technologies and terminology. 1. [Achieving cm Level GNSS Accuracy using RTK](https://www.semuconsulting.com/gnsswiki/rtktips/) - practical tips on high precision RTK using PyGPSClient. -1. From time to time, instructional videos may be posted to the [semuadmin YouTube channel](https://www.youtube.com/@semuadmin). +1. From time to time, instructional videos may be posted to the [semuadmin YouTube channel](https://www.youtube.com/@semuadmin). [Sparkfun](https://www.sparkfun.com/gnss.html) have also published a number of [RTK tutorial YouTube videos](https://www.youtube.com/watch?v=nO1IznPGGtk) using PyGPSClient running on a Raspberry Pi. 1. [Sphinx API Documentation](https://www.semuconsulting.com/pygpsclient) in HTML format. --- @@ -102,68 +102,76 @@ For more comprehensive installation instructions, please refer to [INSTALLATION. #### Settings panel 1. By default, the Settings panel is displayed to the right of the main application window. It can be hidden or shown via Menu..View..Hide/Show Settings. The panel can also be 'undocked' from the main application window via Menu..View..Undock Settings and - if [non-transient](#transient) (`transient_dialog_b: 0`) - minimized independently of the main window. Exiting the undocked dialog, or selecting Menu..View..Dock Settings, will 'dock' the panel. -1. To connect to a GNSS receiver via USB or UART port, select the device from the listbox, set the appropriate serial connection parameters and click -![connect icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/usbport-1-24.png?raw=true). The application will endeavour to pre-select a recognised GNSS/GPS device but this is platform and device dependent. Press the ![refresh](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-refresh-6-16.png?raw=true) button to refresh the list of connected devices at any point. `Rate bps` (baud rate) is typically the only setting that might need adjusting, but tweaking the `timeout` setting may improve performance on certain platforms. The `Msg Mode` parameter defaults to `GET` i.e., periodic or poll response messages *from* a receiver. If you wish to parse streams of command or poll messages being sent *to* a receiver, set the `Msg Mode` to `SET` or `POLL`. An optional serial or socket stream inactivity timeout can also be set (in seconds; 0 = no timeout). - - If you get a permissions error on attempting to connect to a serial port e.g. `[Errno 13] permission denied /dev/ttyACM0`, refer to the [Installation Guidelines - User Privileges](https://github.com/semuconsulting/PyGPSClient/blob/master/INSTALLATION.md#user-privileges). -1. A custom user-defined serial port can also be passed via the json configuration file setting `"userport_s":`, via environment variable `PYGPSCLIENT_USERPORT` or as a command line argument `--userport`. A special userport value of "ubxsimulator" invokes the experimental [`pyubxutils.UBXSimulator`](https://github.com/semuconsulting/pyubxutils/blob/main/src/pyubxutils/ubxsimulator.py) utility to emulate a GNSS NMEA/UBX serial stream. -1. To connect to a TCP or UDP socket, enter the server URL and port, select the protocol (defaults to TCP) and click +2. Protocols Shown - Select which message protocols to display in the console; 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). + - **NB:** Serial connection must be stopped before changing to or from TTY (terminal) protocol. + - **NB:** Enabling TTY (terminal) mode will disable all other protocols. +3. To connect to a GNSS receiver via USB or UART port, select the device from the listbox, set the appropriate serial connection parameters and click +![connect icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/usbport-1-24.png?raw=true). The application will endeavour to pre-select a recognised GNSS/GPS device but this is platform and device dependent. Press the ![refresh](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-refresh-6-16.png?raw=true) button to refresh the list of connected devices at any point. + - `Rate bps` (baud rate) is typically the only setting that might need adjusting, but tweaking the `timeout` setting may improve performance on certain platforms. + - When the connection is first established, PyGPSClient will poll various hardware information messages (*one for each selected protocol*) to the receiver in an attempt to establish its model and firmware version. You may see a handful of 'unknown protocol' warnings in response to some of these queries - these can be disregarded. **NB:** Some receivers will not output hardware information messages at low baud rates (<38,400). + - If you get a permissions error on attempting to connect to a serial port e.g. `[Errno 13] permission denied /dev/ttyACM0`, refer to the [Installation Guidelines - User Privileges](https://github.com/semuconsulting/PyGPSClient/blob/master/INSTALLATION.md#user-privileges). + - The `Msg Mode` parameter defaults to `GET` i.e., periodic or poll response messages *from* a receiver. If you wish to parse streams of command or poll messages being sent *to* a receiver, set the `Msg Mode` to `SET` or `POLL`. An optional serial or socket stream inactivity timeout can also be set (in seconds; 0 = no timeout). +4. A custom user-defined serial port can also be passed via the json configuration file setting `"userport_s":`, via environment variable `PYGPSCLIENT_USERPORT` or as a command line argument `--userport`. A special userport value of "ubxsimulator" invokes the experimental [`pyubxutils.UBXSimulator`](https://github.com/semuconsulting/pyubxutils/blob/main/src/pyubxutils/ubxsimulator.py) utility to emulate a GNSS NMEA/UBX serial stream. +5. To connect to a TCP or UDP socket, enter the server URL and port, select the protocol (defaults to TCP) and click ![connect socket icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/ethernet-1-24.png?raw=true). For encrypted TLS connections, tick the 'TLS' checkbox. Tick the 'Self Sign' checkbox to accommodate self-signed TLS certification (*typically for test or demonstration services*). -1. To stream from a previously-saved binary datalog file, click +6. To stream from a previously-saved binary datalog file, click ![connect-file icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/binary-1-24.png?raw=true) and select the file type (`*.log, *.ubx, *.*`) and path. PyGPSClient datalog files will be named e.g. `pygpsdata-20220427114802.log`, but any binary dump of an GNSS receiver output is acceptable, including `*.ubx` files produced by u-center. The 'File Delay' spinbox sets the delay in milliseconds between individual file reads, acting as a throttle on file readback. -1. To disconnect from the data stream, click +7. To disconnect from the data stream, click ![disconnect icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-media-control-50-24.png?raw=true). -1. To immediately disconnect and terminate all running threads, click Ctrl-K ("Kill Switch"). -1. To exit the application, click +8. To immediately disconnect and terminate all running threads, click Ctrl-K ("Kill Switch"). +9. To exit the application, click ![exit icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-poweroff-8-24.png?raw=true), or press Ctrl-Q, or click the application window's close window icon. -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). - - **NB:** Serial connection must be stopped before changing to or from TTY (terminal) protocol. - - **NB:** Enabling TTY (terminal) mode will disable all other protocols. -1. Console Display - Select console display format (Parsed, Binary, Hex Tabular, Hex String, Parsed+Hex Tabular - see Console Widget below). -1. Maxlines - Select number of scrollable lines retained in console. -1. File Delay - Select delay in milliseconds between individual reads when streaming from binary file (default 20 milliseconds). -1. Tags - Enable color tags in console (see Console Widget below). -1. Position Format and Units - Change the displayed position (D.DD / D.M.S / D.M.MM / ECEF) and unit (metric/imperial) formats. -1. DataLogging - Turn Data logging in the selected format (Binary, Parsed, Hex Tabular, Hex String, Parsed+Hex Tabular) on or off. On first selection, you will be prompted to select the directory into which timestamped log files are saved. Log files are cycled when a maximum size is reached (default is 10 MB, manually configurable via `logsize_n` setting). -1. GPX Track - Turn track recording (in GPX format) on or off. On first selection, you will be prompted to select the directory into which timestamped GPX track files are saved. -1. Database - Turn spatialite database recording (*where available*) on or off. On first selection, you will be prompted to select the directory into which the `pygpsclient.sqlite` database is saved. Note that, when first created, the database's spatial metadata will take a few seconds to initialise (*up to a minute on Raspberry Pi and similar SBC*). **NB** This facility is dependent on your Python environment supporting the requisite [sqlite3 `mod_spatialite` extension](https://www.gaia-gis.it/fossil/libspatialite/index) - see [INSTALLATION.md](https://github.com/semuconsulting/PyGPSClient/blob/master/INSTALLATION.md#prereqs) for further details. If not supported, the option will be greyed out. Check the Menu..Help..About dialog for an indication of the current spatialite support status. - - *FYI* a helper method `retrieve_data()` is available to retrieve data from this database - see [Sphinx documentation](https://www.semuconsulting.com/pygpsclient/pygpsclient.html#pygpsclient.sqllite_handler.retrieve_data) and [retrieve_data.py](https://github.com/semuconsulting/PyGPSClient/blob/master/examples/retrieve_data.py) example for details. -1. To save the current configuration to a file, go to File..Save Configuration. -1. To load a saved configuration file, go to File..Load Configuration. The default configuration file location is `$HOME/pygpsclient.json`. -**NB** Any active serial or RTK connection must be stopped before loading a new configuration. -1. [UBX Configuration Dialog](#ubxconfig), with the ability to send a variety of UBX CFG configuration commands to u-blox GNSS devices. This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the UBX Configuration Dialog (*only functional when connected to a UBX GNSS device via serial port*), click -![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-ubx.png?raw=true), or go to Menu..Options..UBX Configuration Dialog. -1. [NMEA Configuration Dialog](#nmeaconfig), with the ability to send a variety of NMEA configuration commands to GNSS devices (e.g. Quectel LG290P). This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the NMEA Configuration Dialog (*only functional when connected to a compatible GNSS device via serial port*), click ![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-nmea.png?raw=true), or go to Menu..Options..NMEA Configuration Dialog. -1. [TTY Config Dialog](#ttycommands), with the ability to send a variety of TTY (ASCII) configuration commands to GNSS and related devices (e.g. Septentrio X5, Unicore UM980). This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the TTY Commands Dialog (*only functional when connected to a compatible GNSS device via serial port*), click -![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-tty.png?raw=true), or go to Menu..Options..TTY Commands. -1. [NTRIP Client](#ntripconfig) facility with the ability to connect to a specified NTRIP caster, parse the incoming RTCM3 or SPARTN data and feed this data to a compatible GNSS receiver (*requires an Internet connection and access to an NTRIP caster and local mountpoint*). To display the NTRIP Client Configuration Dialog, click -![ntrip icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-antenna-4-24.png?raw=true), or go to Menu..Options..NTRIP Configuration Dialog. -1. [Server Config](#socketserver) facility with the ability to act as generic socket server or NTRIP caster (mountpoint = `pygnssutils`). To display the Server Configuration Dialog, click -![server icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-transmit-10-24.png?raw=true), or go to Menu..Options..Server Configuration Dialog. -1. [SPARTN Client](#spartnconfig) facility with the ability to configure an IP or L-Band SPARTN Correction source and SPARTN-compatible GNSS receiver (e.g. ZED-F9P) and pass the incoming correction data to the GNSS receiver (*requires an Internet connection and access to a SPARTN location service*). To display the SPARTN Client Configuration Dialog, go to Menu..Options..SPARTN Configuration Dialog. -1. [GPX Track Viewer](#gpxviewer) utility with elevation and speed profiles and track metadata. To display the GPX Track viewer, go to Menu..Options..GPX Track Viewer. +10. Console Display - Select console display format (Parsed, Binary, Hex Tabular, Hex String, Parsed+Hex Tabular - see Console Widget below). +11. Maxlines - Select number of scrollable lines retained in console. +12. File Delay - Select delay in milliseconds between individual reads when streaming from binary file (default 20 milliseconds). +13. Tags - Enable color tags in console (see Console Widget below). +14. Position Format and Units - Change the displayed position (D.DD / D.M.S / D.M.MM / ECEF) and unit (metric / imperial / maritime) formats. #### Saving and loading configuration settings -- Configuration settings for PyGPSClient can be saved and recalled via the Menu..File..Save/Load Configuration options. By default, PyGPSClient will look for a file named `pygpsclient.json` in the user's home directory. Certain configuration settings require manual editing e.g. custom preset UBX, NMEA and TTY commands and tag colour schemes - see details below. -- It is recommended to re-save the configuration settings after each PyGPSClient version update, or if you see the warning "Consider re-saving" on startup. -- PyGPSClient will prompt you to stop all running input and output streams before loading a new configuration. +15. Configuration settings for PyGPSClient can be saved and recalled via the Menu..File..Save/Load Configuration options. By default, PyGPSClient will look for a file named `pygpsclient.json` in the user's home directory. Certain configuration settings require manual editing e.g. custom preset UBX, NMEA and TTY commands and tag colour schemes - see details below. + - It is recommended to re-save the configuration settings after each PyGPSClient version update, or if you see the warning "Consider re-saving" on startup. + - PyGPSClient will prompt you to stop all running input and output streams before loading a new configuration. + - Any active serial or RTK connection must be stopped before loading a new configuration. -#### Toplevel ('pop-up') dialog setting +#### Checking for the latest version -- The behaviour of Toplevel ('pop-up') dialogs will depend on the screen resolution and 'transient' setting. If the width or height of a Toplevel dialog exceeds the screen resolution, the dialog will be displayed in a scrollable, resizeable window. Otherwise, the dialog is displayed as a fixed, non-resizeable panel. -- A boolean configuration setting `transient_dialog_b` governs whether Toplevel dialogs are 'transient' (i.e. always on top of main application dialog) or not. Changing this setting to `0` allows Toplevel dialogs to be minimised independently of the main application window, but be mindful that some dialogs may end up hidden behind others e.g. "Open file/folder" dialogs. **If a file open button appears unresponsive, check that the "Open file/folder" panel isn't already open but obscured**. -- If you're accessing the desktop via a VNC session (e.g. to a headless Raspberry Pi) it is recommended to keep the setting at the default `1`, as VNC may not recognise keystrokes on overlaid non-transient windows. +16. The About dialog (Menu..Help..About) includes a facility to check the latest available versions of PyGPSClient and its subsidiary modules, and initiate an automatic update. Tick the 'Check on startup' box to perform this check on startup (*note that this requires internet access, which may result in slower startup times on platforms with low bandwidth / high latency internet connections*). The facility may be unavailable in certain Homebrew-installed Python environments due to technical constraints. + - The application must be closed and restarted for any update to take effect. -#### Checking for the latest version +#### Datalogging, GPX Track Recording and Database -- The About dialog (Menu..Help..About) includes a facility to check the latest available versions of PyGPSClient and its subsidiary modules, and initiate an automatic update. Tick the 'Check on startup' box to perform this check on startup (*note that this requires internet access, which may result in slower startup times on platforms with low bandwidth / high latency internet connections*). The facility may be unavailable in certain Homebrew-installed Python environments due to technical constraints. +17. DataLogging - Turn Data logging in the selected format (Binary, Parsed, Hex Tabular, Hex String, Parsed+Hex Tabular) on or off. On first selection, you will be prompted to select the directory into which timestamped log files are saved. Log files are cycled when a maximum size is reached (default is 10 MB, manually configurable via `logsize_n` setting). +18. GPX Track - Turn track recording (in GPX format) on or off. On first selection, you will be prompted to select the directory into which timestamped GPX track files are saved. See also [GPX Track Viewer](#gpxviewer). +19. Database - Turn spatialite database recording (*where available*) on or off. On first selection, you will be prompted to select the directory into which the `pygpsclient.sqlite` database is saved. Note that, when first created, the database's spatial metadata will take a few seconds to initialise (*up to a minute on Raspberry Pi and similar SBC*). **NB** This facility is dependent on your Python environment supporting the requisite [sqlite3 `mod_spatialite` extension](https://www.gaia-gis.it/fossil/libspatialite/index) - see [INSTALLATION.md](https://github.com/semuconsulting/PyGPSClient/blob/master/INSTALLATION.md#prereqs) for further details. If not supported, the option will be greyed out. Check the Menu..Help..About dialog for an indication of the current spatialite support status. + - *FYI* a helper method `retrieve_data()` is available to retrieve data from this database - see [Sphinx documentation](https://www.semuconsulting.com/pygpsclient/pygpsclient.html#pygpsclient.sqllite_handler.retrieve_data) and [retrieve_data.py](https://github.com/semuconsulting/PyGPSClient/blob/master/examples/retrieve_data.py) example for details. + +#### Pop-up Configuration Dialogs + +20. [UBX Configuration Dialog](#ubxconfig), with the ability to send a variety of UBX CFG configuration commands to u-blox GNSS devices. This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the UBX Configuration Dialog (*only functional when connected to a UBX GNSS device via serial port*), click +![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-ubx.png?raw=true), or go to Menu..Options..UBX Configuration Dialog. +21. [NMEA Configuration Dialog](#nmeaconfig), with the ability to send a variety of NMEA configuration commands to GNSS devices (e.g. Quectel LGSERIES). This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the NMEA Configuration Dialog (*only functional when connected to a compatible GNSS device via serial port*), click ![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-nmea.png?raw=true), or go to Menu..Options..NMEA Configuration Dialog. +22. [TTY Config Dialog](#ttycommands), with the ability to send a variety of TTY (ASCII) configuration commands to GNSS and related devices (e.g. Septentrio X5, Unicore UM980). This includes the facility to add **user-defined commands or command sequences** - see instructions under [user-defined presets](#userdefined) below. To display the TTY Commands Dialog (*only functional when connected to a compatible GNSS device via serial port*), click +![gear icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-gear-2-24-tty.png?raw=true), or go to Menu..Options..TTY Commands. +23. [NTRIP Client](#ntripconfig) facility with the ability to connect to a specified NTRIP caster, parse the incoming RTCM3 or SPARTN data and feed this data to a compatible GNSS receiver (*requires an Internet connection and access to an NTRIP caster and local mountpoint*). To display the NTRIP Client Configuration Dialog, click +![ntrip icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-antenna-4-24.png?raw=true), or go to Menu..Options..NTRIP Configuration Dialog. +24. [Server Config](#socketserver) facility with the ability to act as generic socket server or NTRIP caster (mountpoint = `pygnssutils`). To display the Server Configuration Dialog, click +![server icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-transmit-10-24.png?raw=true), or go to Menu..Options..Server Configuration Dialog. +25. [GPX Track Viewer](#gpxviewer) facility with elevation and speed profiles and track metadata. To display the GPX Track viewer, go to Menu..Options..GPX Track Viewer. +26. [Import Custom Map](#custommap) facility which allows the user to import geo-referenced images for use as maps. To display the Import Custom Map dialog, go to Menu..Options..Import Custom Map. +27. [Configuration Command Recorder](#recorder) facility which allows the user to record, save, load and replay UBX, NMEA or TTY configuration commands sent to a receiver. To display the Command Record Facility dialog, go to Menu..Options..Configuration Command Recorder. +28. [SPARTN Client](#spartnconfig) facility with the ability to configure an IP or L-Band SPARTN Correction source and SPARTN-compatible GNSS receiver (e.g. ZED-F9P) and pass the incoming correction data to the GNSS receiver (*requires an Internet connection and access to a SPARTN location service*). To display the SPARTN Client Configuration Dialog, go to Menu..Options..SPARTN Configuration Dialog. #### GUI refresh rate setting -- PyGPSClient processes all incoming GNSS data in 'real time' but, by default, the GUI is only refreshed every 0.5 seconds. The refresh rate can be configured via the `guiupdateinterval_f` setting in the json configuration file. **NB:** PyGPSClient may become unresponsive on slower platforms (e.g. Raspberry Pi) at high message rates if the GUI update interval is less than 0.1 seconds, though lower intervals (<= 0.1 secs) can be accommodated on more powerful platforms. +29. PyGPSClient processes all incoming GNSS data in 'real time' but, by default, the GUI is only refreshed every 0.5 seconds. The refresh rate can be configured via the `guiupdateinterval_f` setting in the json configuration file. **NB:** PyGPSClient may become unresponsive on slower platforms (e.g. Raspberry Pi) at high message rates if the GUI update interval is less than 0.1 seconds, though lower intervals (<= 0.1 secs) can be accommodated on more powerful platforms. +#### Toplevel ('pop-up') dialog setting + +30. The behaviour of Toplevel ('pop-up') dialogs will depend on the screen resolution and 'transient' setting. If the width or height of a Toplevel dialog exceeds the screen resolution, the dialog will be displayed in a scrollable, resizeable window. Otherwise, the dialog is displayed as a fixed, non-resizeable panel. + - A boolean configuration setting `transient_dialog_b` governs whether Toplevel dialogs are 'transient' (i.e. always on top of main application dialog) or not. Changing this setting to `0` allows Toplevel dialogs to be minimised independently of the main application window, but be mindful that some dialogs may end up hidden behind others e.g. "Open file/folder" dialogs. **If a file open button appears unresponsive, check that the "Open file/folder" panel isn't already open but obscured**. + - If you're accessing the desktop via a VNC session (e.g. to a headless Raspberry Pi) it is recommended to keep the setting at the default `1`, as VNC may not recognise keystrokes on overlaid non-transient windows. + #### User-selectable widgets --- | Widget | To show or hide the various widgets, go to Menu..View and click on the relevant hide/show option. | @@ -204,7 +212,7 @@ For more comprehensive installation instructions, please refer to [INSTALLATION. The UBX Configuration Dialog currently provides the following UBX configuration panels: -1. Version panel shows current device hardware/firmware versions (*via MON-VER and MON-HW polls*). +1. Version panel shows current device hardware/firmware versions (*Double-left-click to refresh*). 1. Protocol Configuration panel (CFG-PRT) sets baud rate and inbound/outbound protocols across all available ports (*legacy protocols only*). 1. Solution Rate panel (CFG-RATE) sets navigation solution interval in ms (e.g. 1000 = 1/second) and measurement ratio (ratio between the number of measurements and the number of navigation solutions, e.g. 5 = five measurements per navigation solution) (*legacy protocols only*). 1. For each of the panels above, clicking anywhere in the panel background will refresh the displayed information with the current configuration. @@ -232,8 +240,8 @@ warning ![warning icon](https://github.com/semuconsulting/PyGPSClient/blob/maste **Instructions:** The NMEA Configuration Dialog currently provides the following NMEA configuration panels: -1. Version panel shows current device hardware/firmware versions (*via PQTMVERNO polls*). -1. Dynamic configuration panel providing structured updates for supported receivers e.g. Quectel LG290P via PQTM* sentences, or LC29H via PAIR* sentences. Once a command is selected, the configuration is polled and the current values displayed. The user can then amend these values as required and send the updated configuration. Some polls require input arguments (e.g. portid or msgname) - these are highlighted and will be set at default values initially (e.g. portid = 1), but can be amended by the user and re-polled using the ![refresh](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-refresh-lined-24.png?raw=true) button. +1. Version panel shows current device hardware/firmware versions (*Double-left-click to refresh*). +1. Dynamic configuration panel providing structured updates for supported receivers e.g. Quectel LGSERIES via PQTM* sentences, or LCSERIES via PAIR* sentences. Once a command is selected, the configuration is polled and the current values displayed. The user can then amend these values as required and send the updated configuration. Some polls require input arguments (e.g. portid or msgname) - these are highlighted and will be set at default values initially (e.g. portid = 1), but can be amended by the user and re-polled using the ![refresh](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-refresh-lined-24.png?raw=true) button. 1. Preset Commands widget supports a variety of user-defined NMEA commands and queries - see [user defined presets](#userdefined). An icon to the right of each 'SEND' @@ -249,6 +257,8 @@ warning ![warning icon](https://github.com/semuconsulting/PyGPSClient/blob/maste ![ttydialog screenshot](https://github.com/semuconsulting/PyGPSClient/blob/master/images/tty_dialog.png?raw=true) +Version panel shows current device hardware/firmware versions (*Double-left-click to refresh*). + The TTY Commands dialog provides a facility to send user-defined ASCII TTY configuration commands (e.g. `AT+` style commands) to the connected serial device. Commands can be entered manually or selected from a list of user-defined presets. The dialog can be accessed via the TTY Config button or Menu..Options..TTY Commands. - CRLF checkbox - if ticked, a CRLF (`b"\x0d\x0a"`) terminator will be added to the command string. - Echo checkbox - if ticked, outgoing TTY commands will be echoed on the console with the marker `"TTY<<"`. @@ -314,20 +324,14 @@ Below is a illustrative NTRIP DGPS data log, showing: **NB:** Please respect the terms and conditions of any remote NTRIP service used with this facility. For testing or evaluation purposes, consider deploying a local [SNIP LITE](https://www.use-snip.com/download/) server. *Inappropriate use of an NTRIP service may result in your account being blocked*. --- -## SPARTN Client Facilities - - ### NB: As of October 2025, u-blox have discontinued both their L-Band and MQTT encrypted SPARTN correction services, so the SPARTN Client functionality is effectively redundant and may be removed in a subsequent version of PyGPSClient. - - The SPARTN MQTT and L-Band configuration panels are now disabled by default, though the L-Band panel can in theory still be used for other generic L-Band modem configuration purposes and can be re-enabled by setting json configuration parameter `lband_enabled_b` to `1`. - -Please refer to [SPARTN.md](https://github.com/semuconsulting/PyGPSClient/blob/master/SPARTN.md) for instructions. +## NTRIP Caster / Socket Server Facilities ---- -## Socket Server / NTRIP Caster Facilities +To display the Server Configuration Dialog, click +![server icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-transmit-10-24.png?raw=true), or go to Menu..Options..Server Configuration Dialog. -The Socket Server / NTRIP Caster facility is capable of operating in either of two modes; +The NTRIP Caster / Socket Server facility is capable of operating in either of two modes; 1. SOCKET SERVER - an open, unauthenticated TCP socket server available to any socket client including, for example, another instance of PyGPSClient or the [`gnssstreamer` CLI utility](https://github.com/semuconsulting/pygnssutils#gnssstreamer). In this mode it will broadcast the host's currently connected GNSS data stream. The default port is 50012. -2. NTRIP CASTER - a simple implementation of an authenticated NTRIP caster available to any NTRIP client including, for example, PyGPSClient's NTRIP Client facility, [`gnssntripclient`](https://github.com/semuconsulting/pygnssutils#gnssntripclient) or BKG's [NTRIP Client (BNC)](https://igs.bkg.bund.de/ntrip/download). 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. +2. NTRIP CASTER - a simple implementation of an authenticated NTRIP caster available to any NTRIP client. 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. 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`. The server/caster status is indicated: 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 (label shows number of active clients): ![transmit icon](https://github.com/semuconsulting/PyGPSClient/blob/master/src/pygpsclient/resources/iconmonstr-transmit-10-24.png?raw=true). @@ -354,26 +358,47 @@ By default, the server/caster binds to the host address '0.0.0.0' (IPv4) or '::' 1. Select NTRIP CASTER mode and (if necessary) enter the host IP address and port. 1. Select 'TLS' to enable an encrypted TLS (HTTPS) connection. -1. An additional expandable panel is made available to allow the user to configure a connected RTK-compatible receiver to operate in either `FIXED` or `SURVEY-IN` Base Station mode (*NB: parameters can only be amended while the caster is stopped*). +1. An additional expandable panel is made available to allow the user to configure a connected RTK-compatible receiver to operate in either `BASE FIXED`, `BASE SVIN` (Survey In) or `ROVER` mode (*NB: parameters can only be amended while the caster is stopped*). 1. Select the receiver type and click the Send button to send the appropriate configuration commands to the receiver. -1. **NB** Septentrio Mosaic X5 or Unicore UM980: These receivers are configured via ASCII TTY commands - to monitor the command responses, set the console protocol to "TTY" (*remember to set it back to RTCM when monitoring the RTCM3 output*). Note also that the input (ASCII command) UART port may be different to the output (RTCM3) UART port - make sure to select the appropriate port(s) when configuring the device and monitoring the RTCM3 output. -1. NMEA messages can be suppressed by checking 'Disable NMEA'. +1. **Where supported by the receiver**, NMEA messages can be suppressed by checking 'Disable NMEA'. 1. NTRIP client login credentials are set via the user and password fields. 1. Check the Socket Server/NTRIP Caster checkbox to activate the caster. 1. To stop the caster, uncheck the checkbox. ### Base Station Configuration +The current version of PyGPSClient supports 'one click' base station configuration for the following receiver types: +1. u-blox - any modern u-blox RTK model (e.g. XED-F9P, ZED-X20P) configured by binary UBX CFG-VALSET commands. +1. Septentrio - most Septentrio Mosaic series (e.g. Mosaic X5) configured by ASCII TTY commands. +1. Unicore - most UM9* series (e.g. UM981S) configured by ASCII TTY commands. +1. Quectel LG Series - most LG series (e.g. LG290, LG580) configured by NMEA PQTM commands. +1. Quectel LC Series - most LC series (e.g. LC29H) configured by NMEA PAIR commands. + +**NOTE:** +1. Some receivers (*e.g. Quectel LG Series*) will require one or more restarts to enable or disable Base Station mode. This may take several seconds. +1. Different receiver models support different RTCM3 message cohorts, as indicated by the pygnssutils sourcetable entry e.g. `1006(5),1013(5),1019(5),1020(5),1033(5),1077(1),1087(1),1097(1),1127(1),1230(1)` +1. To monitor ASCII TTY command responses, set the console protocol to "TTY" (*remember to set it back to RTCM when monitoring the RTCM3 output*). Note also that the input (ASCII command) UART port may be different to the output (RTCM3) UART port - make sure to select the appropriate port(s) when configuring the device and monitoring the RTCM3 output. + | Configuration Settings | Base Station Mode | |------------------------------------------------------|---------------------------------------------------------| -| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_fixed.png?raw=true) | **FIXED**. In this mode, the known base station coordinates (*Antenna Reference Point or ARP*) are specified in either LLH or ECEF (X,Y,Z) format. The coordinates are pre-populated with the receiver's current navigation solution (if available), but these can (and normally should) be overridden with accurately surveyed values. If the coordinates are accepted, the Fix status will change to `TIME ONLY` and the receiver will start outputting RTCM `1005` or `1006` (*Antenna Reference Point or ARP*) messages containing the base station location in ECEF (X,Y,Z) format. | -| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_svin.png?raw=true) | **SURVEY-IN**. In this mode, the base station coordinates are derived from the receiver's current navigation solution, provided the prescribed level of accuracy is met within the specified survey duration. If the survey is successful, the Fix status will change to `TIME ONLY` and the receiver will start outputting RTCM `1005` or `1006` messages containing the base station location in ECEF (X,Y,Z) format. The surveyed base station location will be updated from the position provided by these RTCM `1005` or `1006` messages.| -| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_off.png?raw=true) | **DISABLED**. Disable base station operation. | +| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_fixed.png?raw=true) | **BASE FIXED**. In this mode, the known base station coordinates (*Antenna Reference Point or ARP*) are specified in either LLH or ECEF (X,Y,Z) format. The coordinates are pre-populated with the receiver's current navigation solution (if available), but these can (and normally should) be overridden with accurately surveyed values. If the coordinates are accepted, the receiver will start outputting RTCM `1005` or `1006` (*Antenna Reference Point or ARP*) messages containing the base station location in ECEF (X,Y,Z) format. | +| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_svin.png?raw=true) | **BASE SVIN (Survey In)**. In this mode, the base station coordinates are derived from a series of observations made by the receiver over a specified survey duration. The minimum duration is 60 seconds, but a longer survey may yield more accurate results. **Where supported by the receiver¹** in the form of SVIN status messages, survey progress can be monitored via a progress bar. If the survey is successful (*i.e. the requisite level of accuracy is achieved within the specified survey duration*), the receiver will start outputting RTCM `1005` or `1006` messages containing the base station location in ECEF (X,Y,Z) format. The surveyed base station location will be updated from the position provided by these RTCM `1005` or `1006` messages.| +| ![basestation config](https://github.com/semuconsulting/PyGPSClient/blob/master/images/basestation_off.png?raw=true) | **ROVER**. Disable base station and resume standard Rover operation. | **NB:** To operate effectively as an RTK Base Station, antenna positioning is of paramount importance. Refer to the following links for advice: - [u-blox GNSS Antennas Paper](https://www.ardusimple.com/wp-content/uploads/2022/04/GNSS-Antennas_AppNote_UBX-15030289.pdf) - [Ardusimple GNSS Antenna Installation Guide](https://www.ardusimple.com/gps-gnss-antenna-installation-guide/) +¹ Unicore and Septentrio devices do not appear to support an SVIN status output message, so Survey-in % completion is not available. + +--- +## SPARTN Client Facilities + + ### NB: As of October 2025, u-blox have discontinued both their L-Band and MQTT encrypted SPARTN correction services, so the SPARTN Client functionality is effectively redundant and may be removed in a subsequent version of PyGPSClient. + + The SPARTN MQTT and L-Band configuration panels are now disabled by default, though the L-Band panel can in theory still be used for other generic L-Band modem configuration purposes and can be re-enabled by setting json configuration parameter `lband_enabled_b` to `1`. + +Please refer to [SPARTN.md](https://github.com/semuconsulting/PyGPSClient/blob/master/SPARTN.md) for instructions. --- ## GPX Track Viewer @@ -435,14 +460,14 @@ ubx = UBXMessage("CFG", "CFG-MSG", SET, msgClass=0x01, msgID=0x03, rateUART1=1) print(ubx2preset(ubx, "Configure NAV-STATUS Message Rate on ZED-F9P")) nmea = NMEAMessage("P", "QTMCFGUART", SET, baudrate=460800) -print(nmea2preset(nmea, "Configure UART baud rate on LG290P")) +print(nmea2preset(nmea, "Configure UART baud rate on LGSERIES")) tty = b"AT+SYSTEM_RESET\r\n" print(tty2preset(tty, "IM19 System Reset CONFIRM")) ``` ``` Configure NAV-STATUS Message Rate on ZED-F9P, CFG, CFG-MSG, 0103000100000000, 1 -Configure UART baud rate on LG290P; P; QTMCFGUART; W,460800; 1 +Configure UART baud rate on LGSERIES; P; QTMCFGUART; W,460800; 1 IM19 System reset CONFIRM; AT+SYSTEM_RESET ``` @@ -460,20 +485,22 @@ For further details, refer to the `pygnssutils` homepage at [https://github.com/ --- ## Known Issues -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. +1. If you encounter persistent `WARNING>>Error parsing data stream Serial stream terminated unexpectedly` messages in the console, this may be indicative of insufficient serial port bandwidth (baudrate or timeout) for the current output message cohort (*particularly if this includes Ephemera or Observation data*). Try increasing the baudrate in the first instance. + +2. 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. -2. Some Linux Wayland platforms appear to require Toplevel dialog windows to be non-transient (`transient_dialog_b: 0`) for the window 'maximise' icon to work properly. +3. Some Linux Wayland platforms appear to require Toplevel dialog windows to be non-transient (`transient_dialog_b: 0`) for the window 'maximise' icon to work properly. -3. Some Homebrew-installed Python environments on MacOS can give rise to critical segmentation errors (*illegal memory access*) when shell subprocesses are invoked, due to the way permissions are implemented. This may, for example, affect About..Update functionality; the workaround is to update via a standard CLI `pip install --upgrade` command. +4. Some Homebrew-installed Python environments on MacOS can give rise to critical segmentation errors (*illegal memory access*) when shell subprocesses are invoked, due to the way permissions are implemented. This may, for example, affect About..Update functionality; the workaround is to update via a standard CLI `pip install --upgrade` command. -4. Installing the optional `cryptography` package on some 32-bit Linux platforms (e.g. Raspberry Pi OS 32) may require [Rust compiler support](https://www.rust-lang.org/tools/install) and some [additional build dependencies](https://cryptography.io/en/latest/installation/) (see [pyspartn cryptography installation notes](https://github.com/semuconsulting/pyspartn/tree/main/cryptography_installation#readme)): +5. Installing the optional `cryptography` package on some 32-bit Linux platforms (e.g. Raspberry Pi OS 32) may require [Rust compiler support](https://www.rust-lang.org/tools/install) and some [additional build dependencies](https://cryptography.io/en/latest/installation/) (see [pyspartn cryptography installation notes](https://github.com/semuconsulting/pyspartn/tree/main/cryptography_installation#readme)): ```shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt-get install build-essential libssl-dev libffi-dev python3-dev pkg-config ``` -5. As of October 2025, u-blox have [discontinued their PointPerfect SPARTN L-Band and MQTT services](https://portal.u-blox.com/s/question/0D5Oj00000uB53GKAS/suspension-of-european-pointperfect-lband-spartn-service). As a result, PyGPSClient's [SPARTN Configuration](#spartnconfig) panel is largely redundant and is disabled by default in version>=1.5.17, though it can be re-enabled by manually setting the `lband_enabled_b` configuration setting to 1. +6. As of October 2025, u-blox have [discontinued their PointPerfect SPARTN L-Band and MQTT services](https://portal.u-blox.com/s/question/0D5Oj00000uB53GKAS/suspension-of-european-pointperfect-lband-spartn-service). As a result, PyGPSClient's [SPARTN Configuration](#spartnconfig) panel is largely redundant and is disabled by default in version>=1.5.17, though it can be re-enabled by manually setting the `lband_enabled_b` configuration setting to 1. --- ## License diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6f88ce0b..fe2544ad 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,17 @@ # PyGPSClient Release Notes +### RELEASE 1.6.4 + +FIXES: +1. Fix `CFG-VALSET ACK-NAK` error when configuring ZED-X20P as base station. +1. Fix `AttributeError: ... has no attribute frm_socketserver` error in Server Config panel when configuring certain devices for SVIN. + +ENHANCEMENTS: +1. Improve Base Station receiver configuration handling in the NTRIP Caster/Socket Server dialog. +1. Add connected device descriptor to status bar (e.g. "u-blox ZED-F9P", "Unicore UM981S", "Septentrio mosaic-X5" or "Quectel LG290AG03"). **FYI** This is based on a series of query messages (*one for each enabled protocol*) sent approximately 3 seconds after the connection is started (*you may see 'unknown protocol' warnings in response to some of these messages; these can be ignored)*. Failing this, a generic descriptor is displayed on receipt of a message protocol unique to a particular manufacturer (*e.g. "u-blox" on receipt of a UBX message, "Unicore" on receipt of a UNI message, etc.*). Note that some (mainly older) devices may not return a meaningful descriptor, in which case "N/A" will be displayed. +1. Minor updates to serial port configuration panel (additional timeout values). +1. Mininum pynmeagps version updated to v1.1.1. + ### RELEASE 1.6.3 1. Add support for Unicore UNI binary data output messages via `pyunigps>=0.1.3` and `pygnssutils>=1.1.22`. @@ -106,7 +118,7 @@ FIXES: ENHANCEMENTS: 1. As of October 2025, u-blox have discontinued their MQTT SPARTN service (*having previously discontinued their L-Band SPARTN service earlier in the year*) so this functionality has been disabled by default in PyGPSClient in this release, and will be removed altogether in a subsequent release. It can be re-enabled by manually editing the `lband_enabled_b` configuration setting. -1. Add provisional support for Quectel QGC binary message protocol (requires pyqgc>=0.1.2). Currently only Quectel LG290P / LG580P / LG680P RAW and LU600 IMU QGC message types are implemented, but this will be enhanced in future releases (contributions welcome). +1. Add provisional support for Quectel QGC binary message protocol (requires pyqgc>=0.1.2). Currently only Quectel LGSERIES / LG580P / LG680P RAW and LU600 IMU QGC message types are implemented, but this will be enhanced in future releases (contributions welcome). 1. Add additional IMU message types to IMU widget drop-down. 1. Enhance performance and look and feel of banner skyview and graphview widgets. 1. Drop active support for Python 3.9, add 3.14 (3.9 EOL as at 31 October 2025). @@ -121,7 +133,7 @@ FIXES: ENHANCEMENTS: -1. Add support for Quectel LC29H base station configuration in NTRIP Caster mode. +1. Add support for Quectel LCSERIES base station configuration in NTRIP Caster mode. 1. Enhance support for Quectel PAIR commands in NMEA configuration panel. 1. Minor refinements to UI on lower resolution screens. @@ -156,7 +168,7 @@ ENHANCEMENTS: 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). 2. BSD 3-Clause license attribution clarified in all modules. 3. Enhance elevation profile and metadata rendering in GPX track viewer. Add support for route and waypoint elements in addition to track. -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). +4. Enhance NMEA Dynamic Configuration dialog to support additional NMEA command types, including Quectel proprietary $PAIR (Quectel LCSERIES/LC79H), Garmin $PGRM, Locosys %PINV (limited) and u-Blox $PUBX (requires pynmeagps>=1.0.53). 5. Add support 5. Various minor improvements to file exception handling. @@ -204,7 +216,7 @@ FIXES: ENHANCEMENTS: -1. Add support for Septentrio Mosaic X5 Base Station configuration in NTRIP Caster mode (supplementing the existing u-blox ZED-F9P/X20P and Quectel LG290P options). Note that the Mosaic X5 is configured via ASCII TTY commands - to monitor the responses, set the console protocol to "TTY" (remember to set it back to "RTCM" to monitor the RTCM3 output). Note also that the input (ASCII command) UART port may be different to the output (RTCM3) port - ensure you select the appropriate port(s) when configuring the receiver and monitoring the RTCM3 output. +1. Add support for Septentrio Mosaic X5 Base Station configuration in NTRIP Caster mode (supplementing the existing u-blox ZED-F9P/X20P and Quectel LGSERIES options). Note that the Mosaic X5 is configured via ASCII TTY commands - to monitor the responses, set the console protocol to "TTY" (remember to set it back to "RTCM" to monitor the RTCM3 output). Note also that the input (ASCII command) UART port may be different to the output (RTCM3) port - ensure you select the appropriate port(s) when configuring the receiver and monitoring the RTCM3 output. 1. Add base station location update - automatically updates NTRIP CASTER Survey-in base station location from RTCM 1005/6 message. 1. Chart Plot widget streamlined to reduce memory footprint and simplify CSV cut-and-paste (double-right-click) function. 1. Minor enhancements to ubx2preset() and nmea2preset() helper functions; added \examples\convert_ubx_preset.py example. @@ -238,7 +250,7 @@ FIXES: ENHANCEMENTS: -1. Add receiver type option to NTRIP Caster mode - can now utilise either u-blox ZED-F9* or Quectel LG290P as Base Station receiver. NOTE THAT due to quirks in the LG290P firmware, setting Base Station mode with RTCM MSM 7 messages requires two successive restarts - you may see `WARNING - connection error` in the console during those restarts. +1. Add receiver type option to NTRIP Caster mode - can now utilise either u-blox ZED-F9* or Quectel LGSERIES as Base Station receiver. NOTE THAT due to quirks in the LGSERIES firmware, setting Base Station mode with RTCM MSM 7 messages requires two successive restarts - you may see `WARNING - connection error` in the console during those restarts. 1. Add new IMU Monitor widget, capable of displaying IMU orientation (roll, pitch, yaw) and status from a variety of NMEA or UBX IMU data sources (e.g. ESF-ALG, HNR-ATT, NAV-ATT, NAV-PVAT, GPFMI). 1. Add TTY Command Dialog, allowing user to enter/select ASCII TTY commands to the connected serial device. Access via menu bar Options...TTY Commands. 1. RTCM3 messages types 1002 (GPS L1 observables) & 1010 (GLONASS L1 observables) added to NTRIP Caster configuration. @@ -265,7 +277,7 @@ ENHANCEMENTS: ### RELEASE 1.5.5 -1. Add new NMEA Configuration panel, complementing and (partly) mirroring the existing UBX Configuration panel. The NMEA configuration panel supports GNSS receivers which can be configured via proprietary NMEA sentences. Currently the only supported receiver is the Quectel LG290P (or other command-compatible Quectel receivers). See [README](https://github.com/semuconsulting/PyGPSClient?tab=readme-ov-file#nmeaconfig) for details. User-defined preset NMEA commands may be added via the `nmeapresets_l` section of the PyGPSClient *.json configuration file. +1. Add new NMEA Configuration panel, complementing and (partly) mirroring the existing UBX Configuration panel. The NMEA configuration panel supports GNSS receivers which can be configured via proprietary NMEA sentences. Currently the only supported receiver is the Quectel LGSERIES (or other command-compatible Quectel receivers). See [README](https://github.com/semuconsulting/PyGPSClient?tab=readme-ov-file#nmeaconfig) for details. User-defined preset NMEA commands may be added via the `nmeapresets_l` section of the PyGPSClient *.json configuration file. 1. Two new helper functions added `ubx2preset()` and `nmea2preset()`, to assist users in converting `UBXMessage` or `NMEAMessage` objects into strings which can be copied-and-pasted into the relevant sections of the *.json configuration file (`ubxpresets_l` and `nmeapresets_l`). See [README](https://github.com/semuconsulting/PyGPSClient?tab=readme-ov-file#userdefined) for details. ### RELEASE 1.5.4 diff --git a/examples/libspatialite_compile.sh b/examples/libspatialite_compile.sh index 90656e88..9e63a550 100755 --- a/examples/libspatialite_compile.sh +++ b/examples/libspatialite_compile.sh @@ -2,8 +2,7 @@ # bash shell script to compile and install libspatialite # (mod_spatialite.so) on Debian Linux platforms which do not -# include a suitable binary in their standard repos -# (e.g. Raspberry Pi OS). +# include a suitable binary installable in their standard repos. # # Remember to run chmod +x libspatialite_compile.sh to make this script executable. # diff --git a/examples/pygpsclient_arch_install.sh b/examples/pygpsclient_arch_install.sh index fd90916b..5933e28d 100644 --- a/examples/pygpsclient_arch_install.sh +++ b/examples/pygpsclient_arch_install.sh @@ -3,6 +3,10 @@ # Bash shell script to install PyGPSClient on 64-bit Arch-based # Linux environments. # +# Arch Desktop generally includes all the necessary Python3 executables by +# default (but remember to look for the third-party ARM64/AARCH64 +# distributables if you're using an ARM SBC like Raspberry Pi). +# # Change shebang /bin/bash to /bin/zsh if running from zsh shell. # NB: NOT for use on Windows or MacOS! # @@ -22,6 +26,7 @@ echo "Installed Python version is $PYVER" echo "PyGPSClient will be installed at $HOME/pygpsclient/bin" +# this is generally all that's needed - Arch Desktop includes the latest Python3 echo "Installing dependencies..." sudo pacman -S tk libspatialite diff --git a/examples/pygpsclient_macos_install.sh b/examples/pygpsclient_macos_install.sh index 08726710..51d1ff91 100644 --- a/examples/pygpsclient_macos_install.sh +++ b/examples/pygpsclient_macos_install.sh @@ -3,6 +3,8 @@ # ZSH shell script to install PyGPSClient on MacOS # environments (MacOS 13 or later running zsh shell). # +# NB: Homebrew or Macports are NOT required. +# # NB: Does NOT create an application launcher - use # the MacOS Automator tool to create a bin/zsh shell app # called PyGPSClient.app with the shell command: diff --git a/examples/python_compile.sh b/examples/python_compile.sh index 889d384f..5d4e2cdc 100644 --- a/examples/python_compile.sh +++ b/examples/python_compile.sh @@ -1,7 +1,12 @@ #!/bin/bash -# bash shell script to compile and install specified Python 3 version -# on Debian Linux platforms e.g. Ubuntu or Raspberry Pi OS. +# bash shell script to compile and install specified Python3/tkinter +# version on Debian Linux platforms e.g. Ubuntu or Raspberry Pi OS. +# +# Why no Arch (pacman) version? Because Arch Desktop generally includes +# the very latest Python3 executables by default - go Arch! +# (but remember to look for the third-party ARM64/AARCH64 distributables +# if you're using an ARM SBC like Raspberry Pi) # # Remember to run chmod +x python_compile.sh to make this script executable. # @@ -18,8 +23,8 @@ # exit on error set -e -# set required Python major and minor version e.g. 3.10.10 -PYVER="3.13.7" +# set required Python major and minor version e.g. 3.13.10 +PYVER="3.14.3" # NB: uncomment this line to install this version alongside existing versions # ALTINSTALL=1 @@ -53,8 +58,9 @@ sudo apt install liblzma-dev || true # liblzma-dev may be lzma-dev on some platforms sudo apt install lzma-dev || true sudo apt install libspatialite || true -# libspatialite may not be available as standard on some platforms -# (e.g. Rasperry PI OS) but it is relatively straightforward to +sudo apt install libsqlite3-mod-spatialite || true +# libspatialite may not be available as a binary installable on some +# platforms (e.g. older Debian) but it is relatively straightforward to # compile from source using the libspatialite_compile.sh script # in the /examples folder diff --git a/images/app.png b/images/app.png index b40123df..efadd79e 100644 Binary files a/images/app.png and b/images/app.png differ diff --git a/images/basestation_fixed.png b/images/basestation_fixed.png index 53df6255..e8def05e 100644 Binary files a/images/basestation_fixed.png and b/images/basestation_fixed.png differ diff --git a/images/basestation_off.png b/images/basestation_off.png index cfcbf5a0..2b714468 100644 Binary files a/images/basestation_off.png and b/images/basestation_off.png differ diff --git a/images/basestation_svin.png b/images/basestation_svin.png index 6e503119..bc4b7601 100644 Binary files a/images/basestation_svin.png and b/images/basestation_svin.png differ diff --git a/images/tty_dialog.png b/images/tty_dialog.png index b07f8930..3365e302 100644 Binary files a/images/tty_dialog.png and b/images/tty_dialog.png differ diff --git a/pygpsclient.json b/pygpsclient.json index 244bf6d1..38952ea0 100644 --- a/pygpsclient.json +++ b/pygpsclient.json @@ -218,9 +218,9 @@ "Set Fix Rate to 1 Hz; P; QTMCFGFIXRATE; W,1000; 1; P; QTMHOT; ; 1", "Set Fix Rate to 5 Hz; P; QTMCFGFIXRATE; W,200; 1; P; QTMHOT; ; 1", "Set Fix Rate to 10 Hz; P; QTMCFGFIXRATE; W,100; 1; P; QTMHOT; ; 1", - "LG290P Set Base Mode Survey-In; P; QTMCFGRCVRMODE; W,2; 1; P; QTMCFGSVIN; W,1,60,3000,0.0,0.0,0.0; 1; P; QTMCFGMSGRATE; W,PQTMSVINSTATUS,1,1; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", - "LG290P Set Base Mode Fixed; P; QTMCFGRCVRMODE; W,2; 1; P; QTMCFGSVIN; W,2,0,0,-2213540.321087019,-4577229.071167925,3838042.2419518335; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", - "LG290P Set Normal (Rover) Mode; P; QTMCFGRCVRMODE; W,1; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", + "LGSERIES Set Base Mode Survey-In; P; QTMCFGRCVRMODE; W,2; 1; P; QTMCFGSVIN; W,1,60,3000,0.0,0.0,0.0; 1; P; QTMCFGMSGRATE; W,PQTMSVINSTATUS,1,1; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", + "LGSERIES Set Base Mode Fixed; P; QTMCFGRCVRMODE; W,2; 1; P; QTMCFGSVIN; W,2,0,0,-2213540.321087019,-4577229.071167925,3838042.2419518335; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", + "LGSERIES Set Normal (Rover) Mode; P; QTMCFGRCVRMODE; W,1; 1; P; QTMSAVEPAR; ; 1; P; QTMSRR; ; 1", "Enable SVIN Status message; P; QTMCFGMSGRATE; W,PQTMSVINSTATUS,1,1; 1", "Disable SVIN Status message; P; QTMCFGMSGRATE; W,PQTMSVINSTATUS,0,1; 1", "Set current UART baudrate to 460800; P; QTMCFGUART; W,460800; 1", diff --git a/pyproject.toml b/pyproject.toml index 52096614..2942e9b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,8 @@ dependencies = [ "requests>=2.28.0", "Pillow>=9.0.0", "pygnssutils>=1.1.22", - "pyunigps>=0.1.4", + "pyunigps>=0.2.0", + "pynmeagps>=1.1.1", ] [project.scripts] diff --git a/src/pygpsclient/_version.py b/src/pygpsclient/_version.py index 4a3417a2..2ccbd725 100644 --- a/src/pygpsclient/_version.py +++ b/src/pygpsclient/_version.py @@ -8,4 +8,4 @@ :license: BSD 3-Clause """ -__version__ = "1.6.3" +__version__ = "1.6.4" diff --git a/src/pygpsclient/app.py b/src/pygpsclient/app.py index 5fc4c660..2a9080ad 100644 --- a/src/pygpsclient/app.py +++ b/src/pygpsclient/app.py @@ -70,11 +70,13 @@ from pygpsclient._version import __version__ as VERSION from pygpsclient.banner_frame import BannerFrame from pygpsclient.configuration import Configuration -from pygpsclient.dialog_state import DialogState +from pygpsclient.dialog_state import DLGTNMEA, DLGTTTY, DLGTUBX, DialogState from pygpsclient.file_handler import FileHandler from pygpsclient.globals import ( BGCOL, CLASS, + CMDINITDELAY, + CMDPAUSE, CONFIGFILE, CONNECTED_NTRIP, CONNECTED_SPARTNIP, @@ -93,6 +95,7 @@ NOPORTS, NTRIP_EVENT, OKCOL, + RTCMSTR, SOCKSERVER_MAX_CLIENTS, SPARTN_EVENT, SPARTN_PROTOCOL, @@ -128,6 +131,7 @@ INACTIVE_TIMEOUT, INTROTXTNOPORTS, KILLSWITCH, + NA, NOTCONN, SAVECONFIGBAD, SAVECONFIGOK, @@ -136,6 +140,7 @@ UPDATEINPROG, UPDATERESTART, VERCHECK, + WARNING, ) from pygpsclient.tty_handler import TTYHandler from pygpsclient.ubx_handler import UBXHandler @@ -228,6 +233,7 @@ def __init__(self, master, **kwargs): self._recorded_commands = [] # captured by RecorderDialog self.recording = False # RecordDialog status self.recording_type = 0 # 0 = TTY ONLY, 1 = UBX/NMEA + self.ntriprtcmstr = RTCMSTR # open database if database recording enabled dbpath = self.configuration.get("databasepath_s") @@ -601,9 +607,11 @@ def dialog(self, dlg: str) -> Toplevel: return self.dialog_state.state[dlg][DLG] - def sockserver_start(self): + def sockserver_start(self, ntriprtcmstr: str = RTCMSTR): """ Start socket server thread. + + :param str ntriprtcmstr: source table string indicating RTCM3 types and intervals """ cfg = self.configuration @@ -617,7 +625,6 @@ def sockserver_start(self): ntripuser = cfg.get("ntripcasteruser_s") ntrippassword = cfg.get("ntripcasterpassword_s") tlspempath = cfg.get("tlspempath_s") - ntriprtcmstr = "1002(1),1006(5),1077(1),1087(1),1097(1),1127(1),1230(1)" self._socket_thread = Thread( target=self._sockserver_thread, args=( @@ -928,7 +935,7 @@ def process_data(self, raw_data: bytes, parsed_data: object, marker: str = ""): if self.configuration.get("ttyprot_b"): msgprot = TTY_PROTOCOL else: - marker = "WARNING>>" + marker = WARNING if msgprot == UBX_PROTOCOL and msgprot & protfilter: self.ubx_handler.process_data(raw_data, parsed_data) @@ -981,16 +988,29 @@ def process_data(self, raw_data: bytes, parsed_data: object, marker: str = ""): self.update_idletasks() - def send_to_device(self, data: bytes): + def send_to_device( + self, data: bytes | list[bytes], pause: int = 0, interval: int = 0 + ): """ - Place raw data on output queue (it will be processed when the - device next connects). + Place one or more binary commands on output queue (they will be + processed in sequence when the device next connects). - :param bytes data: raw GNSS data (NMEA, UBX, TTY, RTCM3, SPARTN) + :param bytes | list[bytes] data: raw GNSS data (NMEA, UBX, TTY, RTCM3, SPARTN) + :param int pause: pause in ms before sending first command + (to allow connection time to to stabilise) + :param int interval: interval in ms between individual commands + (to allow receiver time to process = see CMDPAUSE global) """ - self.logger.debug(f"Sending message {data}") - self.gnss_outqueue.put(data) + if not isinstance(data, list): + data = [ + data, + ] + for i, cmd in enumerate(data): + self.logger.debug(f"Sending message {cmd}") + self.after( + int(pause + interval * i), lambda c=cmd: self.gnss_outqueue.put(c) + ) def _check_update(self): """ @@ -1015,20 +1035,25 @@ def poll_version(self, protocol: int): :param int protocol: protocol(s) """ - msg = None + self.device_label = NA + msgs = [] if protocol & UBX_PROTOCOL: - msg = UBXMessage("MON", "MON-VER", POLL) - elif protocol & SBF_PROTOCOL: - msg = b"SSSSSSSSSS\r\nesoc, COM1, ReceiverSetup\r\n" - elif protocol & NMEA_PROTOCOL: - msg = NMEAMessage("P", "QTMVERNO", POLL) - - if isinstance(msg, (UBXMessage, NMEAMessage)): - self.send_to_device(msg.serialize()) - self.status_label = (f"{msg.identity} POLL message sent", INFOCOL) - elif isinstance(msg, bytes): - self.send_to_device(msg) - self.status_label = ("Setup POLL message sent", INFOCOL) + msgs.append(UBXMessage("MON", "MON-VER", POLL).serialize()) + if protocol & SBF_PROTOCOL: + msgs.append(b"SSSSSSSSSS\r\n") + msgs.append(b"exeSBFOnce, COM1, ReceiverSetup\r\n") + if protocol & UNI_PROTOCOL: + msgs.append(b"VERSIONB\r\n") + if protocol & NMEA_PROTOCOL: + msgs.append(NMEAMessage("P", "QTMVERNO", POLL).serialize()) + + # pause for n seconds before sending first command to allow connection to stabilise + # allow a small interval between individual commands to allow receiver time to process + self.send_to_device( + msgs, + pause=CMDINITDELAY, + interval=self.configuration.get("ttydelay_b") * CMDPAUSE, + ) @property def appmaster(self) -> Tk: @@ -1066,8 +1091,8 @@ def conn_label(self, connection: str | tuple[str, str]): color = INFOCOL # truncate very long connection description - if len(connection) > 100: - connection = "..." + connection[-100:] + if len(connection) > 80: + connection = f"{connection[0:80]}..." if hasattr(self, "frm_status"): self.conn_label.after( @@ -1075,6 +1100,48 @@ def conn_label(self, connection: str | tuple[str, str]): ) self.update_idletasks() + @property + def device_label(self) -> Label: + """ + Getter for device_label. + + :return: status label + :rtype: Label + """ + + return self.frm_status.lbl_device + + @device_label.setter + def device_label(self, device: str | tuple[str, str]): + """ + Sets device description in status bar (if known). + + :param str | tuple connection: (connection, color) + """ + + if isinstance(device, tuple): + device, color = device + else: + color = INFOCOL + + # truncate long device description + if len(device) > 30: + device = f"{device[0:30]}..." + + if hasattr(self, "frm_status"): + self.device_label.after( + 0, + self.device_label.config, + {"text": device, "fg": color}, + ) + self.update_idletasks() + + # update configuration panels + for dlg in (DLGTTTY, DLGTUBX, DLGTNMEA): + if self.dialog(dlg) is not None: + if hasattr(self.dialog(dlg), "frm_device_info"): + self.dialog(dlg).frm_device_info.reset() + @property def status_label(self) -> Label: """ @@ -1109,7 +1176,7 @@ def priority(col): if hasattr(self, "frm_status"): color = INFOCOL if color == "blue" else color self.status_label.config(text=message, fg=color) - self.update_idletasks() + self.status_label.update() else: # defer message until frm_status is instantiated if isinstance(self._deferredmsg, tuple): defpty = priority(self._deferredmsg[1]) @@ -1142,6 +1209,7 @@ def conn_status(self, status: int): self.frm_settings.frm_settings.enable_controls(status) if status == DISCONNECTED: self.conn_label = (NOTCONN, INFOCOL) + self.device_label = NA @property def server_status(self) -> int: diff --git a/src/pygpsclient/configuration.py b/src/pygpsclient/configuration.py index 6bf600be..aa2e0089 100644 --- a/src/pygpsclient/configuration.py +++ b/src/pygpsclient/configuration.py @@ -53,12 +53,13 @@ SPARTN_OUTPORT, SPARTN_PPSERVER_URL, TRACK, + UBLOX_ZEDF9, UMM, WORLD, - ZED_F9, ) from pygpsclient.init_presets import INIT_PRESETS from pygpsclient.mapquest_handler import MAP_UPDATE_INTERVAL +from pygpsclient.serverconfig_dialog import BASE_SVIN from pygpsclient.spartn_lband_frame import D9S_PP_EU as D9S_PP from pygpsclient.strings import ( LOADCONFIGBAD, @@ -169,15 +170,15 @@ def __init__(self, app): "sockclienthttps_b": 0, "sockclientselfsign_b": 0, "sockclientprotocol_s": "TCP IPv4", - # socket server settings from frm_socketserver + # socket server settings from server dialog "sockserver_b": 0, "sockhost_s": SOCKSERVER_HOST, "sockport_n": SOCKSERVER_PORT, "sockportntrip_n": SOCKSERVER_NTRIP_PORT, "sockmode_b": 0, "sockhttps_b": 0, - "ntripcasterbasemode_s": "SURVEY IN", - "ntripcasterrcvrtype_s": ZED_F9, + "ntripcasterbasemode_s": BASE_SVIN, + "ntripcasterrcvrtype_s": UBLOX_ZEDF9, "ntripcasteracclimit_f": 100.0, "ntripcasterduration_n": 60, "ntripcasterposmode_s": "LLH", diff --git a/src/pygpsclient/console_frame.py b/src/pygpsclient/console_frame.py index 21dc45d4..135e90d5 100644 --- a/src/pygpsclient/console_frame.py +++ b/src/pygpsclient/console_frame.py @@ -159,9 +159,9 @@ def update_frame(self, consoledata: list): self.txt_console.configure(font=FONT_TEXT) for raw_data, parsed_data, marker in consoledata: if consoleformat == FORMAT_BINARY: - data = f"{marker}{raw_data}".strip("\n") + data = f"{marker}{raw_data}\n" elif consoleformat == FORMAT_HEXSTR: - data = f"{marker}{raw_data.hex()}" + data = f"{marker}{raw_data.hex()}\n" elif consoleformat == FORMAT_HEXTAB: self.txt_console.configure(font=FONT_FIXED) data = hextable(raw_data) @@ -169,8 +169,9 @@ def update_frame(self, consoledata: list): self.txt_console.configure(font=FONT_FIXED) data = f"{marker}{parsed_data}\n{hextable(raw_data)}" else: - data = f"{marker}{parsed_data}" - consolestr += data + "\n" + data = f"{marker}{parsed_data}\n" + + consolestr += data numlinesbefore = self.numlines self.txt_console.configure(state="normal") diff --git a/src/pygpsclient/globals.py b/src/pygpsclient/globals.py index 6cacaf20..8f9bf202 100644 --- a/src/pygpsclient/globals.py +++ b/src/pygpsclient/globals.py @@ -75,6 +75,8 @@ ) BSR = "backslashreplace" CLASS = "cls" +CMDINITDELAY = 3000 # initial delay before sending commands to new connection +CMDPAUSE = 100 # pause between sent commands in ms COLORTAGS = "colortags" CONFIGFILE = path.join(HOME, f"{APPNAME}.json") CONNECTED = 1 @@ -185,8 +187,8 @@ IMG_WORLD_BOUNDS = Area(-90, -180, 90, 180) IMPORT = "import" LBAND = "LBAND" -LC29H = "Quectel LC29H" -LG290P = "Quectel LG29P/LG580P" +QUECTEL_LCSERIES = "Quectel LC Series" +QUECTEL_LGSERIES = "Quectel LG Series" LICENSE_URL = "https://github.com/semuconsulting/PyGPSClient/blob/master/LICENSE" LIN = "Linux" MAC = "Darwin" @@ -199,7 +201,7 @@ MIN_GUI_UPDATE_INTERVAL = 0.1 # minimum GUI widget update interval (seconds) MINFLOAT = -MAXFLOAT MINDIM = "mindim" -MOSAIC_X5 = "Septentrio Mosaic X3/X5" +SEPTENTRIO_MOSAIC = "Septentrio Mosaic Series" MQAPIKEY = "mqapikey" MQTTIPMODE = 0 MQTTLBANDMODE = 1 @@ -218,6 +220,7 @@ RESIZE = "resize" ROMVER_NEW = "23.01" # min device ROM version using configuration database ROUTE = "route" +RTCMSTR = "1002(1),1006(5),1077(1),1087(1),1097(1),1127(1),1230(1)" RXMMSG = "RXM-SPARTN-KEY" SAT_EXPIRY = 10 # how long passed satellites are kept in the sky and graph view SOCKCLIENT_HOST = "localhost" @@ -242,7 +245,7 @@ SQRT2 = 0.7071067811865476 # square root of 2 STATUSPRIORITY = {INFOCOL: 0, "blue": 0, OKCOL: 2, "green": 1, ERRCOL: 3, "red": 3} TIME0 = datetime(1970, 1, 1) # basedate for time() -TIMEOUTS = ("0.1", "0.2", "1", "2", "5", "10", "20", "None", "0") +TIMEOUTS = ("0.1", "0.2", "0.5", "1", "2", "5", "10", "20", "None", "0") # map nmea talker to gnss_id TKGN = {"GN": 0, "GP": 0, "GA": 2, "GB": 3, "BD": 3, "GQ": 5, "GL": 6, "GI": 7} TOPIC_IP = "/pp/ip/{}" @@ -255,7 +258,7 @@ TTYMARKER = "TTY<<" UBXPRESETS = "ubxpresets" UBXSIMULATOR = "ubxsimulator" -UM980 = "Unicore UM98n" +UNICORE_UM980 = "Unicore UM9* Series" UNDO = "UNDO" UTF8 = "utf-8" VALBLANK = 1 @@ -277,8 +280,8 @@ WIN = "Windows" WORLD = "world" XML_HDR = '' -ZED_F9 = "u-blox ZED-F9" -ZED_X20 = "u-blox ZED-X20" +UBLOX_ZEDF9 = "u-blox ZED-F9" +UBLOX_ZEDX20 = "u-blox ZED-X20" # Conversion factors UI = "Imperial mph" @@ -323,6 +326,7 @@ SERVERCONFIG = 18 SBF_MONHW = 19 SIGNALSVIEW = 20 +UNI_MONHW = 21 KNOWNGPS = ( "cp210", diff --git a/src/pygpsclient/hardware_info_frame.py b/src/pygpsclient/hardware_info_frame.py index 300980ee..394377a6 100644 --- a/src/pygpsclient/hardware_info_frame.py +++ b/src/pygpsclient/hardware_info_frame.py @@ -13,21 +13,16 @@ from tkinter import Frame, Label, W from PIL import Image, ImageTk -from pynmeagps import POLL, NMEAMessage -from pyubx2 import UBXMessage from pygpsclient.globals import ( - CONNECTED, - CONNECTED_SIMULATOR, ICON_CONFIRMED, ICON_PENDING, ICON_SEND, ICON_WARNING, - NMEA_MONHW, - SBF_MONHW, - UBX_MONVER, + INFOCOL, + OKCOL, ) -from pygpsclient.strings import NA +from pygpsclient.strings import HWREPOLL, HWRESET, NA class Hardware_Info_Frame(Frame): @@ -58,6 +53,7 @@ def __init__(self, app: Frame, parent: Frame, *args, **kwargs): self._body() self._do_layout() + self.reset() self._attach_events() def _body(self): @@ -102,50 +98,25 @@ def _do_layout(self): def _attach_events(self): """ Bind events to widget. - """ - - # click mouse button to refresh information - self.bind("