introduce the basic concept of optional keys
This commit is contained in:
parent
683a711b49
commit
770fd749cd
@ -71,7 +71,7 @@ class SdrDeviceController(SettingsFormController):
|
|||||||
def getSections(self):
|
def getSections(self):
|
||||||
try:
|
try:
|
||||||
description = SdrDeviceDescription.getByType(self.device["type"])
|
description = SdrDeviceDescription.getByType(self.device["type"])
|
||||||
return [description.getSection()]
|
return [description.getSection(self.device)]
|
||||||
except SdrDeviceDescriptionMissing:
|
except SdrDeviceDescriptionMissing:
|
||||||
# TODO provide a generic interface that allows to switch the type
|
# TODO provide a generic interface that allows to switch the type
|
||||||
return []
|
return []
|
||||||
|
@ -376,6 +376,9 @@ class SdrDeviceDescriptionMissing(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class SdrDeviceDescription(object):
|
class SdrDeviceDescription(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.indexedInputs = {input.id: input for input in self.getInputs()}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getByType(sdr_type: str) -> "SdrDeviceDescription":
|
def getByType(sdr_type: str) -> "SdrDeviceDescription":
|
||||||
try:
|
try:
|
||||||
@ -423,10 +426,14 @@ class SdrDeviceDescription(object):
|
|||||||
# TODO `schedule`
|
# TODO `schedule`
|
||||||
]
|
]
|
||||||
|
|
||||||
def mergeInputs(self, *args):
|
def getMandatoryKeys(self):
|
||||||
# build a dictionary indexed by the input id to make sure every id only exists once
|
return ["name", "enabled"]
|
||||||
inputs = {input.id: input for input_list in args for input in input_list}
|
|
||||||
return inputs.values()
|
|
||||||
|
|
||||||
def getSection(self):
|
def getOptionalKeys(self):
|
||||||
return Section("Device settings", *self.getInputs())
|
return ["ppm", "always-on", "services", "rf_gain", "lfo_offset", "waterfall_min_level", "waterfall_max_level"]
|
||||||
|
|
||||||
|
def getSection(self, data):
|
||||||
|
visible_keys = set(self.getMandatoryKeys() + [k for k in self.getOptionalKeys() if k in data])
|
||||||
|
inputs = [input for k, input in self.indexedInputs.items() if k in visible_keys]
|
||||||
|
# TODO: render remaining keys in optional area
|
||||||
|
return Section("Device settings", *inputs)
|
||||||
|
@ -22,17 +22,21 @@ class AirspySource(SoapyConnectorSource):
|
|||||||
|
|
||||||
class AirspyDeviceDescription(SoapyConnectorDeviceDescription):
|
class AirspyDeviceDescription(SoapyConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
BiasTeeInput(),
|
||||||
[
|
CheckboxInput(
|
||||||
BiasTeeInput(),
|
"bitpack",
|
||||||
CheckboxInput(
|
"",
|
||||||
"bitpack",
|
checkboxText="Enable bit-packing",
|
||||||
"",
|
infotext="Packs two 12-bit samples into 3 bytes."
|
||||||
checkboxText="Enable bit-packing",
|
+ " Lowers USB bandwidth consumption, increases CPU load",
|
||||||
infotext="Packs two 12-bit samples into 3 bytes."
|
converter=OptionalConverter(defaultFormValue=False),
|
||||||
+ " Lowers USB bandwidth consumption, increases CPU load",
|
),
|
||||||
converter=OptionalConverter(defaultFormValue=False),
|
]
|
||||||
),
|
|
||||||
],
|
def getOptionalKeys(self):
|
||||||
)
|
return super().getOptionalKeys() + ["bias_tee", "bitpack"]
|
||||||
|
|
||||||
|
# TODO: find actual gain stages for airspay
|
||||||
|
# def getGainStages(self):
|
||||||
|
# return None
|
||||||
|
@ -76,23 +76,23 @@ class ConnectorSource(SdrSource):
|
|||||||
|
|
||||||
class ConnectorDeviceDescription(SdrDeviceDescription):
|
class ConnectorDeviceDescription(SdrDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
NumberInput(
|
||||||
[
|
"rtltcp_compat",
|
||||||
NumberInput(
|
"Port for rtl_tcp compatible data",
|
||||||
"rtltcp_compat",
|
infotext="Activate an rtl_tcp compatible interface on the port number specified.<br />"
|
||||||
"Port for rtl_tcp compatible data",
|
+ "Note: Port is only available on the local machine, not on the network.<br />"
|
||||||
infotext="Activate an rtl_tcp compatible interface on the port number specified.<br />"
|
+ "Note: IQ data may be degraded by the downsampling process to 8 bits.",
|
||||||
+ "Note: Port is only available on the local machine, not on the network.<br />"
|
converter=OptionalConverter(IntConverter()),
|
||||||
+ "Note: IQ data may be degraded by the downsampling process to 8 bits.",
|
),
|
||||||
converter=OptionalConverter(IntConverter()),
|
CheckboxInput(
|
||||||
),
|
"iqswap",
|
||||||
CheckboxInput(
|
"",
|
||||||
"iqswap",
|
checkboxText="Swap I and Q channels",
|
||||||
"",
|
infotext="Swapping inverts the spectrum, so this is useful in combination with an inverting mixer",
|
||||||
checkboxText="Swap I and Q channels",
|
converter=OptionalConverter(defaultFormValue=False),
|
||||||
infotext="Swapping inverts the spectrum, so this is useful in combination with an inverting mixer",
|
),
|
||||||
converter=OptionalConverter(defaultFormValue=False),
|
]
|
||||||
),
|
|
||||||
],
|
def getOptionalKeys(self):
|
||||||
)
|
return super().getOptionalKeys() + ["rtltcp_compat", "iqswap"]
|
||||||
|
@ -16,4 +16,11 @@ class HackrfSource(SoapyConnectorSource):
|
|||||||
|
|
||||||
class HackrfDeviceDescription(SoapyConnectorDeviceDescription):
|
class HackrfDeviceDescription(SoapyConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(super().getInputs(), [BiasTeeInput()])
|
return super().getInputs() + [BiasTeeInput()]
|
||||||
|
|
||||||
|
def getOptionalKeys(self):
|
||||||
|
return super().getOptionalKeys() + ["bias_tee"]
|
||||||
|
|
||||||
|
# TODO: find actual gain stages for hackrf
|
||||||
|
# def getGainStages(self):
|
||||||
|
# return None
|
||||||
|
@ -18,16 +18,16 @@ class RtlSdrSource(ConnectorSource):
|
|||||||
|
|
||||||
class RtlSdrDeviceDescription(ConnectorDeviceDescription):
|
class RtlSdrDeviceDescription(ConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
TextInput(
|
||||||
[
|
"device",
|
||||||
TextInput(
|
"Device identifier",
|
||||||
"device",
|
infotext="Device serial number or index",
|
||||||
"Device identifier",
|
converter=OptionalConverter(),
|
||||||
infotext="Device serial number or index",
|
),
|
||||||
converter=OptionalConverter(),
|
BiasTeeInput(),
|
||||||
),
|
DirectSamplingInput()
|
||||||
BiasTeeInput(),
|
]
|
||||||
DirectSamplingInput()
|
|
||||||
],
|
def getOptionalKeys(self):
|
||||||
)
|
return super().getOptionalKeys() + ["device", "bias_tee", "direct_sampling"]
|
||||||
|
@ -16,4 +16,7 @@ class RtlSdrSoapySource(SoapyConnectorSource):
|
|||||||
|
|
||||||
class RtlSdrSoapyDeviceDescription(SoapyConnectorDeviceDescription):
|
class RtlSdrSoapyDeviceDescription(SoapyConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(super().getInputs(), [BiasTeeInput(), DirectSamplingInput()])
|
return super().getInputs() + [BiasTeeInput(), DirectSamplingInput()]
|
||||||
|
|
||||||
|
def getOptionalKeys(self):
|
||||||
|
return super().getOptionalKeys() + ["bias_tee", "direct_sampling"]
|
||||||
|
@ -23,4 +23,7 @@ class RtlTcpSource(ConnectorSource):
|
|||||||
|
|
||||||
class RtlTcpDeviceDescription(ConnectorDeviceDescription):
|
class RtlTcpDeviceDescription(ConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(super().getInputs(), [RemoteInput()])
|
return super().getInputs() + [RemoteInput()]
|
||||||
|
|
||||||
|
def getMandatoryKeys(self):
|
||||||
|
return super().getMandatoryKeys() + ["device"]
|
||||||
|
@ -39,13 +39,13 @@ class ProtocolOptions(DropdownEnum):
|
|||||||
|
|
||||||
class RundsDeviceDescription(ConnectorDeviceDescription):
|
class RundsDeviceDescription(ConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
RemoteInput(),
|
||||||
[
|
DropdownInput("protocol", "Protocol", ProtocolOptions),
|
||||||
RemoteInput(),
|
CheckboxInput(
|
||||||
DropdownInput("protocol", "Protocol", ProtocolOptions),
|
"long", "", "Use 32-bit sample size (LONG)", converter=OptionalConverter(defaultFormValue=False)
|
||||||
CheckboxInput(
|
),
|
||||||
"long", "", "Use 32-bit sample size (LONG)", converter=OptionalConverter(defaultFormValue=False)
|
]
|
||||||
),
|
|
||||||
],
|
def getMandatoryKeys(self):
|
||||||
)
|
return super().getMandatoryKeys() + ["device"]
|
||||||
|
@ -38,29 +38,29 @@ class SdrplayDeviceDescription(SoapyConnectorDeviceDescription):
|
|||||||
return ["RFGR", "IFGR"]
|
return ["RFGR", "IFGR"]
|
||||||
|
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
BiasTeeInput(),
|
||||||
[
|
CheckboxInput(
|
||||||
BiasTeeInput(),
|
"rf_notch",
|
||||||
CheckboxInput(
|
"",
|
||||||
"rf_notch",
|
checkboxText="Enable RF notch filter",
|
||||||
"",
|
converter=OptionalConverter(defaultFormValue=True),
|
||||||
checkboxText="Enable RF notch filter",
|
),
|
||||||
converter=OptionalConverter(defaultFormValue=True),
|
CheckboxInput(
|
||||||
|
"dab_notch",
|
||||||
|
"",
|
||||||
|
checkboxText="Enable DAB notch filter",
|
||||||
|
converter=OptionalConverter(defaultFormValue=True),
|
||||||
|
),
|
||||||
|
DropdownInput(
|
||||||
|
"if_mode",
|
||||||
|
"IF Mode",
|
||||||
|
IfModeOptions,
|
||||||
|
converter=OptionalConverter(
|
||||||
|
EnumConverter(IfModeOptions), defaultFormValue=IfModeOptions.IFMODE_ZERO_IF.name
|
||||||
),
|
),
|
||||||
CheckboxInput(
|
),
|
||||||
"dab_notch",
|
]
|
||||||
"",
|
|
||||||
checkboxText="Enable DAB notch filter",
|
def getOptionalKeys(self):
|
||||||
converter=OptionalConverter(defaultFormValue=True),
|
return super().getOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"]
|
||||||
),
|
|
||||||
DropdownInput(
|
|
||||||
"if_mode",
|
|
||||||
"IF Mode",
|
|
||||||
IfModeOptions,
|
|
||||||
converter=OptionalConverter(
|
|
||||||
EnumConverter(IfModeOptions), defaultFormValue=IfModeOptions.IFMODE_ZERO_IF.name
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
@ -84,27 +84,27 @@ class SoapyConnectorSource(ConnectorSource, metaclass=ABCMeta):
|
|||||||
|
|
||||||
class SoapyConnectorDeviceDescription(ConnectorDeviceDescription):
|
class SoapyConnectorDeviceDescription(ConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
TextInput(
|
||||||
[
|
"device",
|
||||||
TextInput(
|
"Device Identifier",
|
||||||
"device",
|
infotext='SoapySDR device identifier string (example: "serial=123456789")',
|
||||||
"Device Identifier",
|
converter=OptionalConverter()
|
||||||
infotext='SoapySDR device identifier string (example: "serial=123456789")',
|
),
|
||||||
converter=OptionalConverter()
|
GainInput(
|
||||||
),
|
"rf_gain",
|
||||||
GainInput(
|
"Device Gain",
|
||||||
"rf_gain",
|
gain_stages=self.getGainStages(),
|
||||||
"Device Gain",
|
),
|
||||||
gain_stages=self.getGainStages(),
|
TextInput(
|
||||||
),
|
"antenna",
|
||||||
TextInput(
|
"Antenna",
|
||||||
"antenna",
|
converter=OptionalConverter(),
|
||||||
"Antenna",
|
),
|
||||||
converter=OptionalConverter(),
|
]
|
||||||
),
|
|
||||||
],
|
def getOptionalKeys(self):
|
||||||
)
|
return super().getOptionalKeys() + ["device", "rf_gain", "antenna"]
|
||||||
|
|
||||||
def getGainStages(self):
|
def getGainStages(self):
|
||||||
return None
|
return None
|
||||||
|
@ -22,12 +22,12 @@ class SoapyRemoteSource(SoapyConnectorSource):
|
|||||||
|
|
||||||
class SoapyRemoteDeviceDescription(SoapyConnectorDeviceDescription):
|
class SoapyRemoteDeviceDescription(SoapyConnectorDeviceDescription):
|
||||||
def getInputs(self) -> List[Input]:
|
def getInputs(self) -> List[Input]:
|
||||||
return self.mergeInputs(
|
return super().getInputs() + [
|
||||||
super().getInputs(),
|
RemoteInput(),
|
||||||
[
|
TextInput(
|
||||||
RemoteInput(),
|
"remote_driver", "Remote driver", infotext="SoapySDR driver to be used on the remote SoapySDRServer"
|
||||||
TextInput(
|
),
|
||||||
"remote_driver", "Remote driver", infotext="SoapySDR driver to be used on the remote SoapySDRServer"
|
]
|
||||||
),
|
|
||||||
],
|
def getOptionalKeys(self):
|
||||||
)
|
return super().getOptionalKeys() + ["remote_driver"]
|
||||||
|
Loading…
Reference in New Issue
Block a user