From c16ec8ef0d62913ef6c8ca621e34f34da45ba5a6 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Wed, 28 Feb 2024 23:21:11 +0100 Subject: [PATCH 1/8] JT4 enablement --- CHANGELOG.md | 1 + README.md | 2 +- docker.sh | 2 +- htdocs/lib/DemodulatorPanel.js | 4 ++-- htdocs/lib/MessagePanel.js | 4 ++-- owrx/config/defaults.py | 1 + owrx/controllers/settings/decoding.py | 7 +++++- owrx/dsp.py | 2 +- owrx/modes.py | 1 + owrx/reporting/pskreporter.py | 2 +- owrx/service/__init__.py | 2 +- owrx/wsjt.py | 31 +++++++++++++++++++++++++++ 12 files changed, 49 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a583fd0f..4ecf6362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Added support for the MSK144 digimode - Added support for decoding ADS-B with dump1090 - Added support for decoding HFDL and VDL2 aircraft communications +- Added support for JT4 modes - Added decoding of ISM band transmissions using rtl_433 - Added support for decoding RDS data on WFM broadcasts using redsea decoder - Added decoding for DAB broadcast stations using csdr-eti and dablin diff --git a/README.md b/README.md index f8ed6b87..ebd29d1a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ It has the following features: - Multiple SDR devices can be used simultaneously - [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag, D-Star, NXDN) - [wsjt-x](https://wsjt.sourceforge.io/) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4, - FST4W) + FST4W, JT4) - [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets - [JS8Call](http://js8call.com/) support - [DRM](https://github.com/jketterl/openwebrx/wiki/DRM-demodulator-notes) support diff --git a/docker.sh b/docker.sh index b3657af6..d40abaf4 100755 --- a/docker.sh +++ b/docker.sh @@ -94,4 +94,4 @@ case ${1:-} in *) usage ;; -esac \ No newline at end of file +esac diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js index 6f35e6b7..fda0929d 100644 --- a/htdocs/lib/DemodulatorPanel.js +++ b/htdocs/lib/DemodulatorPanel.js @@ -167,7 +167,7 @@ DemodulatorPanel.prototype.updatePanels = function() { var mode = Modes.findByModulation(modulation); toggle_panel("openwebrx-panel-digimodes", modulation && (!mode || mode.secondaryFft)); // WSJT-X modes share the same panel - toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0); + toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'jt4', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0); // these modes come with their own ['js8', 'packet', 'pocsag', 'adsb', 'ism', 'hfdl', 'vdl2'].forEach(function(m) { toggle_panel('openwebrx-panel-' + m + '-message', modulation === m); @@ -382,4 +382,4 @@ $.fn.demodulatorPanel = function(){ this.data('panel', new DemodulatorPanel(this)); } return this.data('panel'); -}; \ No newline at end of file +}; diff --git a/htdocs/lib/MessagePanel.js b/htdocs/lib/MessagePanel.js index 0bb2d5ac..ac3e089a 100644 --- a/htdocs/lib/MessagePanel.js +++ b/htdocs/lib/MessagePanel.js @@ -59,7 +59,7 @@ MessagePanel.prototype.scrollToBottom = function() { function WsjtMessagePanel(el) { MessagePanel.call(this, el); this.initClearTimer(); - this.qsoModes = ['FT8', 'JT65', 'JT9', 'FT4', 'FST4', 'Q65', 'MSK144']; + this.qsoModes = ['FT8', 'JT65', 'JT9', 'JT4', 'FT4', 'FST4', 'Q65', 'MSK144']; this.beaconModes = ['WSPR', 'FST4W']; this.modes = [].concat(this.qsoModes, this.beaconModes); } @@ -809,4 +809,4 @@ $.fn.vdl2MessagePanel = function() { this.data('panel', new Vdl2MessagePanel(this)); } return this.data('panel'); -}; \ No newline at end of file +}; diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 3f9be5d0..0f97a199 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -155,6 +155,7 @@ defaultConfig = PropertyLayer( wsjt_decoding_depths=PropertyLayer(jt65=1), fst4_enabled_intervals=[15, 30], fst4w_enabled_intervals=[120, 300], + jt4_enabled_submodes=["F", "G"], q65_enabled_combinations=["A30", "E120", "C60"], js8_enabled_profiles=["normal", "slow"], js8_decoding_depth=3, diff --git a/owrx/controllers/settings/decoding.py b/owrx/controllers/settings/decoding.py index 480b0e9b..24f32ae8 100644 --- a/owrx/controllers/settings/decoding.py +++ b/owrx/controllers/settings/decoding.py @@ -4,7 +4,7 @@ from owrx.form.input import CheckboxInput, NumberInput, DropdownInput, Js8Profil from owrx.form.input.wfm import WfmTauValues from owrx.form.input.wsjt import Q65ModeMatrix, WsjtDecodingDepthsInput from owrx.form.input.converter import OptionalConverter -from owrx.wsjt import Fst4Profile, Fst4wProfile +from owrx.wsjt import Fst4Profile, Fst4wProfile, JT4Profile from owrx.breadcrumb import Breadcrumb, BreadcrumbItem @@ -90,6 +90,11 @@ class DecodingSettingsController(SettingsFormController): "Enabled FST4W intervals", [Option(v, "{}s".format(v)) for v in Fst4wProfile.availableIntervals], ), + MultiCheckboxInput( + "jt4_enabled_submodes", + "Enabled JT4 Submodes", + [Option(v, "{}".format(v)) for v in JT4Profile.availableSubmodes], + ), Q65ModeMatrix("q65_enabled_combinations", "Enabled Q65 Mode combinations"), ), ] diff --git a/owrx/dsp.py b/owrx/dsp.py index 625254ea..08eefc5f 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -611,7 +611,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient) def _getSecondaryDemodulator(self, mod) -> Optional[SecondaryDemodulator]: if isinstance(mod, SecondaryDemodulator): return mod - if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]: + if mod in ["ft8", "wspr", "jt65", "jt9", "jt4", "ft4", "fst4", "fst4w", "q65"]: from csdr.chain.digimodes import AudioChopperDemodulator from owrx.wsjt import WsjtParser return AudioChopperDemodulator(mod, WsjtParser()) diff --git a/owrx/modes.py b/owrx/modes.py index f5ea047e..934b6961 100644 --- a/owrx/modes.py +++ b/owrx/modes.py @@ -147,6 +147,7 @@ class Modes(object): WsjtMode("wspr", "WSPR", bandpass=Bandpass(1350, 1650)), WsjtMode("fst4", "FST4", requirements=["wsjt-x-2-3"]), WsjtMode("fst4w", "FST4W", bandpass=Bandpass(1350, 1650), requirements=["wsjt-x-2-3"]), + WsjtMode("jt4", "JT4", requirements=["wsjt-x-2-4"]), WsjtMode("q65", "Q65", requirements=["wsjt-x-2-4"]), DigitalMode("msk144", "MSK144", requirements=["msk144"], underlying=["usb"], service=True), Js8Mode("js8", "JS8Call"), diff --git a/owrx/reporting/pskreporter.py b/owrx/reporting/pskreporter.py index 76a93d6b..ca50b179 100644 --- a/owrx/reporting/pskreporter.py +++ b/owrx/reporting/pskreporter.py @@ -29,7 +29,7 @@ class PskReporter(FilteredReporter): Current version at the time of the last change: https://www.adif.org/314/ADIF_314.htm#Mode_Enumeration """ - return ["FT8", "FT4", "JT9", "JT65", "FST4", "JS8", "Q65", "WSPR", "FST4W", "MSK144"] + return ["FT8", "FT4", "JT9", "JT4", "JT65", "FST4", "JS8", "Q65", "WSPR", "FST4W", "MSK144"] def stop(self): self.cancelTimer() diff --git a/owrx/service/__init__.py b/owrx/service/__init__.py index d78b03e3..813b42ce 100644 --- a/owrx/service/__init__.py +++ b/owrx/service/__init__.py @@ -298,7 +298,7 @@ class ServiceHandler(SdrSourceEventClient): def _getSecondaryDemodulator(self, mod) -> Optional[ServiceDemodulator]: if isinstance(mod, ServiceDemodulatorChain): return mod - if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]: + if mod in ["ft8", "wspr", "jt65", "jt9", "jt4", "ft4", "fst4", "fst4w", "q65"]: from csdr.chain.digimodes import AudioChopperDemodulator from owrx.wsjt import WsjtParser return AudioChopperDemodulator(mod, WsjtParser()) diff --git a/owrx/wsjt.py b/owrx/wsjt.py index b1fdd9c9..51614c96 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -62,6 +62,16 @@ class Fst4wProfileSource(ConfigWiredProfileSource): return [Fst4wProfile(i) for i in profiles if i in Fst4wProfile.availableIntervals] +class JT4ProfileSource(ConfigWiredProfileSource): + def getPropertiesToWire(self) -> List[str]: + return ["jt4_enabled_submodes"] + + def getProfiles(self) -> List[AudioChopperProfile]: + config = Config.get() + profiles = config["jt4_enabled_submodes"] if "jt4_enabled_submodes" in config else [] + return [JT4Profile(i) for i in profiles if i in JT4Profile.availableSubmodes] + + class Q65ProfileSource(ConfigWiredProfileSource): def getPropertiesToWire(self) -> List[str]: return ["q65_enabled_combinations"] @@ -102,6 +112,8 @@ class WsjtProfiles(object): return Fst4ProfileSource() elif mode == "fst4w": return Fst4wProfileSource() + elif mode == "jt4": + return JT4ProfileSource() elif mode == "q65": return Q65ProfileSource() @@ -197,6 +209,25 @@ class Fst4wProfile(WsjtProfile): return "FST4W" +class JT4Profile(WsjtProfile): + availableSubmodes = ["A", "B", "C", "D", "E", "F", "G"] + + def __init__(self, submode): + self.submode = submode + + def getInterval(self): + return 60 + + def getSubmode(self): + return self.submode + + def decoder_commandline(self, file): + return ["jt9", "-4", "-b", str(self.submode), "-F", "1000" , "-d", str(self.decoding_depth()), file] + + def getMode(self): + return "JT4" + + class Q65Mode(Enum): # value is the bandwidth multiplier according to https://physics.princeton.edu/pulsar/k1jt/Q65_Quick_Start.pdf A = 1 From cde00a0e874268c249fbd91970a52b44478eb0a6 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Sun, 3 Mar 2024 20:19:18 +0100 Subject: [PATCH 2/8] JT4 fixes according to jkettler suggestions --- CHANGELOG.md | 2 +- debian/changelog | 1 + docker.sh | 2 +- owrx/modes.py | 2 +- owrx/wsjt.py | 5 +---- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ecf6362..041f527a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ - Added support for the MSK144 digimode - Added support for decoding ADS-B with dump1090 - Added support for decoding HFDL and VDL2 aircraft communications -- Added support for JT4 modes +- Added support for decoding JT4 modes - Added decoding of ISM band transmissions using rtl_433 - Added support for decoding RDS data on WFM broadcasts using redsea decoder - Added decoding for DAB broadcast stations using csdr-eti and dablin diff --git a/debian/changelog b/debian/changelog index aa95d2f4..dcdbd1cc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ openwebrx (1.3.0) UNRELEASED; urgency=low * Added support for the MSK144 digimode * Added support for decoding ADS-B with dump1090 * Added support for decoding HFDL and VDL2 aircraft communications + * Added support for decoding JT4 modes * Added decoding of ISM band transmissions using rtl_433 * Added support for decoding RDS data on WFM broadcasts using redsea decoder * Added decoding for DAB broadcast stations using csdr-eti and dablin diff --git a/docker.sh b/docker.sh index d40abaf4..b3657af6 100755 --- a/docker.sh +++ b/docker.sh @@ -94,4 +94,4 @@ case ${1:-} in *) usage ;; -esac +esac \ No newline at end of file diff --git a/owrx/modes.py b/owrx/modes.py index 934b6961..14e7e542 100644 --- a/owrx/modes.py +++ b/owrx/modes.py @@ -147,7 +147,7 @@ class Modes(object): WsjtMode("wspr", "WSPR", bandpass=Bandpass(1350, 1650)), WsjtMode("fst4", "FST4", requirements=["wsjt-x-2-3"]), WsjtMode("fst4w", "FST4W", bandpass=Bandpass(1350, 1650), requirements=["wsjt-x-2-3"]), - WsjtMode("jt4", "JT4", requirements=["wsjt-x-2-4"]), + WsjtMode("jt4", "JT4"), WsjtMode("q65", "Q65", requirements=["wsjt-x-2-4"]), DigitalMode("msk144", "MSK144", requirements=["msk144"], underlying=["usb"], service=True), Js8Mode("js8", "JS8Call"), diff --git a/owrx/wsjt.py b/owrx/wsjt.py index 51614c96..f4d0b12c 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -215,14 +215,11 @@ class JT4Profile(WsjtProfile): def __init__(self, submode): self.submode = submode - def getInterval(self): - return 60 - def getSubmode(self): return self.submode def decoder_commandline(self, file): - return ["jt9", "-4", "-b", str(self.submode), "-F", "1000" , "-d", str(self.decoding_depth()), file] + return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), file] def getMode(self): return "JT4" From d494a5936814ab56eb902a12cfa4e3fe9edadadd Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Sun, 3 Mar 2024 20:39:40 +0100 Subject: [PATCH 3/8] getInterval is needed by audio/chopper.py --- owrx/wsjt.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/owrx/wsjt.py b/owrx/wsjt.py index f4d0b12c..38ce7c8f 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -215,6 +215,9 @@ class JT4Profile(WsjtProfile): def __init__(self, submode): self.submode = submode + def getInterval(self): + return 60 + def getSubmode(self): return self.submode From f8fb1788ee06c21b799aa33caf75a854b8ec45b8 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Mon, 24 Feb 2025 16:52:47 +0100 Subject: [PATCH 4/8] Add possibility to set frequency tolerance (initial for jt4 only) Signed-off-by: Dawid SQ6EMM --- owrx/config/defaults.py | 1 + owrx/controllers/settings/decoding.py | 5 +++++ owrx/wsjt.py | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 0f97a199..30e3da5d 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -152,6 +152,7 @@ defaultConfig = PropertyLayer( decoding_queue_workers=2, decoding_queue_length=10, wsjt_decoding_depth=3, + wsjt_frequency_tolerance=20, wsjt_decoding_depths=PropertyLayer(jt65=1), fst4_enabled_intervals=[15, 30], fst4w_enabled_intervals=[120, 300], diff --git a/owrx/controllers/settings/decoding.py b/owrx/controllers/settings/decoding.py index 24f32ae8..ced6fa07 100644 --- a/owrx/controllers/settings/decoding.py +++ b/owrx/controllers/settings/decoding.py @@ -70,6 +70,11 @@ class DecodingSettingsController(SettingsFormController): "Default WSJT decoding depth", infotext="A higher decoding depth will allow more results, but will also consume more cpu", ), + NumberInput( + "wsjt_frequency_tolerance", + "Default WSJT frequency tolerance", + infotext="A higher frequency tolerance will allow more decodes, but will also consume more cpu", + ), WsjtDecodingDepthsInput( "wsjt_decoding_depths", "Individual decoding depths", diff --git a/owrx/wsjt.py b/owrx/wsjt.py index 38ce7c8f..78ced60a 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -29,6 +29,14 @@ class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta): # default when no setting is provided return 3 + def frequency_tolerance(self): + pm = Config.get() + if "wsjt_frequency_tolerance" in pm: + return pm["wsjt_frequency_tolerance"] + # default when no setting is provided + return 20 + + def getTimestampFormat(self): if self.getInterval() < 60: return "%H%M%S" @@ -222,7 +230,7 @@ class JT4Profile(WsjtProfile): return self.submode def decoder_commandline(self, file): - return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), file] + return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), "-F", str(self.frequency_tolerance()), file] def getMode(self): return "JT4" From 6e6100f766a3e436444dbda7705eb2d4b03ace79 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Fri, 7 Mar 2025 09:52:23 +0100 Subject: [PATCH 5/8] Add possibility to set frequency tolerance (initial for jt4 only) Signed-off-by: Dawid SQ6EMM --- owrx/config/defaults.py | 2 +- owrx/controllers/settings/decoding.py | 4 ++-- owrx/wsjt.py | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 30e3da5d..818d16f6 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -152,11 +152,11 @@ defaultConfig = PropertyLayer( decoding_queue_workers=2, decoding_queue_length=10, wsjt_decoding_depth=3, - wsjt_frequency_tolerance=20, wsjt_decoding_depths=PropertyLayer(jt65=1), fst4_enabled_intervals=[15, 30], fst4w_enabled_intervals=[120, 300], jt4_enabled_submodes=["F", "G"], + jt4_frequency_tolerance=20, q65_enabled_combinations=["A30", "E120", "C60"], js8_enabled_profiles=["normal", "slow"], js8_decoding_depth=3, diff --git a/owrx/controllers/settings/decoding.py b/owrx/controllers/settings/decoding.py index ced6fa07..1c3e32a7 100644 --- a/owrx/controllers/settings/decoding.py +++ b/owrx/controllers/settings/decoding.py @@ -71,8 +71,8 @@ class DecodingSettingsController(SettingsFormController): infotext="A higher decoding depth will allow more results, but will also consume more cpu", ), NumberInput( - "wsjt_frequency_tolerance", - "Default WSJT frequency tolerance", + "jt4_frequency_tolerance", + "Default JT4 frequency tolerance", infotext="A higher frequency tolerance will allow more decodes, but will also consume more cpu", ), WsjtDecodingDepthsInput( diff --git a/owrx/wsjt.py b/owrx/wsjt.py index 78ced60a..02bc67b7 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -29,14 +29,13 @@ class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta): # default when no setting is provided return 3 - def frequency_tolerance(self): + def jt4_frequency_tolerance(self): pm = Config.get() - if "wsjt_frequency_tolerance" in pm: - return pm["wsjt_frequency_tolerance"] + if "jt4_frequency_tolerance" in pm: + return pm["jt4_frequency_tolerance"] # default when no setting is provided return 20 - def getTimestampFormat(self): if self.getInterval() < 60: return "%H%M%S" @@ -230,7 +229,7 @@ class JT4Profile(WsjtProfile): return self.submode def decoder_commandline(self, file): - return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), "-F", str(self.frequency_tolerance()), file] + return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), "-F", str(self.jt4_frequency_tolerance()), file] def getMode(self): return "JT4" From 965287bf3c8545d89492e402752a95bb9ed738e6 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Tue, 18 Mar 2025 23:20:42 +0100 Subject: [PATCH 6/8] Made frequency tolerance local to JT4 class Signed-off-by: Dawid SQ6EMM --- owrx/wsjt.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/owrx/wsjt.py b/owrx/wsjt.py index 02bc67b7..1c54e8f7 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -29,13 +29,6 @@ class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta): # default when no setting is provided return 3 - def jt4_frequency_tolerance(self): - pm = Config.get() - if "jt4_frequency_tolerance" in pm: - return pm["jt4_frequency_tolerance"] - # default when no setting is provided - return 20 - def getTimestampFormat(self): if self.getInterval() < 60: return "%H%M%S" @@ -78,7 +71,6 @@ class JT4ProfileSource(ConfigWiredProfileSource): profiles = config["jt4_enabled_submodes"] if "jt4_enabled_submodes" in config else [] return [JT4Profile(i) for i in profiles if i in JT4Profile.availableSubmodes] - class Q65ProfileSource(ConfigWiredProfileSource): def getPropertiesToWire(self) -> List[str]: return ["q65_enabled_combinations"] @@ -228,8 +220,15 @@ class JT4Profile(WsjtProfile): def getSubmode(self): return self.submode + def frequency_tolerance(self): + config = Config.get() + if "jt4_frequency_tolerance" in config: + return config["jt4_frequency_tolerance"] + # default when no setting is provided + return 20 + def decoder_commandline(self, file): - return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), "-F", str(self.jt4_frequency_tolerance()), file] + return ["jt9", "-4", "-b", str(self.submode), "-d", str(self.decoding_depth()), "-F", str(self.frequency_tolerance()), file] def getMode(self): return "JT4" From d4d4f72bfbd3d16abcc5015b588f66e4c8ba783d Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Wed, 19 Mar 2025 13:47:33 +0100 Subject: [PATCH 7/8] Removed unused getSubode Signed-off-by: Dawid SQ6EMM --- owrx/wsjt.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/owrx/wsjt.py b/owrx/wsjt.py index 1c54e8f7..cde0f216 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -217,9 +217,6 @@ class JT4Profile(WsjtProfile): def getInterval(self): return 60 - def getSubmode(self): - return self.submode - def frequency_tolerance(self): config = Config.get() if "jt4_frequency_tolerance" in config: From cf7b81f7b46300265eb1aad76d57c352383dd5f7 Mon Sep 17 00:00:00 2001 From: Dawid SQ6EMM Date: Thu, 20 Mar 2025 19:10:43 +0100 Subject: [PATCH 8/8] Remove empty JT4 messages (be design of JT4 decoder) Signed-off-by: Dawid SQ6EMM --- owrx/wsjt.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/owrx/wsjt.py b/owrx/wsjt.py index cde0f216..31c0d88a 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -305,6 +305,8 @@ class WsjtParser(AudioChopperParser): return mode = profile.getMode() + if mode in ["JT4"] and (msg.endswith("$*") or msg.endswith("$#")): + return if mode in ["WSPR", "FST4W"]: messageParser = BeaconMessageParser() else: