From 9c927d90018ec45f6906fe3feda9fe8c45b15b0e Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Sun, 21 Jul 2019 23:39:11 +0200 Subject: [PATCH] first iteration of background services --- openwebrx.py | 3 ++ owrx/bands.py | 2 +- owrx/connection.py | 2 +- owrx/service.py | 117 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 owrx/service.py diff --git a/openwebrx.py b/openwebrx.py index de51f66..9fa685b 100755 --- a/openwebrx.py +++ b/openwebrx.py @@ -7,6 +7,7 @@ from owrx.feature import FeatureDetector from owrx.source import SdrService, ClientRegistry from socketserver import ThreadingMixIn from owrx.sdrhu import SdrHuUpdater +from owrx.service import ServiceManager import logging @@ -47,6 +48,8 @@ Author contact info: Andras Retzler, HA7ILM updater = SdrHuUpdater() updater.start() + ServiceManager.getSharedInstance().start() + server = ThreadedHttpServer(("0.0.0.0", pm.getPropertyValue("web_port")), RequestHandler) server.serve_forever() diff --git a/owrx/bands.py b/owrx/bands.py index bc76b2a..c32caec 100644 --- a/owrx/bands.py +++ b/owrx/bands.py @@ -54,5 +54,5 @@ class Bandplan(object): def findBand(self, freq): return next(band for band in self.bands if band.inBand(freq)) - def collectDialFrequencis(self, range): + def collectDialFrequencies(self, range): return [e for b in self.bands for e in b.getDialFrequencies(range)] diff --git a/owrx/connection.py b/owrx/connection.py index b68cbaf..5008e36 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -118,7 +118,7 @@ class OpenWebRxReceiverClient(Client): cf = configProps["center_freq"] srh = configProps["samp_rate"] / 2 frequencyRange = (cf - srh, cf + srh) - self.write_dial_frequendies(Bandplan.getSharedInstance().collectDialFrequencis(frequencyRange)) + self.write_dial_frequendies(Bandplan.getSharedInstance().collectDialFrequencies(frequencyRange)) self.configSub = configProps.wire(sendConfig) sendConfig(None, None) diff --git a/owrx/service.py b/owrx/service.py new file mode 100644 index 0000000..84a436e --- /dev/null +++ b/owrx/service.py @@ -0,0 +1,117 @@ +import threading +from owrx.source import SdrService +from owrx.bands import Bandplan +from csdr import dsp, output +from owrx.wsjt import WsjtParser + +import logging + +logger = logging.getLogger(__name__) + + +class ServiceOutput(output): + def __init__(self, frequency): + self.frequency = frequency + + def add_output(self, t, read_fn): + logger.debug("got output of type {0}".format(t)) + + def pump(read, write): + def copy(): + run = True + while run: + data = read() + if data is None or (isinstance(data, bytes) and len(data) == 0): + logger.warning("zero read on {0}".format(t)) + run = False + else: + write(data) + + return copy + + if t == "wsjt_demod": + parser = WsjtParser(WsjtHandler()) + parser.setDialFrequency(self.frequency) + target = pump(read_fn, parser.parse) + else: + # dump everything else + # TODO rewrite the output mechanism in a way that avoids producing unnecessary data + target = pump(read_fn, lambda x: None) + threading.Thread(target=target).start() + + +class ServiceHandler(object): + def __init__(self, source): + self.services = [] + self.source = source + self.source.addClient(self) + self.source.getProps().collect("center_freq", "samp_rate").wire(self.onFrequencyChange) + self.onFrequencyChange("", "") + + def onSdrAvailable(self): + logger.debug("sdr {0} is available".format(self.source.getName())) + self.onFrequencyChange("", "") + + def onSdrUnavailable(self): + logger.debug("sdr {0} is unavailable".format(self.source.getName())) + self.stopServices() + + def isSupported(self, mode): + return mode in ["ft8", "ft4", "wspr"] + + def stopServices(self): + for service in self.services: + service.stop() + self.services = [] + + def startServices(self): + for service in self.services: + service.start() + + def onFrequencyChange(self, key, value): + if not self.source.isAvailable(): + return + logger.debug("sdr {0} is changing frequency".format(self.source.getName())) + self.stopServices() + cf = self.source.getProps()["center_freq"] + srh = self.source.getProps()["samp_rate"] / 2 + frequency_range = (cf - srh, cf + srh) + self.services = [self.setupService(dial["mode"], dial["frequency"]) for dial in Bandplan.getSharedInstance().collectDialFrequencies(frequency_range) if self.isSupported(dial["mode"])] + + def setupService(self, mode, frequency): + logger.debug("setting up service {0} on frequency {1}".format(mode, frequency)) + d = dsp(ServiceOutput(frequency)) + d.set_offset_freq(frequency - self.source.getProps()["center_freq"]) + d.set_demodulator("usb") + d.set_bpf(0, 3000) + d.set_secondary_demodulator(mode) + d.set_audio_compression("none") + d.set_samp_rate(self.source.getProps()["samp_rate"]) + d.start() + return d + + +class WsjtHandler(object): + def write_wsjt_message(self, msg): + pass + + +class ServiceManager(object): + sharedInstance = None + @staticmethod + def getSharedInstance(): + if ServiceManager.sharedInstance is None: + ServiceManager.sharedInstance = ServiceManager() + return ServiceManager.sharedInstance + + def start(self): + for source in SdrService.getSources().values(): + ServiceHandler(source) + + +class Service(object): + pass + + +class WsjtService(Service): + pass