activate more scheduler and service settings

This commit is contained in:
Jakob Ketterl 2021-02-26 21:27:42 +01:00
parent 0231d98ab8
commit 4e7f02fc2c
2 changed files with 66 additions and 28 deletions

View File

@ -9,7 +9,7 @@ from owrx.js8 import Js8Parser
from owrx.config.core import CoreConfig
from owrx.config import Config
from owrx.source.resampler import Resampler
from owrx.property import PropertyLayer
from owrx.property import PropertyLayer, PropertyDeleted
from js8py import Js8Frame
from abc import ABCMeta, abstractmethod
from .schedule import ServiceScheduler
@ -66,13 +66,42 @@ class ServiceHandler(SdrSourceEventClient):
self.services = []
self.source = source
self.startupTimer = None
self.scheduler = None
self.activitySub = None
self.running = False
props = self.source.getProps()
self.enabledSub = props.wireProperty("services", self._receiveEvent)
# need to call _start() manually if property is not set since the default is True, but the initial call is only
# made if the property is present
if "services" not in props:
self._start()
def _receiveEvent(self, state):
# deletion means fall back to default, which is True
if state is PropertyDeleted:
state = True
if self.running == state:
return
if state:
self._start()
else:
self._stop()
def _start(self):
self.running = True
self.source.addClient(self)
props = self.source.getProps()
self.subscriptions = [props.filter("center_freq", "samp_rate").wire(self.onFrequencyChange)]
self.activitySub = props.filter("center_freq", "samp_rate").wire(self.onFrequencyChange)
if self.source.isAvailable():
self.scheduleServiceStartup()
self.scheduler = ServiceScheduler(self.source)
def _stop(self):
if self.activitySub is not None:
self.activitySub.cancel()
self.activitySub = None
self._cancelStartupTimer()
self.source.removeClient(self)
self.stopServices()
self.running = False
def getClientClass(self) -> SdrClientClass:
return SdrClientClass.INACTIVE
@ -86,8 +115,6 @@ class ServiceHandler(SdrSourceEventClient):
elif state is SdrSourceState.FAILED:
logger.debug("sdr source failed; stopping services.")
self.stopServices()
if self.scheduler:
self.scheduler.shutdown()
def onBusyStateChange(self, state: SdrBusyState):
pass
@ -98,12 +125,10 @@ class ServiceHandler(SdrSourceEventClient):
return mode in configured and mode in available
def shutdown(self):
while self.subscriptions:
self.subscriptions.pop().cancel()
self.stopServices()
self.source.removeClient(self)
if self.scheduler:
self.scheduler.shutdown()
self._stop()
if self.enabledSub is not None:
self.enabledSub.cancel()
self.enabledSub = None
def stopServices(self):
with self.lock:
@ -119,9 +144,13 @@ class ServiceHandler(SdrSourceEventClient):
return
self.scheduleServiceStartup()
def scheduleServiceStartup(self):
def _cancelStartupTimer(self):
if self.startupTimer:
self.startupTimer.cancel()
self.startupTimer = None
def scheduleServiceStartup(self):
self._cancelStartupTimer()
self.startupTimer = threading.Timer(10, self.updateServices)
self.startupTimer.start()
@ -281,23 +310,27 @@ class Js8Handler(object):
class Services(object):
handlers = []
schedulers = []
@staticmethod
def start():
config = Config.get()
config.wireProperty("services_enabled", Services._receiveEvent)
for source in SdrService.getSources().values():
Services.schedulers.append(ServiceScheduler(source))
@staticmethod
def _receiveEvent(state):
if state:
for source in SdrService.getSources().values():
props = source.getProps()
if "services" not in props or props["services"] is not False:
Services.handlers.append(ServiceHandler(source))
else:
Services.stop()
while Services.handlers:
Services.handlers.pop().shutdown()
@staticmethod
def stop():
while Services.handlers:
Services.handlers.pop().shutdown()
while Services.schedulers:
Services.schedulers.pop().shutdown()

View File

@ -209,10 +209,13 @@ class ServiceScheduler(SdrSourceEventClient):
def __init__(self, source):
self.source = source
self.selectionTimer = None
self.currentProfile = None
self.source.addClient(self)
self.schedule = None
props = self.source.getProps()
props.filter("center_freq", "samp_rate").wire(self.onFrequencyChange)
props.wireProperty("scheduler", self.parseSchedule)
self.subscriptions = []
self.subscriptions.append(props.filter("center_freq", "samp_rate").wire(self.onFrequencyChange))
self.subscriptions.append(props.wireProperty("scheduler", self.parseSchedule))
# wireProperty calls parseSchedule with the initial value
# self.parseSchedule()
@ -222,6 +225,8 @@ class ServiceScheduler(SdrSourceEventClient):
self.scheduleSelection()
def shutdown(self):
while self.subscriptions:
self.subscriptions.pop().cancel()
self.cancelTimer()
self.source.removeClient(self)
@ -241,13 +246,16 @@ class ServiceScheduler(SdrSourceEventClient):
self.selectionTimer.cancel()
def getClientClass(self) -> SdrClientClass:
if self.currentProfile is None:
return SdrClientClass.INACTIVE
else:
return SdrClientClass.BACKGROUND
def onStateChange(self, state: SdrSourceState):
if state is SdrSourceState.STOPPING:
self.scheduleSelection()
elif state is SdrSourceState.FAILED:
self.cancelTimer()
self.shutdown()
def onBusyStateChange(self, state: SdrBusyState):
if state is SdrBusyState.IDLE:
@ -262,17 +270,15 @@ class ServiceScheduler(SdrSourceEventClient):
return
if self.schedule is None:
logger.debug("no active schedule. releasing source...")
self.source.removeClient(self)
self.currentProfile = None
logger.debug("no active schedule, scheduler standing by for external events.")
return
logger.debug("source seems to be idle, selecting profile for background services")
entry = self.schedule.getCurrentEntry()
self.currentProfile = entry = self.schedule.getCurrentEntry()
if entry is None:
logger.debug("schedule did not return a current profile. releasing source...")
self.source.removeClient(self)
logger.debug("checking next (future) entry...")
logger.debug("schedule did not return a current profile. checking next (future) entry...")
nextEntry = self.schedule.getNextEntry()
if nextEntry is not None:
self.scheduleSelection(nextEntry.getNextActivation())
@ -280,7 +286,6 @@ class ServiceScheduler(SdrSourceEventClient):
logger.debug("no next entry available, scheduler standing by for external events.")
return
self.source.addClient(self)
logger.debug("selected profile %s until %s", entry.getProfile(), entry.getScheduledEnd())
self.scheduleSelection(entry.getScheduledEnd())