show sdr device log messages in the web configuration

This commit is contained in:
Jakob Ketterl
2022-12-10 19:50:26 +01:00
parent ab40a2934f
commit 13e323cdd2
13 changed files with 133 additions and 34 deletions

View File

@@ -18,6 +18,7 @@ from owrx.form.input.device import GainInput, SchedulerInput, WaterfallLevelsInp
from owrx.form.input.validator import RequiredValidator
from owrx.form.section import OptionalSection
from owrx.feature import FeatureDetector
from owrx.log import LogPipe, HistoryHandler
from typing import List
from enum import Enum
@@ -114,6 +115,10 @@ class SdrSource(ABC):
self.commandMapper = None
self.tcpSource = None
self.buffer = None
self.logger = logger.getChild(id) if id is not None else logger
self.logger.addHandler(HistoryHandler.getHandler(self.logger.name))
self.stdoutPipe = None
self.stderrPipe = None
self.props = PropertyStack()
@@ -185,17 +190,17 @@ class SdrSource(ABC):
for id, p in self.props["profiles"].items():
props.replaceLayer(0, p)
if "center_freq" not in props:
logger.warning('Profile "%s" does not specify a center_freq', id)
self.logger.warning('Profile "%s" does not specify a center_freq', id)
continue
if "samp_rate" not in props:
logger.warning('Profile "%s" does not specify a samp_rate', id)
self.logger.warning('Profile "%s" does not specify a samp_rate', id)
continue
if "start_freq" in props:
start_freq = props["start_freq"]
srh = props["samp_rate"] / 2
center_freq = props["center_freq"]
if start_freq < center_freq - srh or start_freq > center_freq + srh:
logger.warning('start_freq for profile "%s" is out of range', id)
self.logger.warning('start_freq for profile "%s" is out of range', id)
def isAlwaysOn(self):
return "always-on" in self.props and self.props["always-on"]
@@ -225,11 +230,11 @@ class SdrSource(ABC):
return [self.getCommandMapper().map(self.getCommandValues())]
def activateProfile(self, profile_id):
logger.debug("activating profile {0} for {1}".format(profile_id, self.getId()))
self.logger.debug("activating profile {0} for {1}".format(profile_id, self.getId()))
try:
self.profileCarousel.switch(profile_id)
except KeyError:
logger.warning("invalid profile %s for sdr %s. ignoring", profile_id, self.getId())
self.logger.warning("invalid profile %s for sdr %s. ignoring", profile_id, self.getId())
def getId(self):
return self.id
@@ -283,23 +288,37 @@ class SdrSource(ABC):
try:
self.preStart()
except Exception:
logger.exception("Exception during preStart()")
self.logger.exception("Exception during preStart()")
cmd = self.getCommand()
cmd = [c for c in cmd if c is not None]
self.stdoutPipe = LogPipe(logging.INFO, self.logger, "STDOUT")
self.stderrPipe = LogPipe(logging.WARNING, self.logger, "STDERR")
# don't use shell mode for commands without piping
if len(cmd) > 1:
# multiple commands with pipes
cmd = "|".join(cmd)
self.process = subprocess.Popen(cmd, shell=True, start_new_session=True)
self.process = subprocess.Popen(
cmd,
shell=True,
start_new_session=True,
stdout=self.stdoutPipe,
stderr=self.stderrPipe
)
else:
# single command
cmd = cmd[0]
# start_new_session can go as soon as there's no piped commands left
# the os.killpg call must be replaced with something more reasonable at the same time
self.process = subprocess.Popen(shlex.split(cmd), start_new_session=True)
logger.info("Started sdr source: " + cmd)
self.process = subprocess.Popen(
shlex.split(cmd),
start_new_session=True,
stdout=self.stdoutPipe,
stderr=self.stderrPipe
)
self.logger.info("Started sdr source: " + cmd)
available = False
failed = False
@@ -307,9 +326,13 @@ class SdrSource(ABC):
def wait_for_process_to_end():
nonlocal failed
rc = self.process.wait()
logger.debug("shut down with RC={0}".format(rc))
self.logger.debug("shut down with RC={0}".format(rc))
self.process = None
self.monitor = None
self.stdoutPipe.close()
self.stdoutPipe = None
self.stderrPipe.close()
self.stderrPipe = None
if self.getState() is SdrSourceState.RUNNING:
self.fail()
else:
@@ -340,7 +363,7 @@ class SdrSource(ABC):
try:
self.postStart()
except Exception:
logger.exception("Exception during postStart()")
self.logger.exception("Exception during postStart()")
failed = True
if failed:
@@ -374,7 +397,7 @@ class SdrSource(ABC):
self.monitor.join(10)
# if the monitor is still running, the process still hasn't ended, so kill it
if self.monitor:
logger.warning("source has not shut down normally within 10 seconds, sending SIGKILL")
self.logger.warning("source has not shut down normally within 10 seconds, sending SIGKILL")
os.killpg(os.getpgid(self.process.pid), signal.SIGKILL)
except ProcessLookupError:
# been killed by something else, ignore