From e3aa3fa4c65009c11a2c6982a78dfcd7756518f4 Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Thu, 14 Jan 2021 22:54:59 +0100 Subject: [PATCH] implement wsprnet reporting, refs #62 --- owrx/reporting.py | 7 ++++- owrx/wsjt.py | 2 +- owrx/wsprnet.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 owrx/wsprnet.py diff --git a/owrx/reporting.py b/owrx/reporting.py index 3b14935..d6e0831 100644 --- a/owrx/reporting.py +++ b/owrx/reporting.py @@ -36,10 +36,15 @@ class ReportingEngine(object): def __init__(self): self.reporters = [] - if Config.get()["pskreporter_enabled"]: + config = Config.get() + if config["pskreporter_enabled"]: # inline import due to circular dependencies from owrx.pskreporter import PskReporter self.reporters += [PskReporter()] + if config["wsprnet_enabled"]: + # inline import due to circular dependencies + from owrx.wsprnet import WsprnetReporter + self.reporters += [WsprnetReporter()] def stop(self): for r in self.reporters: diff --git a/owrx/wsjt.py b/owrx/wsjt.py index fd23550..6d2c800 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -273,4 +273,4 @@ class WsprDecoder(Decoder): m = WsprDecoder.wspr_splitter_pattern.match(msg) if m is None: return {} - return {"callsign": m.group(1), "locator": m.group(2)} + return {"callsign": m.group(1), "locator": m.group(2), "dbm": m.group(3)} diff --git a/owrx/wsprnet.py b/owrx/wsprnet.py new file mode 100644 index 0000000..5ba8535 --- /dev/null +++ b/owrx/wsprnet.py @@ -0,0 +1,75 @@ +from owrx.reporting import Reporter +from owrx.version import openwebrx_version +from owrx.config import Config +from owrx.locator import Locator +from queue import Queue, Full +from urllib import request, parse +import threading +import logging +from datetime import datetime, timezone + +logger = logging.getLogger(__name__) + +class Worker(threading.Thread): + def __init__(self, queue: Queue): + self.queue = queue + self.doRun = True + # some constants that we don't expect to change + config = Config.get() + self.callsign = config["wsprnet_callsign"] + self.locator = Locator.fromCoordinates(config["receiver_gps"]) + + super().__init__(daemon=True) + + def run(self): + while self.doRun: + try: + spot = self.queue.get() + self.uploadSpot(spot) + self.queue.task_done() + except Exception: + logger.exception("Exception while uploading WSPRNet spot") + + def uploadSpot(self, spot): + # function=wspr&date=210114&time=1732&sig=-15&dt=0.5&drift=0&tqrg=7.040019&tcall=DF2UU&tgrid=JN48&dbm=37&version=2.3.0-rc3&rcall=DD5JFK&rgrid=JN58SC&rqrg=7.040047&mode=2 + # {'timestamp': 1610655960000, 'db': -23.0, 'dt': 0.3, 'freq': 7040048, 'drift': -1, 'msg': 'LA3JJ JO59 37', 'callsign': 'LA3JJ', 'locator': 'JO59', 'mode': 'WSPR'} + date = datetime.fromtimestamp(spot["timestamp"] / 1000, tz=timezone.utc) + data = parse.urlencode({ + "function": "wspr", + "date": date.strftime("%y%m%d"), + "time": date.strftime("%H%M"), + "sig": spot["db"], + "dt": spot["dt"], + "drift": spot["drift"], + "tqrg": spot["freq"] / 1E6, + "tcall": spot["callsign"], + "tgrid": spot["locator"], + "dbm": spot["dbm"], + "version": openwebrx_version, + "rcall": self.callsign, + "rgrid": self.locator, + # mode 2 = WSPR 2 minutes + # TODO implement FST4W mode codes + "mode": 2 + }).encode() + request.urlopen("http://wsprnet.org/post/", data) + + +class WsprnetReporter(Reporter): + def __init__(self): + # max 100 entries + self.queue = Queue(100) + # single worker + Worker(self.queue).start() + + def stop(self): + pass + + def spot(self, spot): + try: + self.queue.put(spot, block=False) + except Full: + logger.warning("WSPRNet Queue overflow, one spot lost") + + def getSupportedModes(self): + return ["WSPR"]