Updates to support v2 telemetry

pyqt6
Mark Jessop 2021-09-04 19:17:45 +09:30
rodzic 38628217be
commit 6becf68ebf
6 zmienionych plików z 45 dodań i 20 usunięć

Wyświetl plik

@ -3,10 +3,10 @@
Telemetry demodulator for the following modems in use by Project Horus
* Horus Binary Modes (4FSK)
* v1 - Legacy 22 byte mode, Golay(23,12) FEC
* v2 - 16/32-byte modes, LDPC FEC (Under development)
* v2 - 32-byte mode, Golay(23,12) FEC
* RTTY (7N1, 7N2 and 8N2, standard [UKHAS sentences](https://ukhas.org.uk/communication:protocol) with CRC16 only)
This project serves as a graphical front-end to [horusdemodlib](https://github.com/projecthorus/horusdemodlib) a Python/C library of telemetry demodulators based off the [codec2](https://github.com/drowe67/codec2) FSK modem. The core modem used in this library is very well tested, and performs in line with incoherent FSK demodulator theory. The RTTY decoder is approximately [2dB better](http://www.rowetel.com/?p=5906) than dl-fldigi, and the Horus Binary v1 modem approximately 7 dB better again. Once finished, the Horus Binary v2 modes should provide more flexibility over the v1 mode, and provide further performance improvements.
This project serves as a graphical front-end to [horusdemodlib](https://github.com/projecthorus/horusdemodlib) a Python/C library of telemetry demodulators based off the [codec2](https://github.com/drowe67/codec2) FSK modem. The core modem used in this library is very well tested, and performs in line with incoherent FSK demodulator theory. The RTTY decoder is approximately [2dB better](http://www.rowetel.com/?p=5906) than dl-fldigi, and the Horus Binary modem approximately 7 dB better again. The Horus Binary v2 mode provides some additional flexibility over the v1 mode, allowing the addition of custom telemetry fields.
### Important Performance Notes
The FSK demodulator at the core of this application expects the transmitter to behave like a modem. That is, it should:
@ -25,7 +25,6 @@ Written by:
* Python Library - Mark Jessop <vk5qi@rfhead.net>
* FSK Modem - [David Rowe](http://rowetel.com)
* FSK Modem Python Wrapper - [XSSFox](https://twitter.com/xssfox)
* LDPC Codes - [Bill Cowley](http://lowsnr.org/)
![Screenshot](doc/horusgui_screenshot.png)

Wyświetl plik

@ -1 +1 @@
__version__ = "0.1.17"
__version__ = "0.2.1"

Wyświetl plik

@ -12,7 +12,7 @@ from ruamel.yaml import YAML
from . import __version__
from .modem import populate_modem_settings
from .audio import populate_sample_rates
from horusdemodlib.payloads import download_latest_payload_id_list, download_latest_custom_field_list
from horusdemodlib.payloads import download_latest_payload_id_list, download_latest_custom_field_list, read_payload_list, read_custom_field_list
import horusdemodlib.payloads
default_config = {
@ -69,7 +69,7 @@ def read_config(widgets):
""" Read in configuration settings from Qt """
global qt_settings, default_config
OK_VERSIONS = [__version__, "0.1.15", "0.1.14"]
OK_VERSIONS = [__version__]
# Try and read in the version parameter from QSettings
if qt_settings.value("version") not in OK_VERSIONS:
@ -153,19 +153,24 @@ def save_config(widgets):
write_config()
def init_payloads():
def init_payloads(payload_id_list=None, custom_field_list=None):
""" Attempt to download the latest payload / config data, and update local configs """
global default_config
# Attempt to grab the payload list.
_payload_list = download_latest_payload_id_list(timeout=3)
if payload_id_list is None:
_payload_list = download_latest_payload_id_list(timeout=3)
else:
logging.info(f"Using supplied Payload ID list file: {payload_id_list}")
_payload_list = read_payload_list(payload_id_list)
if _payload_list:
# Sanity check the result
if 0 in _payload_list:
horusdemodlib.payloads.HORUS_PAYLOAD_LIST = _payload_list
logging.info(f"Updated Payload List Successfuly!")
else:
logging.critical("Could not read downloaded payload list!")
logging.critical("Could not read payload list!")
else:
if 'payload_list' in default_config:
# Maybe we have a stored config we can use.
@ -183,20 +188,25 @@ def init_payloads():
logging.info(f"Payload List contains {len(list(horusdemodlib.payloads.HORUS_PAYLOAD_LIST.keys()))} entries.")
_custom_fields = download_latest_custom_field_list(timeout=3)
if custom_field_list is None:
_custom_fields = download_latest_custom_field_list(timeout=3)
else:
logging.info(f"Using supplied Custom Field List file: {custom_field_list}")
_custom_fields = read_custom_field_list(custom_field_list)
if _custom_fields:
# Sanity Check
if 'HORUSTEST' in _custom_fields:
if '4FSKTEST-V2' in _custom_fields:
horusdemodlib.payloads.HORUS_CUSTOM_FIELDS = _custom_fields
logging.info(f"Updated Custom Field List Successfuly!")
else:
logging.critical("Could not read downloaded custom field list!")
logging.critical("Could not read custom field list!")
else:
if 'custom_field_list' in default_config:
# Maybe we have a stored config we can use.
try:
_custom_fields = json.loads(default_config['custom_field_list'])
if 'HORUSTEST' in _custom_fields:
if '4FSKTEST-V2' in _custom_fields:
horusdemodlib.payloads.HORUS_CUSTOM_FIELDS = _custom_fields
logging.warning("Loaded Custom Fields List from local cache, may be out of date!")
else:

Wyświetl plik

@ -13,6 +13,7 @@ if sys.version_info < (3, 0):
print("This script requires Python 3!")
sys.exit(1)
import argparse
import datetime
import glob
import logging
@ -39,8 +40,6 @@ from horusdemodlib.payloads import *
from horusdemodlib.horusudp import send_payload_summary, send_ozimux_message
from . import __version__
# Setup Logging
logging.basicConfig(format="%(asctime)s %(levelname)s: %(message)s", level=logging.INFO)
# A few hardcoded defaults
DEFAULT_ESTIMATOR_MIN = 100
@ -69,6 +68,23 @@ decoder_init = False
# Global running indicator
running = False
# Read command-line arguments
parser = argparse.ArgumentParser(description="Project Horus GUI", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--payload-id-list", type=str, default=None, help="Use supplied Payload ID List instead of downloading a new one.")
parser.add_argument("--custom-field-list", type=str, default=None, help="Use supplied Custom Field List instead of downloading a new one.")
parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose output (set logging level to DEBUG)")
args = parser.parse_args()
if args.verbose:
_log_level = logging.DEBUG
else:
_log_level = logging.INFO
# Setup Logging
logging.basicConfig(
format="%(asctime)s %(levelname)s: %(message)s", level=_log_level
)
#
# GUI Creation - The Bad way.
#
@ -914,7 +930,7 @@ def handle_log_update(log_update):
# GUI Update Loop
def processQueues():
""" Read in data from the queues, this decouples the GUI and async inputs somewhat. """
global fft_update_queue, status_update_queue, decoder_init, widgets
global fft_update_queue, status_update_queue, decoder_init, widgets, args
while fft_update_queue.qsize() > 0:
_data = fft_update_queue.get()
@ -936,7 +952,7 @@ def processQueues():
if not decoder_init:
# Initialise decoders, and other libraries here.
init_payloads()
init_payloads(payload_id_list = args.payload_id_list, custom_field_list = args.custom_field_list)
decoder_init = True
# Once initialised, enable the start button
widgets["startDecodeButton"].setEnabled(True)

Wyświetl plik

@ -1,6 +1,6 @@
[tool.poetry]
name = "horusgui"
version = "0.1.17"
version = "0.2.1"
description = ""
authors = ["Mark Jessop <vk5qi@rfhead.net>"]
@ -12,7 +12,7 @@ PyQt5 = "^5.13.0"
pyqtgraph = "^0.11.0"
pyaudio = "^0.2.11"
"ruamel.yaml" = "^0.16.10"
horusdemodlib = "^0.1.21"
horusdemodlib = "^0.2.2"
[tool.poetry.dev-dependencies]

Wyświetl plik

@ -5,4 +5,4 @@ PyQt5
pyqtgraph
ruamel.yaml
requests
horusdemodlib>=0.1.21
horusdemodlib>=0.2.2