diff --git a/owrx/bands.py b/owrx/bands.py index 1aba72e..ef4d0e9 100644 --- a/owrx/bands.py +++ b/owrx/bands.py @@ -1,4 +1,4 @@ -from owrx.modes import Modes +from owrx.modes import Modes, DigitalMode from datetime import datetime, timezone import json import os @@ -9,14 +9,14 @@ logger = logging.getLogger(__name__) class Band(object): - def __init__(self, dict): - self.name = dict["name"] - self.lower_bound = dict["lower_bound"] - self.upper_bound = dict["upper_bound"] + def __init__(self, b_dict): + self.name = b_dict["name"] + self.lower_bound = b_dict["lower_bound"] + self.upper_bound = b_dict["upper_bound"] self.frequencies = [] - if "frequencies" in dict: + if "frequencies" in b_dict: availableModes = [mode.modulation for mode in Modes.getAvailableModes()] - for (mode, freqs) in dict["frequencies"].items(): + for (mode, freqs) in b_dict["frequencies"].items(): if mode not in availableModes: logger.info( 'Modulation "{mode}" is not available, bandplan bookmark will not be displayed'.format( @@ -27,14 +27,30 @@ class Band(object): if not isinstance(freqs, list): freqs = [freqs] for f in freqs: - if not self.inBand(f): + f_dict = {"frequency": f} if not isinstance(f, dict) else f + f_dict["mode"] = mode + + if not self.inBand(f_dict["frequency"]): logger.warning( "Frequency for {mode} on {band} is not within band limits: {frequency}".format( - mode=mode, frequency=f, band=self.name + mode=mode, frequency=f_dict["frequency"], band=self.name ) ) continue - self.frequencies.append({"mode": mode, "frequency": f}) + + if "underlying" in f_dict: + m = Modes.findByModulation(mode) + if not isinstance(m, DigitalMode): + logger.warning("%s is not a digital mode, cannot be used with \"underlying\" config", mode) + continue + if f_dict["underlying"] not in m.underlying: + logger.warning( + "%s is not a valid underlying mode for %s; skipping", + f_dict["underlying"], + mode + ) + + self.frequencies.append(f_dict) def inBand(self, freq): return self.lower_bound <= freq <= self.upper_bound diff --git a/owrx/modes.py b/owrx/modes.py index 130ae55..c27e85b 100644 --- a/owrx/modes.py +++ b/owrx/modes.py @@ -55,6 +55,13 @@ class DigitalMode(Mode): def get_modulation(self): return self.get_underlying_mode().get_modulation() + def for_underlying(self, underlying: str): + if underlying not in self.underlying: + raise ValueError("{} is not a valid underlying mode for {}".format(underlying, self.modulation)) + return DigitalMode( + self.modulation, self.name, [underlying], self.bandpass, self.requirements, self.service, self.squelch + ) + class AudioChopperMode(DigitalMode, metaclass=ABCMeta): def __init__(self, modulation, name, bandpass=None, requirements=None): diff --git a/owrx/service/__init__.py b/owrx/service/__init__.py index 6361b0c..789ca09 100644 --- a/owrx/service/__init__.py +++ b/owrx/service/__init__.py @@ -123,13 +123,11 @@ class ServiceHandler(SdrSourceEventClient): def updateServices(self): def addService(dial, source): - mode = dial["mode"] - frequency = dial["frequency"] try: - service = self.setupService(mode, frequency, source) + service = self.setupService(dial, source) self.services.append(service) except Exception: - logger.exception("Error setting up service %s on frequency %d", mode, frequency) + logger.exception("Error setting up service {mode} on frequency {frequency}".format(**dial)) with self.lock: logger.debug("re-scheduling services due to sdr changes") @@ -247,23 +245,26 @@ class ServiceHandler(SdrSourceEventClient): return None return best["groups"] - def setupService(self, mode, frequency, source): - logger.debug("setting up service {0} on frequency {1}".format(mode, frequency)) + def setupService(self, dial, source): + logger.debug("setting up service {mode} on frequency {frequency}".format(**dial)) - modeObject = Modes.findByModulation(mode) + modeObject = Modes.findByModulation(dial["mode"]) if not isinstance(modeObject, DigitalMode): - logger.warning("mode is not a digimode: %s", mode) + logger.warning("mode is not a digimode: %s", dial["mode"]) return None + if "underlying" in dial: + modeObject = modeObject.for_underlying(dial["underlying"]) + demod = self._getDemodulator(modeObject.get_modulation()) secondaryDemod = self._getSecondaryDemodulator(modeObject.modulation) center_freq = source.getProps()["center_freq"] sampleRate = source.getProps()["samp_rate"] bandpass = modeObject.get_bandpass() if isinstance(secondaryDemod, DialFrequencyReceiver): - secondaryDemod.setDialFrequency(frequency) + secondaryDemod.setDialFrequency(dial["frequency"]) - chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, frequency - center_freq) + chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, dial["frequency"] - center_freq) chain.setBandPass(bandpass.low_cut, bandpass.high_cut) chain.setReader(source.getBuffer().getReader())