mapping sdr device layer

This commit is contained in:
Jakob Ketterl 2021-03-18 18:59:38 +01:00
parent 620771eaf2
commit 916f19ac60

View File

@ -1,25 +1,59 @@
from owrx.config import Config from owrx.config import Config
from owrx.property import PropertyLayer from owrx.property import PropertyManager, PropertyDeleted, PropertyDelegator, PropertyLayer
from owrx.feature import FeatureDetector, UnknownFeatureException from owrx.feature import FeatureDetector, UnknownFeatureException
from owrx.source import SdrSourceState from owrx.source import SdrSourceState
from functools import partial
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class SdrService(object): class MappedSdrSources(PropertyDelegator):
sdrProps = None def __init__(self, pm: PropertyManager):
sources = {} self.subscriptions = {}
lastPort = None super().__init__(PropertyLayer())
for key, value in pm.items():
self._addSource(key, value)
pm.wire(self.handleSdrDeviceChange)
@staticmethod def handleSdrDeviceChange(self, changes):
def _loadProps(): for key, value in changes.items():
if SdrService.sdrProps is None: if value is PropertyDeleted:
pm = Config.get() del self[key]
else:
self._addSource(key, value)
def handleDeviceUpdate(self, key, value, changes):
if self.isDeviceValid(value) and key not in self:
self._addSource(key, value)
elif not self.isDeviceValid(value) and key in self:
self._removeSource(key)
def _addSource(self, key, value):
if self.isDeviceValid(value):
self[key] = self.buildNewSource(key, value)
updateMethod = partial(self.handleDeviceUpdate, key, value)
self.subscriptions[key] = [
value.filter("type", "profiles").wire(updateMethod),
value["profiles"].wire(updateMethod)
]
def _removeSource(self, key):
if key in self:
self[key].shutdown()
for sub in self.subscriptions[key]:
sub.cancel()
del self.subscriptions[key]
def isDeviceValid(self, device):
return self._hasProfiles(device) and self._sdrTypeAvailable(device)
def _hasProfiles(self, device):
return "profiles" in device and device["profiles"] and len(device["profiles"]) > 0
def _sdrTypeAvailable(self, value):
featureDetector = FeatureDetector() featureDetector = FeatureDetector()
def sdrTypeAvailable(value):
try: try:
if not featureDetector.is_available(value["type"]): if not featureDetector.is_available(value["type"]):
logger.error( logger.error(
@ -35,15 +69,26 @@ class SdrService(object):
) )
return False return False
# transform all dictionary items into PropertyManager object, filtering out unavailable ones def buildNewSource(self, id, props):
SdrService.sdrProps = { sdrType = props["type"]
name: value for (name, value) in pm["sdrs"].items() if sdrTypeAvailable(value) className = "".join(x for x in sdrType.title() if x.isalnum()) + "Source"
} module = __import__("owrx.source.{0}".format(sdrType), fromlist=[className])
logger.info( cls = getattr(module, className)
"SDR sources loaded. Available SDRs: {0}".format( return cls(id, props)
", ".join(x["name"] for x in SdrService.sdrProps.values())
) def __setitem__(self, key, value):
) if key in self:
self._removeSource(key)
super().__setitem__(key, value)
def __delitem__(self, key):
if key in self:
self._removeSource(key)
super().__delitem__(key)
class SdrService(object):
sources = None
@staticmethod @staticmethod
def getFirstSource(): def getFirstSource():
@ -58,21 +103,14 @@ class SdrService(object):
sources = SdrService.getSources() sources = SdrService.getSources()
if not sources: if not sources:
return None return None
if not id in sources: if id not in sources:
return None return None
return sources[id] return sources[id]
@staticmethod @staticmethod
def getSources(): def getSources():
SdrService._loadProps() if SdrService.sources is None:
for id in SdrService.sdrProps.keys(): SdrService.sources = MappedSdrSources(Config.get()["sdrs"])
if id not in SdrService.sources:
props = SdrService.sdrProps[id]
sdrType = props["type"]
className = "".join(x for x in sdrType.title() if x.isalnum()) + "Source"
module = __import__("owrx.source.{0}".format(sdrType), fromlist=[className])
cls = getattr(module, className)
SdrService.sources[id] = cls(id, props)
return { return {
key: s key: s
for key, s in SdrService.sources.items() for key, s in SdrService.sources.items()