better timestamping and overhaul

This commit is contained in:
Jakob Ketterl 2019-07-20 12:47:10 +02:00
parent abd5cf0795
commit 18b65f769f
1 changed files with 42 additions and 34 deletions

View File

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