better timestamping and overhaul
This commit is contained in:
parent
abd5cf0795
commit
18b65f769f
76
owrx/wsjt.py
76
owrx/wsjt.py
@ -1,6 +1,6 @@
|
||||
import threading
|
||||
import wave
|
||||
from datetime import datetime, timedelta, date
|
||||
from datetime import datetime, timedelta, date, timezone
|
||||
import time
|
||||
import sched
|
||||
import subprocess
|
||||
@ -31,7 +31,7 @@ class WsjtChopper(threading.Thread):
|
||||
filename = "{tmp_dir}/openwebrx-wsjtchopper-{id}-{timestamp}.wav".format(
|
||||
tmp_dir = self.tmp_dir,
|
||||
id = id(self),
|
||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
timestamp = datetime.utcnow().strftime(self.fileTimestampFormat)
|
||||
)
|
||||
wavefile = wave.open(filename, "wb")
|
||||
wavefile.setnchannels(1)
|
||||
@ -71,9 +71,9 @@ class WsjtChopper(threading.Thread):
|
||||
self._scheduleNextSwitch()
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
'''
|
||||
"""
|
||||
must be overridden in child classes
|
||||
'''
|
||||
"""
|
||||
return []
|
||||
|
||||
def decode(self):
|
||||
@ -128,6 +128,7 @@ class WsjtChopper(threading.Thread):
|
||||
class Ft8Chopper(WsjtChopper):
|
||||
def __init__(self, source):
|
||||
self.interval = 15
|
||||
self.fileTimestampFormat = "%y%m%d_%H%M%S"
|
||||
super().__init__(source)
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
@ -138,6 +139,7 @@ class Ft8Chopper(WsjtChopper):
|
||||
class WsprChopper(WsjtChopper):
|
||||
def __init__(self, source):
|
||||
self.interval = 120
|
||||
self.fileTimestampFormat = "%y%m%d_%H%M"
|
||||
super().__init__(source)
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
@ -148,6 +150,7 @@ class WsprChopper(WsjtChopper):
|
||||
class Jt65Chopper(WsjtChopper):
|
||||
def __init__(self, source):
|
||||
self.interval = 60
|
||||
self.fileTimestampFormat = "%y%m%d_%H%M"
|
||||
super().__init__(source)
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
@ -158,6 +161,7 @@ class Jt65Chopper(WsjtChopper):
|
||||
class Jt9Chopper(WsjtChopper):
|
||||
def __init__(self, source):
|
||||
self.interval = 60
|
||||
self.fileTimestampFormat = "%y%m%d_%H%M"
|
||||
super().__init__(source)
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
@ -167,8 +171,6 @@ class Jt9Chopper(WsjtChopper):
|
||||
|
||||
class WsjtParser(object):
|
||||
locator_pattern = re.compile(".*\\s([A-Z0-9]+)\\s([A-R]{2}[0-9]{2})$")
|
||||
jt9_pattern = re.compile("^([0-9]{6}|\\*{4}) .*")
|
||||
wspr_pattern = re.compile("^[0-9]{4} .*")
|
||||
wspr_splitter_pattern = re.compile("([A-Z0-9]*)\\s([A-R]{2}[0-9]{2})\\s([0-9]+)")
|
||||
|
||||
def __init__(self, handler):
|
||||
@ -191,38 +193,45 @@ class WsjtParser(object):
|
||||
if msg.startswith(" EOF on input file"):
|
||||
return
|
||||
|
||||
out = {}
|
||||
if WsjtParser.jt9_pattern.match(msg):
|
||||
modes = list(WsjtParser.modes.keys())
|
||||
if msg[21] in modes or msg[19] in modes:
|
||||
out = self.parse_from_jt9(msg)
|
||||
elif WsjtParser.wspr_pattern.match(msg):
|
||||
else:
|
||||
out = self.parse_from_wsprd(msg)
|
||||
|
||||
self.handler.write_wsjt_message(out)
|
||||
except ValueError:
|
||||
logger.exception("error while parsing wsjt message")
|
||||
|
||||
def parse_timestamp(self, instring, dateformat):
|
||||
ts = datetime.strptime(instring, dateformat).replace(tzinfo=timezone.utc)
|
||||
return int(datetime.combine(date.today(), ts.time(), timezone.utc).timestamp() * 1000)
|
||||
|
||||
def parse_from_jt9(self, msg):
|
||||
# ft8 sample
|
||||
# '222100 -15 -0.0 508 ~ CQ EA7MJ IM66'
|
||||
# jt65 sample
|
||||
# '**** -10 0.4 1556 # CQ RN6AM KN95'
|
||||
out = {}
|
||||
if msg.startswith("****"):
|
||||
out["timestamp"] = int(datetime.now().timestamp() * 1000)
|
||||
msg = msg[5:]
|
||||
# '2352 -7 0.4 1801 # R0WAS R2ABM KO85'
|
||||
# '0003 -4 0.4 1762 # CQ R2ABM KO85'
|
||||
modes = list(WsjtParser.modes.keys())
|
||||
if msg[19] in modes:
|
||||
dateformat = "%H%M"
|
||||
else:
|
||||
ts = datetime.strptime(msg[0:6], "%H%M%S")
|
||||
out["timestamp"] = int(datetime.combine(date.today(), ts.time(), datetime.now().tzinfo).timestamp() * 1000)
|
||||
msg = msg[7:]
|
||||
out["db"] = float(msg[0:3])
|
||||
out["dt"] = float(msg[4:8])
|
||||
out["freq"] = int(msg[9:13])
|
||||
dateformat = "%H%M%S"
|
||||
timestamp = self.parse_timestamp(msg[0:len(dateformat)], dateformat)
|
||||
msg = msg[len(dateformat) + 1:]
|
||||
modeChar = msg[14:15]
|
||||
out["mode"] = mode = WsjtParser.modes[modeChar] if modeChar in WsjtParser.modes else "unknown"
|
||||
mode = WsjtParser.modes[modeChar] if modeChar in WsjtParser.modes else "unknown"
|
||||
wsjt_msg = msg[17:53].strip()
|
||||
self.parseLocator(wsjt_msg, mode)
|
||||
out["msg"] = wsjt_msg
|
||||
return out
|
||||
return {
|
||||
"timestamp": timestamp,
|
||||
"db": float(msg[0:3]),
|
||||
"dt": float(msg[4:8]),
|
||||
"freq": int(msg[9:13]),
|
||||
"mode": mode,
|
||||
"msg": wsjt_msg
|
||||
}
|
||||
|
||||
def parseLocator(self, msg, mode):
|
||||
m = WsjtParser.locator_pattern.match(msg)
|
||||
@ -237,19 +246,18 @@ class WsjtParser(object):
|
||||
def parse_from_wsprd(self, msg):
|
||||
# wspr sample
|
||||
# '2600 -24 0.4 0.001492 -1 G8AXA JO01 33'
|
||||
out = {}
|
||||
now = datetime.now()
|
||||
ts = datetime.strptime(msg[0:4], "%M%S").replace(hour=now.hour)
|
||||
out["timestamp"] = int(datetime.combine(date.today(), ts.time(), now.tzinfo).timestamp() * 1000)
|
||||
out["db"] = float(msg[5:8])
|
||||
out["dt"] = float(msg[9:13])
|
||||
out["freq"] = float(msg[14:24])
|
||||
out["drift"] = int(msg[25:28])
|
||||
out["mode"] = "WSPR"
|
||||
# '0052 -29 2.6 0.001486 0 G02CWT IO92 23'
|
||||
wsjt_msg = msg[29:].strip()
|
||||
out["msg"] = wsjt_msg
|
||||
self.parseWsprMessage(wsjt_msg)
|
||||
return out
|
||||
return {
|
||||
"timestamp": self.parse_timestamp(msg[0:4], "%H%M"),
|
||||
"db": float(msg[5:8]),
|
||||
"dt": float(msg[9:13]),
|
||||
"freq": float(msg[14:24]),
|
||||
"drift": int(msg[25:28]),
|
||||
"mode": "WSPR",
|
||||
"msg": wsjt_msg
|
||||
}
|
||||
|
||||
def parseWsprMessage(self, msg):
|
||||
m = WsjtParser.wspr_splitter_pattern.match(msg)
|
||||
|
Loading…
Reference in New Issue
Block a user