basic mqtt implementation based on maho mqtt

This commit is contained in:
Jakob Ketterl 2024-01-30 01:29:25 +01:00
parent e66a8d1dff
commit 80319475c8
8 changed files with 65 additions and 11 deletions

View file

@ -175,4 +175,6 @@ defaultConfig = PropertyLayer(
# pskreporter_antenna_information=None,
wsprnet_enabled=False,
wsprnet_callsign="N0CALL",
mqtt_enabled=False,
mqtt_host="localhost",
).readonly()

View file

@ -90,4 +90,15 @@ class ReportingController(SettingsFormController):
infotext="This callsign will be used to send spots to wsprnet.org",
),
),
Section(
"MQTT settings",
CheckboxInput(
"mqtt_enabled",
"Enable publishing decodes to MQTT",
),
TextInput(
"mqtt_host",
"MQTT Host",
),
)
]

View file

@ -90,7 +90,8 @@ class FeatureDetector(object):
"dumphfdl": ["dumphfdl"],
"dumpvdl2": ["dumpvdl2"],
"redsea": ["redsea"],
"dab": ["csdreti", "dablin"]
"dab": ["csdreti", "dablin"],
"mqtt": ["paho_mqtt"],
}
def feature_availability(self):
@ -680,3 +681,10 @@ class FeatureDetector(object):
Dablin comes packaged with Debian and Ubuntu, so installing the `dablin` package should get you going.
"""
return self.command_is_runnable("dablin -h")
def has_paho_mqtt(self):
try:
from paho.mqtt import __version__
return True
except ImportError:
return False

View file

@ -1,8 +1,9 @@
import threading
from owrx.config import Config
from owrx.reporting.reporter import Reporter
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__)
@ -12,9 +13,12 @@ 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_enabled": PskReporter,
"wsprnet_enabled": WsprnetReporter,
"pskreporter": PskReporter,
"wsprnet": WsprnetReporter,
"mqtt": ("owrx.reporting.mqtt", "MqttReporter")
}
@staticmethod
@ -32,12 +36,22 @@ class ReportingEngine(object):
def __init__(self):
self.reporters = []
self.configSub = Config.get().filter(*ReportingEngine.reporterClasses.keys()).wire(self.setupReporters)
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 configKey, reporterClass in ReportingEngine.reporterClasses.items():
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()]
@ -53,5 +67,5 @@ class ReportingEngine(object):
def spot(self, spot):
for r in self.reporters:
if spot["mode"] in r.getSupportedModes():
if not isinstance(r, FilteredReporter) or spot["mode"] in r.getSupportedModes():
r.spot(spot)

17
owrx/reporting/mqtt.py Normal file
View file

@ -0,0 +1,17 @@
from paho.mqtt.client import Client
from owrx.reporting.reporter import Reporter
from owrx.config import Config
import json
class MqttReporter(Reporter):
def __init__(self):
pm = Config.get()
self.client = Client()
self.client.connect(host=pm["mqtt_host"])
def stop(self):
self.client.disconnect()
def spot(self, spot):
self.client.publish("openwebrx/spots", payload=json.dumps(spot))

View file

@ -9,12 +9,12 @@ from owrx.config import Config
from owrx.version import openwebrx_version
from owrx.locator import Locator
from owrx.metrics import Metrics, CounterMetric
from owrx.reporting.reporter import Reporter
from owrx.reporting.reporter import FilteredReporter
logger = logging.getLogger(__name__)
class PskReporter(Reporter):
class PskReporter(FilteredReporter):
"""
This class implements the reporting interface to send received signals to pskreporter.info.

View file

@ -10,6 +10,8 @@ class Reporter(ABC):
def spot(self, spot):
pass
class FilteredReporter(Reporter):
@abstractmethod
def getSupportedModes(self):
return []

View file

@ -1,4 +1,4 @@
from owrx.reporting.reporter import Reporter
from owrx.reporting.reporter import FilteredReporter
from owrx.version import openwebrx_version
from owrx.config import Config
from owrx.locator import Locator
@ -68,7 +68,7 @@ class Worker(threading.Thread):
request.urlopen("http://wsprnet.org/post/", data, timeout=60)
class WsprnetReporter(Reporter):
class WsprnetReporter(FilteredReporter):
def __init__(self):
# max 100 entries
self.queue = Queue(100)