add js8 decoding if available

This commit is contained in:
Jakob Ketterl 2020-04-12 13:10:23 +02:00
parent 0e8715b5a1
commit ddfd85c586
7 changed files with 72 additions and 15 deletions

View File

@ -8,7 +8,8 @@
"ft8": 1840000, "ft8": 1840000,
"wspr": 1836600, "wspr": 1836600,
"jt65": 1838000, "jt65": 1838000,
"jt9": 1839000 "jt9": 1839000,
"js8": 1842000
} }
}, },
{ {
@ -21,7 +22,8 @@
"wspr": 3592600, "wspr": 3592600,
"jt65": 3570000, "jt65": 3570000,
"jt9": 3572000, "jt9": 3572000,
"ft4": [3568000, 3575000] "ft4": [3568000, 3575000],
"js8": 3578000
} }
}, },
{ {
@ -43,7 +45,8 @@
"wspr": 7038600, "wspr": 7038600,
"jt65": 7076000, "jt65": 7076000,
"jt9": 7078000, "jt9": 7078000,
"ft4": 7047500 "ft4": 7047500,
"js8": 7078000
} }
}, },
{ {
@ -56,7 +59,8 @@
"wspr": 10138700, "wspr": 10138700,
"jt65": 10138000, "jt65": 10138000,
"jt9": 10140000, "jt9": 10140000,
"ft4": 10140000 "ft4": 10140000,
"js8": 10130000
} }
}, },
{ {
@ -69,7 +73,8 @@
"wspr": 14095600, "wspr": 14095600,
"jt65": 14076000, "jt65": 14076000,
"jt9": 14078000, "jt9": 14078000,
"ft4": 14080000 "ft4": 14080000,
"js8": 14078000
} }
}, },
{ {
@ -82,7 +87,8 @@
"wspr": 18104600, "wspr": 18104600,
"jt65": 18102000, "jt65": 18102000,
"jt9": 18104000, "jt9": 18104000,
"ft4": 18104000 "ft4": 18104000,
"js8": 18104000
} }
}, },
{ {
@ -95,7 +101,8 @@
"wspr": 21094600, "wspr": 21094600,
"jt65": 21076000, "jt65": 21076000,
"jt9": 21078000, "jt9": 21078000,
"ft4": 21140000 "ft4": 21140000,
"js8": 21078000
} }
}, },
{ {
@ -108,7 +115,8 @@
"wspr": 24924600, "wspr": 24924600,
"jt65": 24917000, "jt65": 24917000,
"jt9": 24919000, "jt9": 24919000,
"ft4": 24919000 "ft4": 24919000,
"js8": 24922000
} }
}, },
{ {
@ -121,7 +129,8 @@
"wspr": 28124600, "wspr": 28124600,
"jt65": 28076000, "jt65": 28076000,
"jt9": 28078000, "jt9": 28078000,
"ft4": 28180000 "ft4": 28180000,
"js8": 28078000
} }
}, },
{ {
@ -134,7 +143,8 @@
"wspr": 50293000, "wspr": 50293000,
"jt65": 50310000, "jt65": 50310000,
"jt9": 50312000, "jt9": 50312000,
"ft4": 50318000 "ft4": 50318000,
"js8": 50318000
} }
}, },
{ {

View File

@ -30,6 +30,7 @@ from functools import partial
from owrx.kiss import KissClient, DirewolfConfig from owrx.kiss import KissClient, DirewolfConfig
from owrx.wsjt import Ft8Chopper, WsprChopper, Jt9Chopper, Jt65Chopper, Ft4Chopper from owrx.wsjt import Ft8Chopper, WsprChopper, Jt9Chopper, Jt65Chopper, Ft4Chopper
from owrx.js8 import Js8Chopper
import logging import logging
@ -450,6 +451,7 @@ class dsp(object):
if self.isWsjtMode(): if self.isWsjtMode():
smd = self.get_secondary_demodulator() smd = self.get_secondary_demodulator()
chopper_cls = None chopper_cls = None
output_name = "wsjt_demod"
if smd == "ft8": if smd == "ft8":
chopper_cls = Ft8Chopper chopper_cls = Ft8Chopper
elif smd == "wspr": elif smd == "wspr":
@ -460,10 +462,13 @@ class dsp(object):
chopper_cls = Jt9Chopper chopper_cls = Jt9Chopper
elif smd == "ft4": elif smd == "ft4":
chopper_cls = Ft4Chopper chopper_cls = Ft4Chopper
elif smd == "js8":
chopper_cls = Js8Chopper
output_name = "js8_demod"
if chopper_cls is not None: if chopper_cls is not None:
chopper = chopper_cls(self, self.secondary_process_demod.stdout) chopper = chopper_cls(self, self.secondary_process_demod.stdout)
chopper.start() chopper.start()
self.output.send_output("wsjt_demod", chopper.read) self.output.send_output(output_name, chopper.read)
elif self.isPacket(): elif self.isPacket():
# we best get the ax25 packets from the kiss socket # we best get the ax25 packets from the kiss socket
kiss = KissClient(self.direwolf_port) kiss = KissClient(self.direwolf_port)
@ -576,7 +581,7 @@ class dsp(object):
def isWsjtMode(self, demodulator=None): def isWsjtMode(self, demodulator=None):
if demodulator is None: if demodulator is None:
demodulator = self.get_secondary_demodulator() demodulator = self.get_secondary_demodulator()
return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4"] return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "js8"]
def isPacket(self, demodulator=None): def isPacket(self, demodulator=None):
if demodulator is None: if demodulator is None:

View File

@ -193,6 +193,7 @@
<option value="jt65" data-feature="wsjt-x">JT65</option> <option value="jt65" data-feature="wsjt-x">JT65</option>
<option value="jt9" data-feature="wsjt-x">JT9</option> <option value="jt9" data-feature="wsjt-x">JT9</option>
<option value="ft4" data-feature="wsjt-x">FT4</option> <option value="ft4" data-feature="wsjt-x">FT4</option>
<option value="js8" data-feature="js8call">JS8Call</option>
<option value="packet" data-feature="packet">Packet</option> <option value="packet" data-feature="packet">Packet</option>
<option value="pocsag" data-feature="pocsag">Pocsag</option> <option value="pocsag" data-feature="pocsag">Pocsag</option>
</select> </select>

View File

@ -1305,7 +1305,7 @@ function update_wsjt_panel(msg) {
}; };
var linkedmsg = msg['msg']; var linkedmsg = msg['msg'];
var matches; var matches;
if (['FT8', 'JT65', 'JT9', 'FT4'].indexOf(msg['mode']) >= 0) { if (['FT8', 'JT65', 'JT9', 'FT4', 'JS8'].indexOf(msg['mode']) >= 0) {
matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/); matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/);
if (matches && matches[2] !== 'RR73') { if (matches && matches[2] !== 'RR73') {
linkedmsg = html_escape(matches[1]) + '<a href="map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>'; linkedmsg = html_escape(matches[1]) + '<a href="map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>';
@ -2019,6 +2019,7 @@ function demodulator_digital_replace(subtype) {
case "jt65": case "jt65":
case "jt9": case "jt9":
case "ft4": case "ft4":
case "js8":
secondary_demod_start(subtype); secondary_demod_start(subtype);
demodulator_analog_replace('usb', true); demodulator_analog_replace('usb', true);
break; break;
@ -2045,7 +2046,7 @@ function demodulator_digital_replace(subtype) {
demodulator_buttons_update(); demodulator_buttons_update();
$('#openwebrx-panel-digimodes').attr('data-mode', subtype); $('#openwebrx-panel-digimodes').attr('data-mode', subtype);
toggle_panel("openwebrx-panel-digimodes", true); toggle_panel("openwebrx-panel-digimodes", true);
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4'].indexOf(subtype) >= 0); toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'js8'].indexOf(subtype) >= 0);
toggle_panel("openwebrx-panel-packet-message", subtype === "packet"); toggle_panel("openwebrx-panel-packet-message", subtype === "packet");
toggle_panel("openwebrx-panel-pocsag-message", subtype === "pocsag"); toggle_panel("openwebrx-panel-pocsag-message", subtype === "pocsag");
updateHash(); updateHash();

View File

@ -1,6 +1,6 @@
from owrx.config import Config
from owrx.meta import MetaParser from owrx.meta import MetaParser
from owrx.wsjt import WsjtParser from owrx.wsjt import WsjtParser
from owrx.js8 import Js8Parser
from owrx.aprs import AprsParser from owrx.aprs import AprsParser
from owrx.pocsag import PocsagParser from owrx.pocsag import PocsagParser
from owrx.source import SdrSource from owrx.source import SdrSource
@ -22,6 +22,7 @@ class DspManager(csdr.output):
"wsjt_demod": WsjtParser(self.handler), "wsjt_demod": WsjtParser(self.handler),
"packet_demod": AprsParser(self.handler), "packet_demod": AprsParser(self.handler),
"pocsag_demod": PocsagParser(self.handler), "pocsag_demod": PocsagParser(self.handler),
"js8_demod": Js8Parser(self.handler),
} }
self.props = PropertyStack() self.props = PropertyStack()

View File

@ -40,6 +40,7 @@ class FeatureDetector(object):
"wsjt-x": ["wsjtx", "sox"], "wsjt-x": ["wsjtx", "sox"],
"packet": ["direwolf", "sox"], "packet": ["direwolf", "sox"],
"pocsag": ["digiham", "sox"], "pocsag": ["digiham", "sox"],
"js8call": ["js8", "sox"],
} }
def feature_availability(self): def feature_availability(self):
@ -370,6 +371,12 @@ class FeatureDetector(object):
""" """
return reduce(and_, map(self.command_is_runnable, ["jt9", "wsprd"]), True) return reduce(and_, map(self.command_is_runnable, ["jt9", "wsprd"]), True)
def has_js8(self):
"""
To decode JS8, you will need to install [JS8Call](http://js8call.com/)
"""
return self.command_is_runnable("js8")
def has_alsa(self): def has_alsa(self):
""" """
Some SDR receivers are identifying themselves as a soundcard. In order to read their data, OpenWebRX relies Some SDR receivers are identifying themselves as a soundcard. In order to read their data, OpenWebRX relies

32
owrx/js8.py Normal file
View File

@ -0,0 +1,32 @@
from .wsjt import WsjtChopper
from .parser import Parser
import re
import logging
logger = logging.getLogger(__name__)
class Js8Chopper(WsjtChopper):
def getInterval(self):
return 15
def getFileTimestampFormat(self):
return "%y%m%d_%H%M%S"
def decoder_commandline(self, file):
return ["js8", "--js8", "-d", str(self.decoding_depth("js8")), file]
class Js8Parser(Parser):
decoderRegex = re.compile(" ?<Decode(Started|Debug|Finished)>")
def parse(self, raw):
freq, raw_msg = raw
self.setDialFrequency(freq)
msg = raw_msg.decode().rstrip()
if Js8Parser.decoderRegex.match(msg):
return
if msg.startswith(" EOF on input file"):
return
logger.debug(msg)