openwebrx/owrx/reporting/__init__.py
2024-01-30 23:33:20 +01:00

75 lines
2.7 KiB
Python

import threading
from owrx.config import Config
from owrx.reporting.reporter import Reporter, FilteredReporter
from owrx.reporting.pskreporter import PskReporter
from owrx.reporting.wsprnet import WsprnetReporter
from owrx.feature import FeatureDetector
import logging
logger = logging.getLogger(__name__)
class ReportingEngine(object):
creationLock = threading.Lock()
sharedInstance = None
# concrete classes if they can be imported without the risk of optional dependencies
# tuples if the import needs to be detected by a feature check
reporterClasses = {
"pskreporter": PskReporter,
"wsprnet": WsprnetReporter,
"mqtt": ("owrx.reporting.mqtt", "MqttReporter")
}
@staticmethod
def getSharedInstance():
with ReportingEngine.creationLock:
if ReportingEngine.sharedInstance is None:
ReportingEngine.sharedInstance = ReportingEngine()
return ReportingEngine.sharedInstance
@staticmethod
def stopAll():
with ReportingEngine.creationLock:
if ReportingEngine.sharedInstance is not None:
ReportingEngine.sharedInstance.stop()
def __init__(self):
self.reporters = []
configKeys = ["{}_enabled".format(n) for n in self.reporterClasses.keys()]
self.configSub = Config.get().filter(*configKeys).wire(self.setupReporters)
self.setupReporters()
def setupReporters(self, *args):
config = Config.get()
for typeStr, reporterClass in self.reporterClasses.items():
configKey = "{}_enabled".format(typeStr)
if isinstance(reporterClass, tuple):
# feature check
if FeatureDetector().is_available(typeStr):
package, className = reporterClass
module = __import__(package, fromlist=[className])
reporterClass = getattr(module, className)
else:
continue
if configKey in config and config[configKey]:
if not any(isinstance(r, reporterClass) for r in self.reporters):
self.reporters += [reporterClass()]
else:
for reporter in [r for r in self.reporters if isinstance(r, reporterClass)]:
reporter.stop()
self.reporters.remove(reporter)
def stop(self):
for r in self.reporters:
r.stop()
self.configSub.cancel()
def spot(self, spot):
for r in self.reporters:
if not isinstance(r, FilteredReporter) or spot["mode"] in r.getSupportedModes():
try:
r.spot(spot)
except Exception:
logger.exception("error sending spot to reporter")