From 374bbb599e00a57d683db7588bb0e1bee9263637 Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Wed, 17 Jan 2024 21:23:35 +0100 Subject: [PATCH] implement some basic validation for the sample rate --- owrx/form/input/__init__.py | 4 ++-- owrx/form/input/validator.py | 34 +++++++++++++++++++++++++++++----- owrx/source/__init__.py | 13 +++++++++++-- owrx/source/rtl_sdr.py | 4 ++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/owrx/form/input/__init__.py b/owrx/form/input/__init__.py index 42feb2ac..3366b7ab 100644 --- a/owrx/form/input/__init__.py +++ b/owrx/form/input/__init__.py @@ -331,8 +331,8 @@ class ModesInput(DropdownInput): class ExponentialInput(Input): - def __init__(self, id, label, unit, infotext=None): - super().__init__(id, label, infotext=infotext) + def __init__(self, id, label, unit, infotext=None, validator: Validator = None): + super().__init__(id, label, infotext=infotext, validator=validator) self.unit = unit def defaultConverter(self): diff --git a/owrx/form/input/validator.py b/owrx/form/input/validator.py index fe4e16e5..35c99920 100644 --- a/owrx/form/input/validator.py +++ b/owrx/form/input/validator.py @@ -14,16 +14,40 @@ class RequiredValidator(Validator): raise ValidationError(key, "Field is required") +class Range(object): + def __init__(self, start: int, end: int): + self.start = start + self.end = end + + def isInRange(self, value): + return self.start <= value <= self.end + + def __str__(self): + return "{start}...{end}".format(**vars(self)) + + class RangeValidator(Validator): def __init__(self, minValue, maxValue): - self.minValue = minValue - self.maxValue = maxValue + self.range = Range(minValue, maxValue) def validate(self, key, value) -> None: if value is None or value == "": return # Ignore empty values - n = float(value) - if n < self.minValue or n > self.maxValue: + if not self.range.isInRange(float(value)): raise ValidationError( - key, "Value must be between {min} and {max}".format(min=self.minValue, max=self.maxValue) + key, "Value must be between {min} and {max}".format(min=self.range.start, max=self.range.end) ) + + +class RangeListValidator(Validator): + def __init__(self, rangeList: list[Range]): + self.rangeList = rangeList + + def validate(self, key, value) -> None: + if not any(range for range in self.rangeList if range.isInRange(value)): + raise ValidationError( + key, "Value is out of range {}".format(self._rangeStr()) + ) + + def _rangeStr(self): + return "[{}]".format(", ".join(str(r) for r in self.rangeList)) diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index fb5a9727..7da39e94 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -15,7 +15,7 @@ from owrx.property.filter import ByLambda from owrx.form.input import Input, TextInput, NumberInput, CheckboxInput, ModesInput, ExponentialInput from owrx.form.input.converter import OptionalConverter from owrx.form.input.device import GainInput, SchedulerInput, WaterfallLevelsInput -from owrx.form.input.validator import RequiredValidator +from owrx.form.input.validator import RequiredValidator, Range, RangeListValidator from owrx.form.input.converter import Converter from owrx.form.section import OptionalSection from owrx.feature import FeatureDetector @@ -622,7 +622,12 @@ class SdrDeviceDescription(object): ), SchedulerInput("scheduler", "Scheduler"), ExponentialInput("center_freq", "Center frequency", "Hz"), - ExponentialInput("samp_rate", "Sample rate", "S/s"), + ExponentialInput( + "samp_rate", + "Sample rate", + "S/s", + validator=RangeListValidator(self.getSampleRateRanges()) + ), ExponentialInput("start_freq", "Initial frequency", "Hz"), ModesInput("start_mod", "Initial modulation"), NumberInput("initial_squelch_level", "Initial squelch level", append="dBFS"), @@ -673,3 +678,7 @@ class SdrDeviceDescription(object): self.getProfileMandatoryKeys(), self.getProfileOptionalKeys(), ) + + def getSampleRateRanges(self) -> List[Range]: + # semi-sane default value. should be overridden with more specific values per device. + return [Range(500000, 10000000)] diff --git a/owrx/source/rtl_sdr.py b/owrx/source/rtl_sdr.py index cb9e9542..1c23e957 100644 --- a/owrx/source/rtl_sdr.py +++ b/owrx/source/rtl_sdr.py @@ -3,6 +3,7 @@ from owrx.command import Flag, Option from typing import List from owrx.form.input import Input, TextInput from owrx.form.input.device import BiasTeeInput, DirectSamplingInput +from owrx.form.input.validator import Range class RtlSdrSource(ConnectorSource): @@ -35,3 +36,6 @@ class RtlSdrDeviceDescription(ConnectorDeviceDescription): def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"] + + def getSampleRateRanges(self) -> List[Range]: + return [Range(250000, 3200000)]