diff --git a/htdocs/lib/settings/SchedulerInput.js b/htdocs/lib/settings/SchedulerInput.js new file mode 100644 index 0000000..86870e3 --- /dev/null +++ b/htdocs/lib/settings/SchedulerInput.js @@ -0,0 +1,17 @@ +$.fn.schedulerInput = function() { + this.each(function() { + var $container = $(this); + + var update = function(value){ + $container.find('.option').hide(); + $container.find('.option.' + value).show(); + } + + var $select = $container.find('select.mode'); + $select.on('change', function(e) { + var value = $(e.target).val(); + update(value); + }); + update($select.val()); + }); +} \ No newline at end of file diff --git a/htdocs/settings.js b/htdocs/settings.js index 30aacad..3ac5e53 100644 --- a/htdocs/settings.js +++ b/htdocs/settings.js @@ -6,4 +6,5 @@ $(function(){ $('#waterfall_scheme').waterfallDropdown(); $('#rf_gain').gainInput(); $('.optional-section').optionalSection(); + $('#scheduler').schedulerInput(); }); \ No newline at end of file diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py index 696d541..1613eec 100644 --- a/owrx/controllers/assets.py +++ b/owrx/controllers/assets.py @@ -152,6 +152,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): "lib/settings/WaterfallDropdown.js", "lib/settings/GainInput.js", "lib/settings/OptionalSection.js", + "lib/settings/SchedulerInput.js", "settings.js", ], } diff --git a/owrx/form/device.py b/owrx/form/device.py index 2254cf3..2a940ab 100644 --- a/owrx/form/device.py +++ b/owrx/form/device.py @@ -163,3 +163,126 @@ class RemoteInput(TextInput): super().__init__( "remote", "Remote IP and Port", infotext="Remote hostname or IP and port to connect to. Format = IP:Port" ) + + +class SchedulerInput(Input): + def __init__(self, id, label): + super().__init__(id, label) + self.profiles = {} + + def render(self, config): + if "profiles" in config: + self.profiles = config["profiles"] + return super().render(config) + + def render_input(self, value): + def render_profiles_select(stage): + stage_value = "" + if value and "schedule" in value and stage in value["schedule"]: + stage_value = value["schedule"][stage] + + return """ + + """.format( + id="{}-{}".format(self.id, stage), + classes=self.input_classes(), + disabled="disabled" if self.disabled else "", + options="".join( + """ + + """.format( + id=p_id, + name=p["name"], + selected="selected" if stage_value == p_id else "", + ) + for p_id, p in self.profiles.items() + ), + ) + + return """ +
+ + + +
+ """.format( + id=self.id, + classes=self.input_classes(), + disabled="disabled" if self.disabled else "", + options=self.render_options(value), + entries="".join( + """ +
+ + {select} +
+ """.format( + slot=slot, + select=render_profiles_select(slot), + ) + for slot, entry in value["schedule"].items() + ), + stages="".join( + """ +
+ + {select} +
+ """.format( + name=name, + select=render_profiles_select(stage), + ) + for stage, name in [("day", "Day"), ("night", "Night"), ("greyline", "Greyline")] + ), + ) + + def _get_mode(self, value): + if value is not None and "type" in value: + return value["type"] + return "" + + def render_options(self, value): + options = [ + ("static", "Static scheduler"), + ("daylight", "Daylight scheduler"), + ] + + mode = self._get_mode(value) + + return "".join( + """ + + """.format( + value=value, name=name, selected="selected" if mode == value else "" + ) + for value, name in options + ) + + def parse(self, data): + def getStageValue(stage): + input_id = "{id}-{stage}".format(id=self.id, stage=stage) + if input_id in data: + return data[input_id][0] + else: + return None + + select_id = "{id}-select".format(id=self.id) + if select_id in data: + if data[select_id][0] == "static": + # TODO parse static fields + pass + elif data[select_id][0] == "daylight": + settings_dict = {s: getStageValue(s) for s in ["day", "night", "greyline"]} + # filter out empty ones + settings_dict = {s: v for s, v in settings_dict.items() if v} + return {self.id: {"type": "daylight", "schedule": settings_dict}} + + return {} diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index 2db99b2..d4e2410 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -13,7 +13,7 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyFilter from owrx.property.filter import ByLambda from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput from owrx.form.converter import OptionalConverter -from owrx.form.device import GainInput +from owrx.form.device import GainInput, SchedulerInput from owrx.controllers.settings import Section from typing import List from enum import Enum, auto @@ -486,7 +486,7 @@ class SdrDeviceDescription(object): ), NumberInput("waterfall_min_level", "Lowest waterfall level", append="dBFS"), NumberInput("waterfall_max_level", "Highest waterfall level", append="dBFS"), - # TODO `schedule` + SchedulerInput("scheduler", "Scheduler"), NumberInput("center_freq", "Center frequency", append="Hz"), NumberInput("samp_rate", "Sample rate", append="S/s"), NumberInput("start_freq", "Initial frequency", append="Hz"), @@ -502,7 +502,16 @@ class SdrDeviceDescription(object): return ["name", "enabled"] def getOptionalKeys(self): - return ["ppm", "always-on", "services", "rf_gain", "lfo_offset", "waterfall_min_level", "waterfall_max_level"] + return [ + "ppm", + "always-on", + "services", + "rf_gain", + "lfo_offset", + "waterfall_min_level", + "waterfall_max_level", + "scheduler", + ] def getProfileMandatoryKeys(self): return ["center_freq", "samp_rate", "start_freq", "start_mod"]