Porównaj commity

...

5 Commity

Autor SHA1 Wiadomość Data
Mark Jessop 55188fcca1 Automatically add microphone entry to Info.plist 2024-04-01 14:01:13 +10:30
Mark Jessop b0bb51cf2a Revert back to PyQt5 2024-03-31 14:10:13 +10:30
Mark Jessop f5d9e87db8 Remove ruamel.yaml dependency 2024-03-31 12:56:37 +10:30
Mark Jessop 356870b7b7 Fix audio error on startup 2024-03-31 11:20:32 +10:30
Mark Jessop 0bb9088917 Move to using Qt6 2024-03-31 10:35:46 +10:30
9 zmienionych plików z 156 dodań i 135 usunięć

Wyświetl plik

@ -66,8 +66,6 @@ $ cd horus-gui
### (Optional) Create a Virtual Environment ### (Optional) Create a Virtual Environment
**Warning - Python 3.10 will not work until a known compatability issue with pyaudio has been fixed. Use Python 3.9.**
Create a virtual environment and install dependencies. Create a virtual environment and install dependencies.
```console ```console
$ python3 -m venv venv $ python3 -m venv venv
@ -83,10 +81,28 @@ $ pip install -r requirements.txt
``` ```
NOTE: Under linux based distros, you may also need to install `python3-distutils` and `python-setuptools`. If you get errors relating to pyaudio when trying to install into a venv, make sure that portaudio is installed (`libportaudio-dev` or `portaudio19-dev` under Linux distros, or `portaudio` under Macports), and then install pyaudio pointing to the portaudio lib by running: NOTE: Under linux based distros, you may also need to install `python3-distutils` and `python-setuptools`. If you get errors relating to pyaudio when trying to install into a venv, make sure that portaudio is installed (`libportaudio-dev` or `portaudio19-dev` under Linux distros, or `portaudio` under Macports), and then install pyaudio pointing to the portaudio lib by running:
On Linux:
``` ```
(Linux) $ pip install --global-option='build_ext' --global-option='-I/usr/include' --global-option='-L/usr/lib' pyaudio $ export CFLAGS="-I/usr/include"
(OSX) $ pip install --global-option='build_ext' --global-option='-I/opt/local/include' --global-option='-L/opt/local/lib' pyaudio $ export LDFLAGS="-L/usr/lib"
(venv) $ pip install pyaudio
``` ```
On OSX using Macports:
```
$ export CFLAGS="-I/opt/local/include"
$ export LDFLAGS="-L/opt/local/lib"
(venv) $ pip install pyaudio
```
On OSX using Homebrew
```
$ export CFLAGS="-I/opt/homebrew/include"
$ export LDFLAGS="-L/opt/homebrew/lib"
(venv) $ pip install pyaudio
```
You should then be able to re-run the install requirements command above. You should then be able to re-run the install requirements command above.
### Install Package ### Install Package
@ -101,12 +117,12 @@ entry points so it can be used like a normal install.
### Run ### Run
```console ```console
$ python -m horusgui.gui $ (venv) python -m horusgui.gui
``` ```
Or run the helper startup script: Or run the helper startup script:
```console ```console
$ python horus-gui.py $ (venv) python horus-gui.py
``` ```
### Updating ### Updating
@ -127,4 +143,4 @@ $ . venv/bin/activate (if using a venv)
$ pip install horusdemodlib --upgrade $ pip install horusdemodlib --upgrade
``` ```
You should then be OK to run horusgui. Configuration settings will be reset when the version number of horus-gui is incremented, until I settle on on a configuration parameter set. You should then be OK to run horusgui.

Wyświetl plik

