use profiles instead of parsing to detect mode
This commit is contained in:
parent
3291dbe8d2
commit
a8011e3a1a
@ -186,7 +186,7 @@ class AudioWriter(object):
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
for line in decoder.stdout:
|
for line in decoder.stdout:
|
||||||
self.outputWriter.send((job.freq, line))
|
self.outputWriter.send((self.profile, job.freq, line))
|
||||||
except OSError:
|
except OSError:
|
||||||
decoder.stdout.flush()
|
decoder.stdout.flush()
|
||||||
# TODO uncouple parsing from the output so that decodes can still go to the map and the spotters
|
# TODO uncouple parsing from the output so that decodes can still go to the map and the spotters
|
||||||
|
@ -28,7 +28,7 @@ class Js8Profiles(object):
|
|||||||
|
|
||||||
|
|
||||||
class Js8Profile(AudioChopperProfile, metaclass=ABCMeta):
|
class Js8Profile(AudioChopperProfile, metaclass=ABCMeta):
|
||||||
def decoding_depth(self, mode):
|
def decoding_depth(self):
|
||||||
pm = Config.get()
|
pm = Config.get()
|
||||||
# return global default
|
# return global default
|
||||||
if "js8_decoding_depth" in pm:
|
if "js8_decoding_depth" in pm:
|
||||||
@ -40,7 +40,7 @@ class Js8Profile(AudioChopperProfile, metaclass=ABCMeta):
|
|||||||
return "%y%m%d_%H%M%S"
|
return "%y%m%d_%H%M%S"
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["js8", "--js8", "-b", self.get_sub_mode(), "-d", str(self.decoding_depth("js8")), file]
|
return ["js8", "--js8", "-b", self.get_sub_mode(), "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_sub_mode(self):
|
def get_sub_mode(self):
|
||||||
@ -85,7 +85,7 @@ class Js8Parser(Parser):
|
|||||||
def parse(self, messages):
|
def parse(self, messages):
|
||||||
for raw in messages:
|
for raw in messages:
|
||||||
try:
|
try:
|
||||||
freq, raw_msg = raw
|
profile, freq, raw_msg = raw
|
||||||
self.setDialFrequency(freq)
|
self.setDialFrequency(freq)
|
||||||
msg = raw_msg.decode().rstrip()
|
msg = raw_msg.decode().rstrip()
|
||||||
if Js8Parser.decoderRegex.match(msg):
|
if Js8Parser.decoderRegex.match(msg):
|
||||||
|
109
owrx/wsjt.py
109
owrx/wsjt.py
@ -14,8 +14,9 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta):
|
class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta):
|
||||||
def decoding_depth(self, mode):
|
def decoding_depth(self):
|
||||||
pm = Config.get()
|
pm = Config.get()
|
||||||
|
mode = self.getMode().lower()
|
||||||
# mode-specific setting?
|
# mode-specific setting?
|
||||||
if "wsjt_decoding_depths" in pm and mode in pm["wsjt_decoding_depths"]:
|
if "wsjt_decoding_depths" in pm and mode in pm["wsjt_decoding_depths"]:
|
||||||
return pm["wsjt_decoding_depths"][mode]
|
return pm["wsjt_decoding_depths"][mode]
|
||||||
@ -25,64 +26,76 @@ class WsjtProfile(AudioChopperProfile, metaclass=ABCMeta):
|
|||||||
# default when no setting is provided
|
# default when no setting is provided
|
||||||
return 3
|
return 3
|
||||||
|
|
||||||
|
def getTimestampFormat(self):
|
||||||
|
if self.getInterval() < 60:
|
||||||
|
return "%H%M%S"
|
||||||
|
return "%H%M"
|
||||||
|
|
||||||
|
def getFileTimestampFormat(self):
|
||||||
|
return "%y%m%d_" + self.getTimestampFormat()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getMode(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Ft8Profile(WsjtProfile):
|
class Ft8Profile(WsjtProfile):
|
||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return 15
|
return 15
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
return "%y%m%d_%H%M%S"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--ft8", "-d", str(self.decoding_depth("ft8")), file]
|
return ["jt9", "--ft8", "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "FT8"
|
||||||
|
|
||||||
|
|
||||||
class WsprProfile(WsjtProfile):
|
class WsprProfile(WsjtProfile):
|
||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return 120
|
return 120
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
return "%y%m%d_%H%M"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
cmd = ["wsprd"]
|
cmd = ["wsprd"]
|
||||||
if self.decoding_depth("wspr") > 1:
|
if self.decoding_depth() > 1:
|
||||||
cmd += ["-d"]
|
cmd += ["-d"]
|
||||||
cmd += [file]
|
cmd += [file]
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "WSPR"
|
||||||
|
|
||||||
|
|
||||||
class Jt65Profile(WsjtProfile):
|
class Jt65Profile(WsjtProfile):
|
||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return 60
|
return 60
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
return "%y%m%d_%H%M"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--jt65", "-d", str(self.decoding_depth("jt65")), file]
|
return ["jt9", "--jt65", "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "JT65"
|
||||||
|
|
||||||
|
|
||||||
class Jt9Profile(WsjtProfile):
|
class Jt9Profile(WsjtProfile):
|
||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return 60
|
return 60
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
return "%y%m%d_%H%M"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--jt9", "-d", str(self.decoding_depth("jt9")), file]
|
return ["jt9", "--jt9", "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "JT9"
|
||||||
|
|
||||||
|
|
||||||
class Ft4Profile(WsjtProfile):
|
class Ft4Profile(WsjtProfile):
|
||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return 7.5
|
return 7.5
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
return "%y%m%d_%H%M%S"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--ft4", "-d", str(self.decoding_depth("ft4")), file]
|
return ["jt9", "--ft4", "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "FT4"
|
||||||
|
|
||||||
|
|
||||||
class Fst4Profile(WsjtProfile):
|
class Fst4Profile(WsjtProfile):
|
||||||
@ -94,13 +107,11 @@ class Fst4Profile(WsjtProfile):
|
|||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return self.interval
|
return self.interval
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
if self.interval < 60:
|
|
||||||
return "%y%m%d_%H%M%S"
|
|
||||||
return "%y%m%d_%H%M"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--fst4", "-p", str(self.interval), "-d", str(self.decoding_depth("fst4")), file]
|
return ["jt9", "--fst4", "-p", str(self.interval), "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "FST4"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getEnabledProfiles():
|
def getEnabledProfiles():
|
||||||
@ -118,13 +129,11 @@ class Fst4wProfile(WsjtProfile):
|
|||||||
def getInterval(self):
|
def getInterval(self):
|
||||||
return self.interval
|
return self.interval
|
||||||
|
|
||||||
def getFileTimestampFormat(self):
|
|
||||||
if self.interval < 60:
|
|
||||||
return "%y%m%d_%H%M%S"
|
|
||||||
return "%y%m%d_%H%M"
|
|
||||||
|
|
||||||
def decoder_commandline(self, file):
|
def decoder_commandline(self, file):
|
||||||
return ["jt9", "--fst4w", "-p", str(self.interval), "-d", str(self.decoding_depth("fst4w")), file]
|
return ["jt9", "--fst4w", "-p", str(self.interval), "-d", str(self.decoding_depth()), file]
|
||||||
|
|
||||||
|
def getMode(self):
|
||||||
|
return "FST4W"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getEnabledProfiles():
|
def getEnabledProfiles():
|
||||||
@ -134,12 +143,10 @@ class Fst4wProfile(WsjtProfile):
|
|||||||
|
|
||||||
|
|
||||||
class WsjtParser(Parser):
|
class WsjtParser(Parser):
|
||||||
modes = {"~": "FT8", "#": "JT65", "@": "JT9", "+": "FT4", "`": "FST4"}
|
|
||||||
|
|
||||||
def parse(self, messages):
|
def parse(self, messages):
|
||||||
for data in messages:
|
for data in messages:
|
||||||
try:
|
try:
|
||||||
freq, raw_msg = data
|
profile, freq, raw_msg = data
|
||||||
self.setDialFrequency(freq)
|
self.setDialFrequency(freq)
|
||||||
msg = raw_msg.decode().rstrip()
|
msg = raw_msg.decode().rstrip()
|
||||||
# known debug messages we know to skip
|
# known debug messages we know to skip
|
||||||
@ -148,17 +155,18 @@ class WsjtParser(Parser):
|
|||||||
if msg.startswith(" EOF on input file"):
|
if msg.startswith(" EOF on input file"):
|
||||||
return
|
return
|
||||||
|
|
||||||
modes = list(WsjtParser.modes.keys())
|
mode = profile.getMode()
|
||||||
if msg[21] in modes or msg[19] in modes:
|
if mode == "WSPR":
|
||||||
decoder = Jt9Decoder()
|
decoder = WsprDecoder(profile)
|
||||||
else:
|
else:
|
||||||
decoder = WsprDecoder()
|
decoder = Jt9Decoder(profile)
|
||||||
out = decoder.parse(msg, freq)
|
out = decoder.parse(msg, freq)
|
||||||
if "mode" in out:
|
out["mode"] = mode
|
||||||
self.pushDecode(out["mode"])
|
|
||||||
|
self.pushDecode(mode)
|
||||||
if "callsign" in out and "locator" in out:
|
if "callsign" in out and "locator" in out:
|
||||||
Map.getSharedInstance().updateLocation(
|
Map.getSharedInstance().updateLocation(
|
||||||
out["callsign"], LocatorLocation(out["locator"]), out["mode"], self.band
|
out["callsign"], LocatorLocation(out["locator"]), mode, self.band
|
||||||
)
|
)
|
||||||
PskReporter.getSharedInstance().spot(out)
|
PskReporter.getSharedInstance().spot(out)
|
||||||
|
|
||||||
@ -189,6 +197,9 @@ class WsjtParser(Parser):
|
|||||||
class Decoder(ABC):
|
class Decoder(ABC):
|
||||||
locator_pattern = re.compile(".*\\s([A-Z0-9]{2,})(\\sR)?\\s([A-R]{2}[0-9]{2})$")
|
locator_pattern = re.compile(".*\\s([A-Z0-9]{2,})(\\sR)?\\s([A-R]{2}[0-9]{2})$")
|
||||||
|
|
||||||
|
def __init__(self, profile):
|
||||||
|
self.profile = profile
|
||||||
|
|
||||||
def parse_timestamp(self, instring, dateformat):
|
def parse_timestamp(self, instring, dateformat):
|
||||||
ts = datetime.strptime(instring, dateformat)
|
ts = datetime.strptime(instring, dateformat)
|
||||||
return int(
|
return int(
|
||||||
@ -219,18 +230,12 @@ class Jt9Decoder(Decoder):
|
|||||||
# '0003 -4 0.4 1762 # CQ R2ABM KO85'
|
# '0003 -4 0.4 1762 # CQ R2ABM KO85'
|
||||||
# fst4 sample
|
# fst4 sample
|
||||||
# '**** -23 0.6 3023 ` <...> <...> R 591631 BI53PV'
|
# '**** -23 0.6 3023 ` <...> <...> R 591631 BI53PV'
|
||||||
modes = list(WsjtParser.modes.keys())
|
dateformat = self.profile.getTimestampFormat()
|
||||||
if msg[19] in modes:
|
|
||||||
dateformat = "%H%M"
|
|
||||||
else:
|
|
||||||
dateformat = "%H%M%S"
|
|
||||||
try:
|
try:
|
||||||
timestamp = self.parse_timestamp(msg[0 : len(dateformat)], dateformat)
|
timestamp = self.parse_timestamp(msg[0:len(dateformat)], dateformat)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
timestamp = None
|
timestamp = None
|
||||||
msg = msg[len(dateformat) + 1:]
|
msg = msg[len(dateformat) + 1:]
|
||||||
modeChar = msg[14:15]
|
|
||||||
mode = WsjtParser.modes[modeChar] if modeChar in WsjtParser.modes else "unknown"
|
|
||||||
wsjt_msg = msg[17:53].strip()
|
wsjt_msg = msg[17:53].strip()
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
@ -238,7 +243,6 @@ class Jt9Decoder(Decoder):
|
|||||||
"db": float(msg[0:3]),
|
"db": float(msg[0:3]),
|
||||||
"dt": float(msg[4:8]),
|
"dt": float(msg[4:8]),
|
||||||
"freq": dial_freq + int(msg[9:13]),
|
"freq": dial_freq + int(msg[9:13]),
|
||||||
"mode": mode,
|
|
||||||
"msg": wsjt_msg,
|
"msg": wsjt_msg,
|
||||||
}
|
}
|
||||||
result.update(self.parseMessage(wsjt_msg))
|
result.update(self.parseMessage(wsjt_msg))
|
||||||
@ -259,7 +263,6 @@ class WsprDecoder(Decoder):
|
|||||||
"dt": float(msg[9:13]),
|
"dt": float(msg[9:13]),
|
||||||
"freq": dial_freq + int(float(msg[14:24]) * 1e6),
|
"freq": dial_freq + int(float(msg[14:24]) * 1e6),
|
||||||
"drift": int(msg[25:28]),
|
"drift": int(msg[25:28]),
|
||||||
"mode": "WSPR",
|
|
||||||
"msg": wsjt_msg,
|
"msg": wsjt_msg,
|
||||||
}
|
}
|
||||||
result.update(self.parseMessage(wsjt_msg))
|
result.update(self.parseMessage(wsjt_msg))
|
||||||
|
Loading…
Reference in New Issue
Block a user