combine waterfall_[min|max]_level into a single config
This commit is contained in:
parent
f6f0a87002
commit
5cd9d386a6
@ -33,7 +33,7 @@ config_webrx: configuration options for OpenWebRX
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# configuration version. please only modify if you're able to perform the associated migration steps.
|
# configuration version. please only modify if you're able to perform the associated migration steps.
|
||||||
version = 4
|
version = 5
|
||||||
|
|
||||||
# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
|
# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
|
||||||
# https://github.com/jketterl/openwebrx/wiki/Configuration-guide
|
# https://github.com/jketterl/openwebrx/wiki/Configuration-guide
|
||||||
@ -258,13 +258,12 @@ sdrs = {
|
|||||||
#waterfall_colors = [0x0000FF, 0x00FF00, 0xFF0000]
|
#waterfall_colors = [0x0000FF, 0x00FF00, 0xFF0000]
|
||||||
|
|
||||||
### Waterfall calibration
|
### Waterfall calibration
|
||||||
#waterfall_min_level = -88 # in dB
|
#waterfall_levels = {"min": -88, "max": -20} # in dB
|
||||||
#waterfall_max_level = -20
|
|
||||||
waterfall_auto_level_margin = {"min": 3, "max": 10, "min_range": 50}
|
waterfall_auto_level_margin = {"min": 3, "max": 10, "min_range": 50}
|
||||||
|
|
||||||
# Note: When the auto waterfall level button is clicked, the following happens:
|
# Note: When the auto waterfall level button is clicked, the following happens:
|
||||||
# [waterfall_min_level] = [current_min_power_level] - [waterfall_auto_level_margin["min"]]
|
# [waterfall_levels.min] = [current_min_power_level] - [waterfall_auto_level_margin["min"]]
|
||||||
# [waterfall_max_level] = [current_max_power_level] + [waterfall_auto_level_margin["max"]]
|
# [waterfall_levels.max] = [current_max_power_level] + [waterfall_auto_level_margin["max"]]
|
||||||
#
|
#
|
||||||
# ___|________________________________________|____________________________________|________________________________________|___> signal power
|
# ___|________________________________________|____________________________________|________________________________________|___> signal power
|
||||||
# \_waterfall_auto_level_margin["min"]_/ |__ current_min_power_level | \_waterfall_auto_level_margin["max"]_/
|
# \_waterfall_auto_level_margin["min"]_/ |__ current_min_power_level | \_waterfall_auto_level_margin["max"]_/
|
||||||
|
@ -717,10 +717,10 @@ function on_ws_recv(evt) {
|
|||||||
var config = json['value'];
|
var config = json['value'];
|
||||||
if ('waterfall_colors' in config)
|
if ('waterfall_colors' in config)
|
||||||
waterfall_colors = buildWaterfallColors(config['waterfall_colors']);
|
waterfall_colors = buildWaterfallColors(config['waterfall_colors']);
|
||||||
if ('waterfall_min_level' in config)
|
if ('waterfall_levels' in config) {
|
||||||
waterfall_min_level_default = config['waterfall_min_level'];
|
waterfall_min_level_default = config['waterfall_levels']['min'];
|
||||||
if ('waterfall_max_level' in config)
|
waterfall_max_level_default = config['waterfall_levels']['max'];
|
||||||
waterfall_max_level_default = config['waterfall_max_level'];
|
}
|
||||||
if ('waterfall_auto_level_margin' in config)
|
if ('waterfall_auto_level_margin' in config)
|
||||||
waterfall_auto_level_margin = config['waterfall_auto_level_margin'];
|
waterfall_auto_level_margin = config['waterfall_auto_level_margin'];
|
||||||
waterfallColorsDefault();
|
waterfallColorsDefault();
|
||||||
|
@ -2,7 +2,7 @@ from owrx.property import PropertyLayer
|
|||||||
|
|
||||||
|
|
||||||
defaultConfig = PropertyLayer(
|
defaultConfig = PropertyLayer(
|
||||||
version=4,
|
version=5,
|
||||||
max_clients=20,
|
max_clients=20,
|
||||||
receiver_name="[Callsign]",
|
receiver_name="[Callsign]",
|
||||||
receiver_location="Budapest, Hungary",
|
receiver_location="Budapest, Hungary",
|
||||||
@ -23,8 +23,7 @@ defaultConfig = PropertyLayer(
|
|||||||
digital_voice_dmr_id_lookup=True,
|
digital_voice_dmr_id_lookup=True,
|
||||||
# sdrs=...
|
# sdrs=...
|
||||||
waterfall_scheme="GoogleTurboWaterfall",
|
waterfall_scheme="GoogleTurboWaterfall",
|
||||||
waterfall_min_level=-88,
|
waterfall_levels=PropertyLayer(min=-88, max=-20),
|
||||||
waterfall_max_level=-20,
|
|
||||||
waterfall_auto_level_margin=PropertyLayer(min=3, max=10, min_range=50),
|
waterfall_auto_level_margin=PropertyLayer(min=3, max=10, min_range=50),
|
||||||
frequency_display_precision=4,
|
frequency_display_precision=4,
|
||||||
squelch_auto_margin=10,
|
squelch_auto_margin=10,
|
||||||
|
@ -59,3 +59,6 @@ class DynamicConfig(PropertyLayer):
|
|||||||
|
|
||||||
def __dict__(self):
|
def __dict__(self):
|
||||||
return {k: v for k, v in super().__dict__().items() if v is not DynamicConfig._deleted}
|
return {k: v for k, v in super().__dict__().items() if v is not DynamicConfig._deleted}
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return [k for k in super().keys() if self.__contains__(k)]
|
||||||
|
@ -41,7 +41,6 @@ class ConfigMigratorVersion2(ConfigMigrator):
|
|||||||
|
|
||||||
|
|
||||||
class ConfigMigratorVersion3(ConfigMigrator):
|
class ConfigMigratorVersion3(ConfigMigrator):
|
||||||
|
|
||||||
def migrate(self, config):
|
def migrate(self, config):
|
||||||
# inline import due to circular dependencies
|
# inline import due to circular dependencies
|
||||||
from owrx.waterfall import WaterfallOptions
|
from owrx.waterfall import WaterfallOptions
|
||||||
@ -61,12 +60,42 @@ class ConfigMigratorVersion3(ConfigMigrator):
|
|||||||
config["version"] = 4
|
config["version"] = 4
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigMigratorVersion4(ConfigMigrator):
|
||||||
|
def _replaceWaterfallLevels(self, instance):
|
||||||
|
if (
|
||||||
|
"waterfall_min_level" in instance
|
||||||
|
and "waterfall_max_level" in instance
|
||||||
|
and not "waterfall_levels" in instance
|
||||||
|
):
|
||||||
|
instance["waterfall_levels"] = {
|
||||||
|
"min": instance["waterfall_min_level"],
|
||||||
|
"max": instance["waterfall_max_level"],
|
||||||
|
}
|
||||||
|
del instance["waterfall_min_level"]
|
||||||
|
del instance["waterfall_max_level"]
|
||||||
|
|
||||||
|
def migrate(self, config):
|
||||||
|
# migrate root level
|
||||||
|
self._replaceWaterfallLevels(config)
|
||||||
|
if "sdrs" in config:
|
||||||
|
for device in config["sdrs"].__dict__().values():
|
||||||
|
# migrate device level
|
||||||
|
self._replaceWaterfallLevels(device)
|
||||||
|
if "profiles" in device:
|
||||||
|
for profile in device["profiles"].__dict__().values():
|
||||||
|
# migrate profile level
|
||||||
|
self._replaceWaterfallLevels(profile)
|
||||||
|
|
||||||
|
config["version"] = 5
|
||||||
|
|
||||||
|
|
||||||
class Migrator(object):
|
class Migrator(object):
|
||||||
currentVersion = 4
|
currentVersion = 5
|
||||||
migrators = {
|
migrators = {
|
||||||
1: ConfigMigratorVersion1(),
|
1: ConfigMigratorVersion1(),
|
||||||
2: ConfigMigratorVersion2(),
|
2: ConfigMigratorVersion2(),
|
||||||
3: ConfigMigratorVersion3(),
|
3: ConfigMigratorVersion3(),
|
||||||
|
4: ConfigMigratorVersion4(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -113,8 +113,7 @@ class OpenWebRxClient(Client, metaclass=ABCMeta):
|
|||||||
|
|
||||||
class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
|
class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
|
||||||
sdr_config_keys = [
|
sdr_config_keys = [
|
||||||
"waterfall_min_level",
|
"waterfall_levels",
|
||||||
"waterfall_max_level",
|
|
||||||
"samp_rate",
|
"samp_rate",
|
||||||
"start_mod",
|
"start_mod",
|
||||||
"start_freq",
|
"start_freq",
|
||||||
|
@ -12,6 +12,7 @@ from owrx.form import (
|
|||||||
from owrx.form.converter import WaterfallColorsConverter
|
from owrx.form.converter import WaterfallColorsConverter
|
||||||
from owrx.form.receiverid import ReceiverKeysConverter
|
from owrx.form.receiverid import ReceiverKeysConverter
|
||||||
from owrx.form.gfx import AvatarInput, TopPhotoInput
|
from owrx.form.gfx import AvatarInput, TopPhotoInput
|
||||||
|
from owrx.form.device import WaterfallLevelsInput
|
||||||
from owrx.waterfall import WaterfallOptions
|
from owrx.waterfall import WaterfallOptions
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
@ -102,8 +103,7 @@ class GeneralSettingsController(SettingsFormController):
|
|||||||
infotext="If fft_voverlap_factor is above 0, multiple FFTs will be used for creating a line on the "
|
infotext="If fft_voverlap_factor is above 0, multiple FFTs will be used for creating a line on the "
|
||||||
+ "diagram.",
|
+ "diagram.",
|
||||||
),
|
),
|
||||||
NumberInput("waterfall_min_level", "Lowest waterfall level", append="dBFS"),
|
WaterfallLevelsInput("waterfall_levels", "Waterfall levels"),
|
||||||
NumberInput("waterfall_max_level", "Highest waterfall level", append="dBFS"),
|
|
||||||
),
|
),
|
||||||
Section(
|
Section(
|
||||||
"Compression",
|
"Compression",
|
||||||
|
@ -338,3 +338,47 @@ class SchedulerInput(Input):
|
|||||||
return {self.id: {"type": "daylight", "schedule": settings_dict}}
|
return {self.id: {"type": "daylight", "schedule": settings_dict}}
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
class WaterfallLevelsInput(Input):
|
||||||
|
def render_input(self, value):
|
||||||
|
return """
|
||||||
|
<div class="row" id="{id}">
|
||||||
|
{inputs}
|
||||||
|
</div>
|
||||||
|
""".format(
|
||||||
|
id=self.id,
|
||||||
|
inputs="".join(
|
||||||
|
"""
|
||||||
|
<div class="col row">
|
||||||
|
<label class="col-3 col-form-label col-form-label-sm" for="{id}-{name}">{label}</label>
|
||||||
|
<div class="col-9 input-group input-group-sm">
|
||||||
|
<input type="number" class="{classes}" name="{id}-{name}" value="{value}" {disabled}>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">dBFS</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
""".format(
|
||||||
|
id=self.id,
|
||||||
|
name=name,
|
||||||
|
label=label,
|
||||||
|
value=value[name] if value and name in value else "0",
|
||||||
|
classes=self.input_classes(),
|
||||||
|
disabled="disabled" if self.disabled else "",
|
||||||
|
)
|
||||||
|
for name, label in [("min", "Minimum"), ("max", "Maximum")]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def parse(self, data):
|
||||||
|
def getValue(name):
|
||||||
|
key = "{}-{}".format(self.id, name)
|
||||||
|
if key in data:
|
||||||
|
return {name: data[key][0]}
|
||||||
|
raise KeyError("waterfall key not found")
|
||||||
|
|
||||||
|
try:
|
||||||
|
return {self.id: {k: v for name in ["min", "max"] for k, v in getValue(name).items()}}
|
||||||
|
except KeyError:
|
||||||
|
return {}
|
||||||
|
@ -13,7 +13,7 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyFilter
|
|||||||
from owrx.property.filter import ByLambda
|
from owrx.property.filter import ByLambda
|
||||||
from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput
|
from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput
|
||||||
from owrx.form.converter import OptionalConverter
|
from owrx.form.converter import OptionalConverter
|
||||||
from owrx.form.device import GainInput, SchedulerInput
|
from owrx.form.device import GainInput, SchedulerInput, WaterfallLevelsInput
|
||||||
from owrx.controllers.settings import Section
|
from owrx.controllers.settings import Section
|
||||||
from typing import List
|
from typing import List
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
@ -492,8 +492,7 @@ class SdrDeviceDescription(object):
|
|||||||
infotext="Use this when the actual receiving frequency differs from the frequency to be tuned on the"
|
infotext="Use this when the actual receiving frequency differs from the frequency to be tuned on the"
|
||||||
+ " device. <br/> Formula: Center frequency + oscillator offset = sdr tune frequency",
|
+ " device. <br/> Formula: Center frequency + oscillator offset = sdr tune frequency",
|
||||||
),
|
),
|
||||||
NumberInput("waterfall_min_level", "Lowest waterfall level", append="dBFS"),
|
WaterfallLevelsInput("waterfall_levels", "Waterfall levels"),
|
||||||
NumberInput("waterfall_max_level", "Highest waterfall level", append="dBFS"),
|
|
||||||
SchedulerInput("scheduler", "Scheduler"),
|
SchedulerInput("scheduler", "Scheduler"),
|
||||||
NumberInput("center_freq", "Center frequency", append="Hz"),
|
NumberInput("center_freq", "Center frequency", append="Hz"),
|
||||||
NumberInput("samp_rate", "Sample rate", append="S/s"),
|
NumberInput("samp_rate", "Sample rate", append="S/s"),
|
||||||
@ -516,8 +515,7 @@ class SdrDeviceDescription(object):
|
|||||||
"services",
|
"services",
|
||||||
"rf_gain",
|
"rf_gain",
|
||||||
"lfo_offset",
|
"lfo_offset",
|
||||||
"waterfall_min_level",
|
"waterfall_levels",
|
||||||
"waterfall_max_level",
|
|
||||||
"scheduler",
|
"scheduler",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -525,7 +523,7 @@ class SdrDeviceDescription(object):
|
|||||||
return ["center_freq", "samp_rate", "start_freq", "start_mod"]
|
return ["center_freq", "samp_rate", "start_freq", "start_mod"]
|
||||||
|
|
||||||
def getProfileOptionalKeys(self):
|
def getProfileOptionalKeys(self):
|
||||||
return ["initial_squelch_level", "rf_gain", "lfo_offset", "waterfall_min_level", "waterfall_max_level"]
|
return ["initial_squelch_level", "rf_gain", "lfo_offset", "waterfall_levels"]
|
||||||
|
|
||||||
def getDeviceSection(self):
|
def getDeviceSection(self):
|
||||||
return OptionalSection("Device settings", self.getInputs(), self.getMandatoryKeys(), self.getOptionalKeys())
|
return OptionalSection("Device settings", self.getInputs(), self.getMandatoryKeys(), self.getOptionalKeys())
|
||||||
|
Loading…
Reference in New Issue
Block a user