@ -4,7 +4,7 @@ block_cipher = None
a = Analysis(['horus-gui.py'], a = Analysis(['horus-gui.py'],
pathex=['/Users/darkside/Dev/horus-gui'], pathex=['.'],
binaries=[('../horusdemodlib/build/src/libhorus.dylib','.')], binaries=[('../horusdemodlib/build/src/libhorus.dylib','.')],
datas=[], datas=[],
hiddenimports=[], hiddenimports=[],
@ -38,4 +38,8 @@ coll = COLLECT(exe,
app = BUNDLE(coll, app = BUNDLE(coll,
name='horus-gui.app', name='horus-gui.app',
icon='doc/horus_logo.icns', icon='doc/horus_logo.icns',
bundle_identifier=None) bundle_identifier=None,
info_plist={
'NSMicrophoneUsageDescription': 'Horus-GUI needs audio access to receive telemetry.'
},
)

Wyświetl plik

@ -1 +1 @@
__version__ = "0.3.15" __version__ = "0.3.16"

Wyświetl plik

@ -48,6 +48,7 @@ def init_audio(widgets):
audioDevices[_name] = _dev audioDevices[_name] = _dev
# Add to audio device selection list. # Add to audio device selection list.
widgets["audioDeviceSelector"].addItem(_name) widgets["audioDeviceSelector"].addItem(_name)
logging.debug(f"Found audio device: {_name}")
# Select first item. # Select first item.
if len(list(audioDevices.keys())) > 0: if len(list(audioDevices.keys())) > 0:
@ -75,6 +76,8 @@ def populate_sample_rates(widgets):
widgets["audioSampleRateSelector"].addItem(str(48000)) widgets["audioSampleRateSelector"].addItem(str(48000))
widgets["audioSampleRateSelector"].setCurrentIndex(0) widgets["audioSampleRateSelector"].setCurrentIndex(0)
return
if _dev_name in audioDevices: if _dev_name in audioDevices:
# Determine which sample rates from a common list are valid for this device. # Determine which sample rates from a common list are valid for this device.
_possible_rates = [8000.0, 22050.0, 44100.0, 48000.0, 96000.0] _possible_rates = [8000.0, 22050.0, 44100.0, 48000.0, 96000.0]
@ -105,7 +108,7 @@ def populate_sample_rates(widgets):
_default_samp_rate = int(audioDevices[_dev_name]["defaultSampleRate"]) _default_samp_rate = int(audioDevices[_dev_name]["defaultSampleRate"])
widgets["audioSampleRateSelector"].setCurrentText(str(_default_samp_rate)) widgets["audioSampleRateSelector"].setCurrentText(str(_default_samp_rate))
else: else:
logging.error("Audio - Unknown Audio Device") logging.error(f"Audio - Unknown Audio Device ({_dev_name})")
class AudioStream(object): class AudioStream(object):

Wyświetl plik

@ -8,7 +8,6 @@ import json
import logging import logging
import os import os
from pyqtgraph.Qt import QtCore from pyqtgraph.Qt import QtCore
from ruamel.yaml import YAML
from . import __version__ from . import __version__
from .modem import populate_modem_settings from .modem import populate_modem_settings
from .audio import populate_sample_rates from .audio import populate_sample_rates
@ -77,7 +76,7 @@ def read_config(widgets):
global qt_settings, default_config global qt_settings, default_config
# This is getting a bit ridiculous, need to re-think this approach. # This is getting a bit ridiculous, need to re-think this approach.
OK_VERSIONS = [__version__, '0.3.14', '0.3.13', '0.3.12', '0.3.11', '0.3.10', '0.3.9', '0.3.8', '0.3.7', '0.3.6', '0.3.5', '0.3.4', '0.3.1', '0.2.1'] OK_VERSIONS = [__version__, '0.3.15', '0.3.14', '0.3.13', '0.3.12', '0.3.11', '0.3.10', '0.3.9', '0.3.8', '0.3.7', '0.3.6', '0.3.5', '0.3.4', '0.3.1', '0.2.1']
# Try and read in the version parameter from QSettings # Try and read in the version parameter from QSettings
if qt_settings.value("version") not in OK_VERSIONS: if qt_settings.value("version") not in OK_VERSIONS:

Wyświetl plik

@ -22,7 +22,8 @@ import time
import pyqtgraph as pg import pyqtgraph as pg
import numpy as np import numpy as np
from queue import Queue from queue import Queue
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets #from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
from PyQt5 import QtWidgets, QtGui
from pyqtgraph.dockarea import * from pyqtgraph.dockarea import *
from threading import Thread from threading import Thread
@ -107,7 +108,7 @@ logging.basicConfig(
pg.mkQApp() pg.mkQApp()
# GUI LAYOUT - Gtk Style! # GUI LAYOUT - Gtk Style!
win = QtGui.QMainWindow() win = QtWidgets.QMainWindow()
area = DockArea() area = DockArea()
win.setCentralWidget(area) win.setCentralWidget(area)
win.setWindowTitle(f"Horus Telemetry GUI - v{__version__}") win.setWindowTitle(f"Horus Telemetry GUI - v{__version__}")
@ -143,14 +144,14 @@ d0_habitat.raiseDock()
# Controls # Controls
w1_audio = pg.LayoutWidget() w1_audio = pg.LayoutWidget()
# TNC Connection # TNC Connection
widgets["audioDeviceLabel"] = QtGui.QLabel("<b>Audio Device:</b>") widgets["audioDeviceLabel"] = QtWidgets.QLabel("<b>Audio Device:</b>")
widgets["audioDeviceSelector"] = QtGui.QComboBox() widgets["audioDeviceSelector"] = QtWidgets.QComboBox()
widgets["audioSampleRateLabel"] = QtGui.QLabel("<b>Sample Rate (Hz):</b>") widgets["audioSampleRateLabel"] = QtWidgets.QLabel("<b>Sample Rate (Hz):</b>")
widgets["audioSampleRateSelector"] = QtGui.QComboBox() widgets["audioSampleRateSelector"] = QtWidgets.QComboBox()
widgets["audioDbfsLabel"] = QtGui.QLabel("<b>Input Level (dBFS):</b>") widgets["audioDbfsLabel"] = QtWidgets.QLabel("<b>Input Level (dBFS):</b>")
widgets["audioDbfsValue"] = QtGui.QLabel("--") widgets["audioDbfsValue"] = QtWidgets.QLabel("--")
widgets["audioDbfsValue_float"] = 0.0 widgets["audioDbfsValue_float"] = 0.0
w1_audio.addWidget(widgets["audioDeviceLabel"], 0, 0, 1, 1) w1_audio.addWidget(widgets["audioDeviceLabel"], 0, 0, 1, 1)
@ -165,29 +166,29 @@ w1_modem = pg.LayoutWidget()
# Modem Parameters # Modem Parameters
widgets["horusModemLabel"] = QtGui.QLabel("<b>Mode:</b>") widgets["horusModemLabel"] = QtWidgets.QLabel("<b>Mode:</b>")
widgets["horusModemSelector"] = QtGui.QComboBox() widgets["horusModemSelector"] = QtWidgets.QComboBox()
widgets["horusModemRateLabel"] = QtGui.QLabel("<b>Baudrate:</b>") widgets["horusModemRateLabel"] = QtWidgets.QLabel("<b>Baudrate:</b>")
widgets["horusModemRateSelector"] = QtGui.QComboBox() widgets["horusModemRateSelector"] = QtWidgets.QComboBox()
widgets["horusMaskEstimatorLabel"] = QtGui.QLabel("<b>Enable Mask Estim.:</b>") widgets["horusMaskEstimatorLabel"] = QtWidgets.QLabel("<b>Enable Mask Estim.:</b>")
widgets["horusMaskEstimatorSelector"] = QtGui.QCheckBox() widgets["horusMaskEstimatorSelector"] = QtWidgets.QCheckBox()
widgets["horusMaskEstimatorSelector"].setToolTip( widgets["horusMaskEstimatorSelector"].setToolTip(
"Enable the mask frequency estimator, which makes uses of the \n"\ "Enable the mask frequency estimator, which makes uses of the \n"\
"tone spacing value entered below as extra input to the frequency\n"\ "tone spacing value entered below as extra input to the frequency\n"\
"estimator. This can help decode performance in very weak signal conditions." "estimator. This can help decode performance in very weak signal conditions."
) )
widgets["horusMaskSpacingLabel"] = QtGui.QLabel("<b>Tone Spacing (Hz):</b>") widgets["horusMaskSpacingLabel"] = QtWidgets.QLabel("<b>Tone Spacing (Hz):</b>")
widgets["horusMaskSpacingEntry"] = QtGui.QLineEdit("270") widgets["horusMaskSpacingEntry"] = QtWidgets.QLineEdit("270")
widgets["horusMaskSpacingEntry"].setToolTip( widgets["horusMaskSpacingEntry"].setToolTip(
"If the tone spacing of the transmitter is known, it can be entered here,\n"\ "If the tone spacing of the transmitter is known, it can be entered here,\n"\
"and used with the mask estimator option above. The default tone spacing for\n"\ "and used with the mask estimator option above. The default tone spacing for\n"\
"a RS41-based transmitter is 270 Hz." "a RS41-based transmitter is 270 Hz."
) )
widgets["horusManualEstimatorLabel"] = QtGui.QLabel("<b>Manual Estim. Limits:</b>") widgets["horusManualEstimatorLabel"] = QtWidgets.QLabel("<b>Manual Estim. Limits:</b>")
widgets["horusManualEstimatorSelector"] = QtGui.QCheckBox() widgets["horusManualEstimatorSelector"] = QtWidgets.QCheckBox()
widgets["horusManualEstimatorSelector"].setToolTip( widgets["horusManualEstimatorSelector"].setToolTip(
"Enables manual selection of the frequency estimator limits. This will enable\n"\ "Enables manual selection of the frequency estimator limits. This will enable\n"\
"a slidable area on the spectrum display, which can be used to select the frequency\n"\ "a slidable area on the spectrum display, which can be used to select the frequency\n"\
@ -197,7 +198,7 @@ widgets["horusManualEstimatorSelector"].setToolTip(
) )
# Start/Stop # Start/Stop
widgets["startDecodeButton"] = QtGui.QPushButton("Start") widgets["startDecodeButton"] = QtWidgets.QPushButton("Start")
widgets["startDecodeButton"].setEnabled(False) widgets["startDecodeButton"].setEnabled(False)
w1_modem.addWidget(widgets["horusModemLabel"], 0, 0, 1, 1) w1_modem.addWidget(widgets["horusModemLabel"], 0, 0, 1, 1)
@ -217,48 +218,48 @@ d0_modem.addWidget(w1_modem)
w1_habitat = pg.LayoutWidget() w1_habitat = pg.LayoutWidget()
# Listener Information # Listener Information
widgets["habitatHeading"] = QtGui.QLabel("<b>SondeHub Settings</b>") widgets["habitatHeading"] = QtWidgets.QLabel("<b>SondeHub Settings</b>")
widgets["sondehubUploadLabel"] = QtGui.QLabel("<b>Enable SondeHub-Ham Upload:</b>") widgets["sondehubUploadLabel"] = QtWidgets.QLabel("<b>Enable SondeHub-Ham Upload:</b>")
widgets["sondehubUploadSelector"] = QtGui.QCheckBox() widgets["sondehubUploadSelector"] = QtWidgets.QCheckBox()
widgets["sondehubUploadSelector"].setChecked(True) widgets["sondehubUploadSelector"].setChecked(True)
widgets["userCallLabel"] = QtGui.QLabel("<b>Callsign:</b>") widgets["userCallLabel"] = QtWidgets.QLabel("<b>Callsign:</b>")
widgets["userCallEntry"] = QtGui.QLineEdit("N0CALL") widgets["userCallEntry"] = QtWidgets.QLineEdit("N0CALL")
widgets["userCallEntry"].setMaxLength(20) widgets["userCallEntry"].setMaxLength(20)
widgets["userCallEntry"].setToolTip( widgets["userCallEntry"].setToolTip(
"Your station callsign, which doesn't necessarily need to be an\n"\ "Your station callsign, which doesn't necessarily need to be an\n"\
"amateur radio callsign, just something unique!" "amateur radio callsign, just something unique!"
) )
widgets["userLocationLabel"] = QtGui.QLabel("<b>Lat/Lon:</b>") widgets["userLocationLabel"] = QtWidgets.QLabel("<b>Lat/Lon:</b>")
widgets["userLatEntry"] = QtGui.QLineEdit("0.0") widgets["userLatEntry"] = QtWidgets.QLineEdit("0.0")
widgets["userLatEntry"].setToolTip("Station Latitude in Decimal Degrees, e.g. -34.123456") widgets["userLatEntry"].setToolTip("Station Latitude in Decimal Degrees, e.g. -34.123456")
widgets["userLonEntry"] = QtGui.QLineEdit("0.0") widgets["userLonEntry"] = QtWidgets.QLineEdit("0.0")
widgets["userLonEntry"].setToolTip("Station Longitude in Decimal Degrees, e.g. 138.123456") widgets["userLonEntry"].setToolTip("Station Longitude in Decimal Degrees, e.g. 138.123456")
widgets["userAltitudeLabel"] = QtGui.QLabel("<b>Altitude:</b>") widgets["userAltitudeLabel"] = QtWidgets.QLabel("<b>Altitude:</b>")
widgets["userAltEntry"] = QtGui.QLineEdit("0.0") widgets["userAltEntry"] = QtWidgets.QLineEdit("0.0")
widgets["userAltEntry"].setToolTip("Station Altitude in Metres Above Sea Level.") widgets["userAltEntry"].setToolTip("Station Altitude in Metres Above Sea Level.")
widgets["userAntennaLabel"] = QtGui.QLabel("<b>Antenna:</b>") widgets["userAntennaLabel"] = QtWidgets.QLabel("<b>Antenna:</b>")
widgets["userAntennaEntry"] = QtGui.QLineEdit("") widgets["userAntennaEntry"] = QtWidgets.QLineEdit("")
widgets["userAntennaEntry"].setToolTip("A text description of your station's antenna.") widgets["userAntennaEntry"].setToolTip("A text description of your station's antenna.")
widgets["userRadioLabel"] = QtGui.QLabel("<b>Radio:</b>") widgets["userRadioLabel"] = QtWidgets.QLabel("<b>Radio:</b>")
widgets["userRadioEntry"] = QtGui.QLineEdit("Horus-GUI " + __version__) widgets["userRadioEntry"] = QtWidgets.QLineEdit("Horus-GUI " + __version__)
widgets["userRadioEntry"].setToolTip( widgets["userRadioEntry"].setToolTip(
"A text description of your station's radio setup.\n"\ "A text description of your station's radio setup.\n"\
"This field will be automatically prefixed with Horus-GUI." "This field will be automatically prefixed with Horus-GUI."
) )
widgets["habitatUploadPosition"] = QtGui.QPushButton("Re-upload Position") widgets["habitatUploadPosition"] = QtWidgets.QPushButton("Re-upload Position")
widgets["habitatUploadPosition"].setToolTip( widgets["habitatUploadPosition"].setToolTip(
"Manually re-upload your position information to SondeHub-Amateur.\n"\ "Manually re-upload your position information to SondeHub-Amateur.\n"\
"Note that it can take a few minutes for your new information to\n"\ "Note that it can take a few minutes for your new information to\n"\
"appear on the map." "appear on the map."
) )
widgets["dialFreqLabel"] = QtGui.QLabel("<b>Radio Dial Freq (MHz):</b>") widgets["dialFreqLabel"] = QtWidgets.QLabel("<b>Radio Dial Freq (MHz):</b>")
widgets["dialFreqEntry"] = QtGui.QLineEdit("") widgets["dialFreqEntry"] = QtWidgets.QLineEdit("")
widgets["dialFreqEntry"].setToolTip( widgets["dialFreqEntry"].setToolTip(
"Optional entry of your radio's dial frequency in MHz (e.g. 437.600).\n"\ "Optional entry of your radio's dial frequency in MHz (e.g. 437.600).\n"\
"Used to provide frequency information on SondeHub-Amateur."\ "Used to provide frequency information on SondeHub-Amateur."\
) )
widgets["saveSettingsButton"] = QtGui.QPushButton("Save Settings") widgets["saveSettingsButton"] = QtWidgets.QPushButton("Save Settings")
w1_habitat.addWidget(widgets["sondehubUploadLabel"], 0, 0, 1, 1) w1_habitat.addWidget(widgets["sondehubUploadLabel"], 0, 0, 1, 1)
w1_habitat.addWidget(widgets["sondehubUploadSelector"], 0, 1, 1, 1) w1_habitat.addWidget(widgets["sondehubUploadSelector"], 0, 1, 1, 1)
@ -282,54 +283,54 @@ w1_habitat.addWidget(widgets["saveSettingsButton"], 9, 0, 1, 3)
d0_habitat.addWidget(w1_habitat) d0_habitat.addWidget(w1_habitat)
w1_other = pg.LayoutWidget() w1_other = pg.LayoutWidget()
widgets["horusHeaderLabel"] = QtGui.QLabel("<b><u>Telemetry Forwarding</u></b>") widgets["horusHeaderLabel"] = QtWidgets.QLabel("<b><u>Telemetry Forwarding</u></b>")
widgets["horusUploadLabel"] = QtGui.QLabel("<b>Enable Horus UDP Output:</b>") widgets["horusUploadLabel"] = QtWidgets.QLabel("<b>Enable Horus UDP Output:</b>")
widgets["horusUploadSelector"] = QtGui.QCheckBox() widgets["horusUploadSelector"] = QtWidgets.QCheckBox()
widgets["horusUploadSelector"].setChecked(True) widgets["horusUploadSelector"].setChecked(True)
widgets["horusUploadSelector"].setToolTip( widgets["horusUploadSelector"].setToolTip(
"Enable output of 'Horus UDP' JSON messages. These are emitted as a JSON object\n"\ "Enable output of 'Horus UDP' JSON messages. These are emitted as a JSON object\n"\
"and contain the fields: callsign, time, latitude, longitude, altitude, snr"\ "and contain the fields: callsign, time, latitude, longitude, altitude, snr"\
) )
widgets["horusUDPLabel"] = QtGui.QLabel("<b>Horus UDP Port:</b>") widgets["horusUDPLabel"] = QtWidgets.QLabel("<b>Horus UDP Port:</b>")
widgets["horusUDPEntry"] = QtGui.QLineEdit("55672") widgets["horusUDPEntry"] = QtWidgets.QLineEdit("55672")
widgets["horusUDPEntry"].setMaxLength(5) widgets["horusUDPEntry"].setMaxLength(5)
widgets["horusUDPEntry"].setToolTip( widgets["horusUDPEntry"].setToolTip(
"UDP Port to output 'Horus UDP' JSON messages to." "UDP Port to output 'Horus UDP' JSON messages to."
) )
widgets["ozimuxUploadLabel"] = QtGui.QLabel("<b>Enable OziMux UDP Output:</b>") widgets["ozimuxUploadLabel"] = QtWidgets.QLabel("<b>Enable OziMux UDP Output:</b>")
widgets["ozimuxUploadSelector"] = QtGui.QCheckBox() widgets["ozimuxUploadSelector"] = QtWidgets.QCheckBox()
widgets["ozimuxUploadSelector"].setChecked(False) widgets["ozimuxUploadSelector"].setChecked(False)
widgets["ozimuxUploadSelector"].setToolTip( widgets["ozimuxUploadSelector"].setToolTip(
"Output OziMux UDP messages. These are of the form:\n"\ "Output OziMux UDP messages. These are of the form:\n"\
"'TELEMETRY,HH:MM:SS,lat,lon,alt\\n'" "'TELEMETRY,HH:MM:SS,lat,lon,alt\\n'"
) )
widgets["ozimuxUDPLabel"] = QtGui.QLabel("<b>Ozimux UDP Port:</b>") widgets["ozimuxUDPLabel"] = QtWidgets.QLabel("<b>Ozimux UDP Port:</b>")
widgets["ozimuxUDPEntry"] = QtGui.QLineEdit("55683") widgets["ozimuxUDPEntry"] = QtWidgets.QLineEdit("55683")
widgets["ozimuxUDPEntry"].setMaxLength(5) widgets["ozimuxUDPEntry"].setMaxLength(5)
widgets["ozimuxUDPEntry"].setToolTip( widgets["ozimuxUDPEntry"].setToolTip(
"UDP Port to output 'OziMux' UDP messages to." "UDP Port to output 'OziMux' UDP messages to."
) )
widgets["loggingHeaderLabel"] = QtGui.QLabel("<b><u>Logging</u></b>") widgets["loggingHeaderLabel"] = QtWidgets.QLabel("<b><u>Logging</u></b>")
widgets["enableLoggingLabel"] = QtGui.QLabel("<b>Enable Logging:</b>") widgets["enableLoggingLabel"] = QtWidgets.QLabel("<b>Enable Logging:</b>")
widgets["enableLoggingSelector"] = QtGui.QCheckBox() widgets["enableLoggingSelector"] = QtWidgets.QCheckBox()
widgets["enableLoggingSelector"].setChecked(False) widgets["enableLoggingSelector"].setChecked(False)
widgets["enableLoggingSelector"].setToolTip( widgets["enableLoggingSelector"].setToolTip(
"Enable logging of received telemetry to disk (JSON)" "Enable logging of received telemetry to disk (JSON)"
) )
widgets["loggingFormatLabel"] = QtGui.QLabel("<b>Log Format:</b>") widgets["loggingFormatLabel"] = QtWidgets.QLabel("<b>Log Format:</b>")
widgets["loggingFormatSelector"] = QtGui.QComboBox() widgets["loggingFormatSelector"] = QtWidgets.QComboBox()
widgets["loggingFormatSelector"].addItem("CSV") widgets["loggingFormatSelector"].addItem("CSV")
widgets["loggingFormatSelector"].addItem("JSON") widgets["loggingFormatSelector"].addItem("JSON")
widgets["loggingPathLabel"] = QtGui.QLabel("<b>Log Directory:</b>") widgets["loggingPathLabel"] = QtWidgets.QLabel("<b>Log Directory:</b>")
widgets["loggingPathEntry"] = QtGui.QLineEdit("") widgets["loggingPathEntry"] = QtWidgets.QLineEdit("")
widgets["loggingPathEntry"].setToolTip( widgets["loggingPathEntry"].setToolTip(
"Logging Directory" "Logging Directory"
) )
widgets["selectLogDirButton"] = QtGui.QPushButton("Select Directory") widgets["selectLogDirButton"] = QtWidgets.QPushButton("Select Directory")
widgets["otherHeaderLabel"] = QtGui.QLabel("<b><u>Other Settings</u></b>") widgets["otherHeaderLabel"] = QtWidgets.QLabel("<b><u>Other Settings</u></b>")
widgets["inhibitCRCLabel"] = QtGui.QLabel("<b>Hide Failed CRC Errors:</b>") widgets["inhibitCRCLabel"] = QtWidgets.QLabel("<b>Hide Failed CRC Errors:</b>")
widgets["inhibitCRCSelector"] = QtGui.QCheckBox() widgets["inhibitCRCSelector"] = QtWidgets.QCheckBox()
widgets["inhibitCRCSelector"].setChecked(True) widgets["inhibitCRCSelector"].setChecked(True)
widgets["inhibitCRCSelector"].setToolTip( widgets["inhibitCRCSelector"].setToolTip(
"Hide CRC Failed error messages." "Hide CRC Failed error messages."
@ -361,41 +362,41 @@ d0_other.addWidget(w1_other)
w1_rotator = pg.LayoutWidget() w1_rotator = pg.LayoutWidget()
widgets["rotatorHeaderLabel"] = QtGui.QLabel("<b><u>Rotator Control</u></b>") widgets["rotatorHeaderLabel"] = QtWidgets.QLabel("<b><u>Rotator Control</u></b>")
widgets["rotatorTypeLabel"] = QtGui.QLabel("<b>Rotator Type:</b>") widgets["rotatorTypeLabel"] = QtWidgets.QLabel("<b>Rotator Type:</b>")
widgets["rotatorTypeSelector"] = QtGui.QComboBox() widgets["rotatorTypeSelector"] = QtWidgets.QComboBox()
widgets["rotatorTypeSelector"].addItem("rotctld") widgets["rotatorTypeSelector"].addItem("rotctld")
widgets["rotatorTypeSelector"].addItem("PSTRotator") widgets["rotatorTypeSelector"].addItem("PSTRotator")
widgets["rotatorHostLabel"] = QtGui.QLabel("<b>Rotator Hostname:</b>") widgets["rotatorHostLabel"] = QtWidgets.QLabel("<b>Rotator Hostname:</b>")
widgets["rotatorHostEntry"] = QtGui.QLineEdit("localhost") widgets["rotatorHostEntry"] = QtWidgets.QLineEdit("localhost")
widgets["rotatorHostEntry"].setToolTip( widgets["rotatorHostEntry"].setToolTip(
"Hostname of the rotctld or PSTRotator Server.\n"\ "Hostname of the rotctld or PSTRotator Server.\n"\
) )
widgets["rotatorPortLabel"] = QtGui.QLabel("<b>Rotator TCP/UDP Port:</b>") widgets["rotatorPortLabel"] = QtWidgets.QLabel("<b>Rotator TCP/UDP Port:</b>")
widgets["rotatorPortEntry"] = QtGui.QLineEdit("4533") widgets["rotatorPortEntry"] = QtWidgets.QLineEdit("4533")
widgets["rotatorPortEntry"].setMaxLength(5) widgets["rotatorPortEntry"].setMaxLength(5)
widgets["rotatorPortEntry"].setToolTip( widgets["rotatorPortEntry"].setToolTip(
"TCP (rotctld) or UDP (PSTRotator) port to connect to.\n"\ "TCP (rotctld) or UDP (PSTRotator) port to connect to.\n"\
"Default for rotctld: 4533\n"\ "Default for rotctld: 4533\n"\
"Default for PSTRotator: 12000" "Default for PSTRotator: 12000"
) )
widgets["rotatorThresholdLabel"] = QtGui.QLabel("<b>Rotator Movement Threshold:</b>") widgets["rotatorThresholdLabel"] = QtWidgets.QLabel("<b>Rotator Movement Threshold:</b>")
widgets["rotatorThresholdEntry"] = QtGui.QLineEdit("5.0") widgets["rotatorThresholdEntry"] = QtWidgets.QLineEdit("5.0")
widgets["rotatorThresholdEntry"].setToolTip( widgets["rotatorThresholdEntry"].setToolTip(
"Only move if the angle between the payload position and \n"\ "Only move if the angle between the payload position and \n"\
"the current rotator position is more than this, in degrees." "the current rotator position is more than this, in degrees."
) )
widgets["rotatorConnectButton"] = QtGui.QPushButton("Start") widgets["rotatorConnectButton"] = QtWidgets.QPushButton("Start")
widgets["rotatorCurrentStatusLabel"] = QtGui.QLabel("<b>Status:</b>") widgets["rotatorCurrentStatusLabel"] = QtWidgets.QLabel("<b>Status:</b>")
widgets["rotatorCurrentStatusValue"] = QtGui.QLabel("Not Started.") widgets["rotatorCurrentStatusValue"] = QtWidgets.QLabel("Not Started.")
widgets["rotatorCurrentPositionLabel"] = QtGui.QLabel("<b>Commanded Az/El:</b>") widgets["rotatorCurrentPositionLabel"] = QtWidgets.QLabel("<b>Commanded Az/El:</b>")
widgets["rotatorCurrentPositionValue"] = QtGui.QLabel("---˚, --˚") widgets["rotatorCurrentPositionValue"] = QtWidgets.QLabel("---˚, --˚")
@ -429,25 +430,25 @@ widgets["spectrumPlotData"] = widgets["spectrumPlot"].plot([0])
widgets["estimatorLines"] = [ widgets["estimatorLines"] = [
pg.InfiniteLine( pg.InfiniteLine(
pos=-1000, pos=-1000,
pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.DashLine), pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.PenStyle.DashLine),
label="F1", label="F1",
labelOpts={'position':0.9} labelOpts={'position':0.9}
), ),
pg.InfiniteLine( pg.InfiniteLine(
pos=-1000, pos=-1000,
pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.DashLine), pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.PenStyle.DashLine),
label="F2", label="F2",
labelOpts={'position':0.9} labelOpts={'position':0.9}
), ),
pg.InfiniteLine( pg.InfiniteLine(
pos=-1000, pos=-1000,
pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.DashLine), pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.PenStyle.DashLine),
label="F3", label="F3",
labelOpts={'position':0.9} labelOpts={'position':0.9}
), ),
pg.InfiniteLine( pg.InfiniteLine(
pos=-1000, pos=-1000,
pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.DashLine), pen=pg.mkPen(color="w", width=2, style=QtCore.Qt.PenStyle.DashLine),
label="F4", label="F4",
labelOpts={'position':0.9} labelOpts={'position':0.9}
), ),
@ -472,13 +473,13 @@ widgets["spectrumPlotRange"] = [-100, -20]
w3_stats = pg.LayoutWidget() w3_stats = pg.LayoutWidget()
widgets["snrBar"] = QtWidgets.QProgressBar() widgets["snrBar"] = QtWidgets.QProgressBar()
widgets["snrBar"].setOrientation(QtCore.Qt.Vertical) widgets["snrBar"].setOrientation(QtCore.Qt.Orientation.Vertical)
widgets["snrBar"].setRange(-10, 15) widgets["snrBar"].setRange(-10, 15)
widgets["snrBar"].setValue(-10) widgets["snrBar"].setValue(-10)
widgets["snrBar"].setTextVisible(False) widgets["snrBar"].setTextVisible(False)
widgets["snrBar"].setAlignment(QtCore.Qt.AlignCenter) widgets["snrBar"].setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
widgets["snrLabel"] = QtGui.QLabel("--.-") widgets["snrLabel"] = QtWidgets.QLabel("--.-")
widgets["snrLabel"].setAlignment(QtCore.Qt.AlignCenter); widgets["snrLabel"].setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter);
widgets["snrLabel"].setFont(QtGui.QFont("Courier New", 14)) widgets["snrLabel"].setFont(QtGui.QFont("Courier New", 14))
w3_stats.addWidget(widgets["snrBar"], 0, 1, 1, 1) w3_stats.addWidget(widgets["snrBar"], 0, 1, 1, 1)
w3_stats.addWidget(widgets["snrLabel"], 1, 0, 1, 3) w3_stats.addWidget(widgets["snrLabel"], 1, 0, 1, 3)
@ -513,14 +514,14 @@ d2_snr.addWidget(widgets["snrPlot"])
# Telemetry Data # Telemetry Data
w4_data = pg.LayoutWidget() w4_data = pg.LayoutWidget()
widgets["latestRawSentenceLabel"] = QtGui.QLabel("<b>Latest Packet (Raw):</b>") widgets["latestRawSentenceLabel"] = QtWidgets.QLabel("<b>Latest Packet (Raw):</b>")
widgets["latestRawSentenceData"] = QtGui.QLineEdit("NO DATA") widgets["latestRawSentenceData"] = QtWidgets.QLineEdit("NO DATA")
widgets["latestRawSentenceData"].setReadOnly(True) widgets["latestRawSentenceData"].setReadOnly(True)
widgets["latestDecodedSentenceLabel"] = QtGui.QLabel("<b>Latest Packet (Decoded):</b>") widgets["latestDecodedSentenceLabel"] = QtWidgets.QLabel("<b>Latest Packet (Decoded):</b>")
widgets["latestDecodedSentenceData"] = QtGui.QLineEdit("NO DATA") widgets["latestDecodedSentenceData"] = QtWidgets.QLineEdit("NO DATA")
widgets["latestDecodedSentenceData"].setReadOnly(True) widgets["latestDecodedSentenceData"].setReadOnly(True)
widgets["latestDecodedAgeLabel"] = QtGui.QLabel("<b>Last Packet Age:</b>") widgets["latestDecodedAgeLabel"] = QtWidgets.QLabel("<b>Last Packet Age:</b>")
widgets["latestDecodedAgeData"] = QtGui.QLabel("No packet yet!") widgets["latestDecodedAgeData"] = QtWidgets.QLabel("No packet yet!")
w4_data.addWidget(widgets["latestRawSentenceLabel"], 0, 0, 1, 1) w4_data.addWidget(widgets["latestRawSentenceLabel"], 0, 0, 1, 1)
w4_data.addWidget(widgets["latestRawSentenceData"], 0, 1, 1, 6) w4_data.addWidget(widgets["latestRawSentenceData"], 0, 1, 1, 6)
w4_data.addWidget(widgets["latestDecodedSentenceLabel"], 1, 0, 1, 1) w4_data.addWidget(widgets["latestDecodedSentenceLabel"], 1, 0, 1, 1)
@ -536,30 +537,30 @@ if 'Windows' in platform.system():
else: else:
POSITION_LABEL_FONT_SIZE = 16 POSITION_LABEL_FONT_SIZE = 16
widgets["latestPacketCallsignLabel"] = QtGui.QLabel("<b>Callsign</b>") widgets["latestPacketCallsignLabel"] = QtWidgets.QLabel("<b>Callsign</b>")
widgets["latestPacketCallsignValue"] = QtGui.QLabel("---") widgets["latestPacketCallsignValue"] = QtWidgets.QLabel("---")
widgets["latestPacketCallsignValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketCallsignValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketTimeLabel"] = QtGui.QLabel("<b>Time</b>") widgets["latestPacketTimeLabel"] = QtWidgets.QLabel("<b>Time</b>")
widgets["latestPacketTimeValue"] = QtGui.QLabel("---") widgets["latestPacketTimeValue"] = QtWidgets.QLabel("---")
widgets["latestPacketTimeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketTimeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketLatitudeLabel"] = QtGui.QLabel("<b>Latitude</b>") widgets["latestPacketLatitudeLabel"] = QtWidgets.QLabel("<b>Latitude</b>")
widgets["latestPacketLatitudeValue"] = QtGui.QLabel("---") widgets["latestPacketLatitudeValue"] = QtWidgets.QLabel("---")
widgets["latestPacketLatitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketLatitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketLongitudeLabel"] = QtGui.QLabel("<b>Longitude</b>") widgets["latestPacketLongitudeLabel"] = QtWidgets.QLabel("<b>Longitude</b>")
widgets["latestPacketLongitudeValue"] = QtGui.QLabel("---") widgets["latestPacketLongitudeValue"] = QtWidgets.QLabel("---")
widgets["latestPacketLongitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketLongitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketAltitudeLabel"] = QtGui.QLabel("<b>Altitude</b>") widgets["latestPacketAltitudeLabel"] = QtWidgets.QLabel("<b>Altitude</b>")
widgets["latestPacketAltitudeValue"] = QtGui.QLabel("---") widgets["latestPacketAltitudeValue"] = QtWidgets.QLabel("---")
widgets["latestPacketAltitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketAltitudeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketBearingLabel"] = QtGui.QLabel("<b>Bearing</b>") widgets["latestPacketBearingLabel"] = QtWidgets.QLabel("<b>Bearing</b>")
widgets["latestPacketBearingValue"] = QtGui.QLabel("---") widgets["latestPacketBearingValue"] = QtWidgets.QLabel("---")
widgets["latestPacketBearingValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketBearingValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketElevationLabel"] = QtGui.QLabel("<b>Elevation</b>") widgets["latestPacketElevationLabel"] = QtWidgets.QLabel("<b>Elevation</b>")
widgets["latestPacketElevationValue"] = QtGui.QLabel("---") widgets["latestPacketElevationValue"] = QtWidgets.QLabel("---")
widgets["latestPacketElevationValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketElevationValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
widgets["latestPacketRangeLabel"] = QtGui.QLabel("<b>Range (km)</b>") widgets["latestPacketRangeLabel"] = QtWidgets.QLabel("<b>Range (km)</b>")
widgets["latestPacketRangeValue"] = QtGui.QLabel("---") widgets["latestPacketRangeValue"] = QtWidgets.QLabel("---")
widgets["latestPacketRangeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Bold)) widgets["latestPacketRangeValue"].setFont(QtGui.QFont("Courier New", POSITION_LABEL_FONT_SIZE, QtGui.QFont.Weight.Bold))
w4_position.addWidget(widgets["latestPacketCallsignLabel"], 0, 0, 1, 2) w4_position.addWidget(widgets["latestPacketCallsignLabel"], 0, 0, 1, 2)
w4_position.addWidget(widgets["latestPacketCallsignValue"], 1, 0, 1, 2) w4_position.addWidget(widgets["latestPacketCallsignValue"], 1, 0, 1, 2)
@ -1060,7 +1061,7 @@ def handle_new_packet(frame):
telemetry_logger.add(_decoded) telemetry_logger.add(_decoded)
# Try and force a refresh of the displays. # Try and force a refresh of the displays.
QtGui.QApplication.processEvents() QtWidgets.QApplication.processEvents()
@ -1264,7 +1265,7 @@ def processQueues():
widgets['latestDecodedAgeData'].setText(f"{_time_delta_hours:02d}:{_time_delta_minutes:02d}:{_time_delta_seconds:02d}") widgets['latestDecodedAgeData'].setText(f"{_time_delta_hours:02d}:{_time_delta_minutes:02d}:{_time_delta_seconds:02d}")
# Try and force a re-draw. # Try and force a re-draw.
QtGui.QApplication.processEvents() QtWidgets.QApplication.processEvents()
if not decoder_init: if not decoder_init:
# Initialise decoders, and other libraries here. # Initialise decoders, and other libraries here.
@ -1373,7 +1374,7 @@ logging.info("Started GUI.")
def main(): def main():
# Start the Qt Loop # Start the Qt Loop
if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"): if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"):
QtGui.QApplication.instance().exec_() QtWidgets.QApplication.instance().exec()
save_config(widgets) save_config(widgets)
try: try:

Wyświetl plik

@ -1,9 +1,9 @@
# Useful widgets # Useful widgets
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets from PyQt5 import QtWidgets
# Useful class for adding horizontal lines. # Useful class for adding horizontal lines.
class QHLine(QtGui.QFrame): class QHLine(QtWidgets.QFrame):
def __init__(self): def __init__(self):
super(QHLine, self).__init__() super(QHLine, self).__init__()
self.setFrameShape(QtGui.QFrame.HLine) self.setFrameShape(QtWidgets.QFrame.HLine)
self.setFrameShadow(QtGui.QFrame.Sunken) self.setFrameShadow(QtWidgets.QFrame.Sunken)

Wyświetl plik

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "horusgui" name = "horusgui"
version = "0.3.15" version = "0.3.16"
description = "" description = ""
authors = ["Mark Jessop <vk5qi@rfhead.net>"] authors = ["Mark Jessop <vk5qi@rfhead.net>"]
@ -8,10 +8,9 @@ authors = ["Mark Jessop <vk5qi@rfhead.net>"]
python = "^3.6" python = "^3.6"
requests = "^2.24.0" requests = "^2.24.0"
crcmod = "^1.7" crcmod = "^1.7"
PyQt5 = "^5.13.0" PyQt5 = "^5.15.0"
pyqtgraph = "^0.11.0" pyqtgraph = "^0.12.3"
pyaudio = "^0.2.11" pyaudio = "^0.2.11"
"ruamel.yaml" = "^0.16.10"
horusdemodlib = "^0.3.13" horusdemodlib = "^0.3.13"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]

Wyświetl plik

@ -2,7 +2,6 @@ numpy
pyaudio pyaudio
crcmod crcmod
PyQt5 PyQt5
pyqtgraph==0.12.4 pyqtgraph
ruamel.yaml
requests requests
horusdemodlib>=0.3.12 horusdemodlib>=0.3.12