2021-04-07 15:54:14 +00:00
|
|
|
from owrx.reporting.reporter import Reporter
|
2021-01-14 21:54:59 +00:00
|
|
|
from owrx.version import openwebrx_version
|
|
|
|
from owrx.config import Config
|
|
|
|
from owrx.locator import Locator
|
2021-01-14 23:11:20 +00:00
|
|
|
from owrx.metrics import Metrics, CounterMetric
|
2021-01-14 21:54:59 +00:00
|
|
|
from queue import Queue, Full
|
|
|
|
from urllib import request, parse
|
|
|
|
import threading
|
|
|
|
import logging
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2021-01-14 23:11:20 +00:00
|
|
|
|
2021-04-07 15:54:14 +00:00
|
|
|
PoisonPill = object()
|
|
|
|
|
|
|
|
|
2021-01-14 21:54:59 +00:00
|
|
|
class Worker(threading.Thread):
|
|
|
|
def __init__(self, queue: Queue):
|
|
|
|
self.queue = queue
|
|
|
|
self.doRun = True
|
|
|
|
|
|
|
|
super().__init__(daemon=True)
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
while self.doRun:
|
|
|
|
try:
|
|
|
|
spot = self.queue.get()
|
2021-04-07 15:54:14 +00:00
|
|
|
if spot is PoisonPill:
|
|
|
|
self.doRun = False
|
|
|
|
else:
|
|
|
|
self.uploadSpot(spot)
|
|
|
|
self.queue.task_done()
|
2021-01-14 21:54:59 +00:00
|
|
|
except Exception:
|
|
|
|
logger.exception("Exception while uploading WSPRNet spot")
|
|
|
|
|
2021-01-15 15:19:45 +00:00
|
|
|
def _getMode(self, spot):
|
|
|
|
interval = round(spot["interval"] / 60)
|
|
|
|
# FST4W modes are mapped not to conflict with WSPR modes 2 and 15:
|
|
|
|
if spot["mode"] != "WSPR" and interval in [2, 15]:
|
|
|
|
return interval + 1
|
|
|
|
return interval
|
|
|
|
|
2021-01-14 21:54:59 +00:00
|
|
|
def uploadSpot(self, spot):
|
2021-04-07 15:54:14 +00:00
|
|
|
config = Config.get()
|
2021-01-14 21:54:59 +00:00
|
|
|
# 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)
|
2021-01-20 16:01:46 +00:00
|
|
|
data = parse.urlencode(
|
|
|
|
{
|
|
|
|
"function": "wspr",
|
|
|
|
"date": date.strftime("%y%m%d"),
|
|
|
|
"time": date.strftime("%H%M"),
|
|
|
|
"sig": spot["db"],
|
|
|
|
"dt": spot["dt"],
|
|
|
|
# FST4W does not have drift
|
|
|
|
"drift": spot["drift"] if "drift" in spot else 0,
|
|
|
|
"tqrg": spot["freq"] / 1e6,
|
2022-11-30 00:07:16 +00:00
|
|
|
"tcall": spot["source"]["callsign"],
|
2021-01-20 16:01:46 +00:00
|
|
|
"tgrid": spot["locator"],
|
|
|
|
"dbm": spot["dbm"],
|
|
|
|
"version": openwebrx_version,
|
2021-04-07 15:54:14 +00:00
|
|
|
"rcall": config["wsprnet_callsign"],
|
|
|
|
"rgrid": Locator.fromCoordinates(config["receiver_gps"]),
|
2021-01-20 16:01:46 +00:00
|
|
|
"mode": self._getMode(spot),
|
|
|
|
}
|
|
|
|
).encode()
|
2021-01-31 19:31:54 +00:00
|
|
|
request.urlopen("http://wsprnet.org/post/", data, timeout=60)
|
2021-01-14 21:54:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
class WsprnetReporter(Reporter):
|
|
|
|
def __init__(self):
|
|
|
|
# max 100 entries
|
|
|
|
self.queue = Queue(100)
|
|
|
|
# single worker
|
|
|
|
Worker(self.queue).start()
|
|
|
|
|
2021-01-14 23:11:20 +00:00
|
|
|
# metrics
|
|
|
|
metrics = Metrics.getSharedInstance()
|
|
|
|
self.spotCounter = CounterMetric()
|
|
|
|
metrics.addMetric("wsprnet.spots", self.spotCounter)
|
|
|
|
|
2021-01-14 21:54:59 +00:00
|
|
|
def stop(self):
|
2021-04-07 15:54:14 +00:00
|
|
|
while not self.queue.empty():
|
|
|
|
self.queue.get(timeout=1)
|
|
|
|
self.queue.task_done()
|
|
|
|
self.queue.put(PoisonPill)
|
2021-01-14 21:54:59 +00:00
|
|
|
|
|
|
|
def spot(self, spot):
|
|
|
|
try:
|
|
|
|
self.queue.put(spot, block=False)
|
2021-01-14 23:11:20 +00:00
|
|
|
self.spotCounter.inc()
|
2021-01-14 21:54:59 +00:00
|
|
|
except Full:
|
|
|
|
logger.warning("WSPRNet Queue overflow, one spot lost")
|
|
|
|
|
|
|
|
def getSupportedModes(self):
|
2021-01-15 15:19:45 +00:00
|
|
|
return ["WSPR", "FST4W"]
|