add more inputs, bind to actual data

This commit is contained in:
Jakob Ketterl 2021-02-19 18:18:25 +01:00
parent 27c16c3720
commit 039b57d28b
10 changed files with 76 additions and 19 deletions

View File

@ -10,11 +10,10 @@ class Section(object):
self.title = title self.title = title
self.inputs = inputs self.inputs = inputs
def render_inputs(self): def render_inputs(self, data):
config = Config.get() return "".join([i.render(data) for i in self.inputs])
return "".join([i.render(config) for i in self.inputs])
def render(self): def render(self, data):
return """ return """
<div class="col-12 settings-section"> <div class="col-12 settings-section">
<h3 class="settings-header"> <h3 class="settings-header">
@ -23,7 +22,7 @@ class Section(object):
{inputs} {inputs}
</div> </div>
""".format( """.format(
title=self.title, inputs=self.render_inputs() title=self.title, inputs=self.render_inputs(data)
) )
def parse(self, data): def parse(self, data):
@ -44,8 +43,11 @@ class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=AB
def getTitle(self): def getTitle(self):
pass pass
def getData(self):
return Config.get()
def render_sections(self): def render_sections(self):
sections = "".join(section.render() for section in self.getSections()) sections = "".join(section.render(self.getData()) for section in self.getSections())
return """ return """
<form class="settings-body" method="POST"> <form class="settings-body" method="POST">
{sections} {sections}
@ -78,6 +80,7 @@ class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=AB
def processFormData(self): def processFormData(self):
self.processData(self.parseFormData()) self.processData(self.parseFormData())
self.send_redirect(self.request.path)
def processData(self, data): def processData(self, data):
config = Config.get() config = Config.get()
@ -88,4 +91,3 @@ class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=AB
else: else:
config[k] = v config[k] = v
config.store() config.store()
self.send_redirect(self.request.path)

View File

@ -5,6 +5,10 @@ from owrx.source import SdrDeviceDescription, SdrDeviceDescriptionMissing
from owrx.config import Config from owrx.config import Config
from urllib.parse import quote, unquote from urllib.parse import quote, unquote
import logging
logger = logging.getLogger(__name__)
class SdrDeviceListController(AuthorizationMixin, WebpageController): class SdrDeviceListController(AuthorizationMixin, WebpageController):
def header_variables(self): def header_variables(self):
@ -52,6 +56,13 @@ class SdrDeviceController(SettingsFormController):
super().__init__(handler, request, options) super().__init__(handler, request, options)
self.device = self._get_device() self.device = self._get_device()
def getData(self):
return self.device
def processData(self, data):
# TODO implement storing of data here
logger.debug(data)
def getSections(self): def getSections(self):
try: try:
description = SdrDeviceDescription.getByType(self.device["type"]) description = SdrDeviceDescription.getByType(self.device["type"])

View File

@ -139,8 +139,8 @@ class TextAreaInput(Input):
class CheckboxInput(Input): class CheckboxInput(Input):
def __init__(self, id, label, checkboxText, infotext=None): def __init__(self, id, label, checkboxText, infotext=None, converter: Converter = None):
super().__init__(id, label, infotext=infotext) super().__init__(id, label, infotext=infotext, converter=converter)
self.checkboxText = checkboxText self.checkboxText = checkboxText
def render_input(self, value): def render_input(self, value):
@ -162,7 +162,7 @@ class CheckboxInput(Input):
return " ".join(["form-check", "form-control-sm"]) return " ".join(["form-check", "form-control-sm"])
def parse(self, data): def parse(self, data):
return {self.id: self.id in data and data[self.id][0] == "on"} return {self.id: self.converter.convert_from_form(self.id in data and data[self.id][0] == "on")}
class Option(object): class Option(object):

View File

@ -22,15 +22,21 @@ class NullConverter(Converter):
class OptionalConverter(Converter): class OptionalConverter(Converter):
""" """
Maps None to an empty string, and reverse Transforms a special form value to None
useful for optional fields The default is look for an empty string, but this can be used to adopt to other types.
If the default is not found, the actual value is passed to the sub_converter for further transformation.
useful for optional fields since None is not stored in the configuration
""" """
def __init__(self, sub_converter: Converter = None, defaultFormValue=""):
self.sub_converter = NullConverter() if sub_converter is None else sub_converter
self.defaultFormValue = defaultFormValue
def convert_to_form(self, value): def convert_to_form(self, value):
return "" if value is None else value return self.defaultFormValue if value is None else self.sub_converter.convert_to_form(value)
def convert_from_form(self, value): def convert_from_form(self, value):
return value if value else None return None if value == self.defaultFormValue else self.sub_converter.convert_to_form(value)
class IntConverter(Converter): class IntConverter(Converter):

13
owrx/form/soapy.py Normal file
View File

@ -0,0 +1,13 @@
from owrx.form import FloatInput
class SoapyGainInput(FloatInput):
def __init__(self, id, label, gain_stages):
super().__init__(id, label)
self.gain_stages = gain_stages
def render_input(self, value):
if not self.gain_stages:
return super().render_input(value)
# TODO implement input for multiple gain stages here
return "soapy gain stages here..."

View File

@ -117,6 +117,7 @@ class Router(object):
), ),
StaticRoute("/settings/sdr", SdrDeviceListController), StaticRoute("/settings/sdr", SdrDeviceListController),
RegexRoute("/settings/sdr/(.+)", SdrDeviceController), RegexRoute("/settings/sdr/(.+)", SdrDeviceController),
RegexRoute("/settings/sdr/(.+)", SdrDeviceController, method="POST", options={"action": "processFormData"}),
StaticRoute("/settings/bookmarks", BookmarksController), StaticRoute("/settings/bookmarks", BookmarksController),
StaticRoute("/settings/bookmarks", BookmarksController, method="POST", options={"action": "new"}), StaticRoute("/settings/bookmarks", BookmarksController, method="POST", options={"action": "new"}),
RegexRoute("/settings/bookmarks/(.+)", BookmarksController, method="POST", options={"action": "update"}), RegexRoute("/settings/bookmarks/(.+)", BookmarksController, method="POST", options={"action": "update"}),

View File

@ -10,7 +10,8 @@ from abc import ABC, abstractmethod
from owrx.command import CommandMapper from owrx.command import CommandMapper
from owrx.socket import getAvailablePort from owrx.socket import getAvailablePort
from owrx.property import PropertyStack, PropertyLayer from owrx.property import PropertyStack, PropertyLayer
from owrx.form import Input, TextInput, NumberInput, CheckboxInput from owrx.form import Input, TextInput, NumberInput, CheckboxInput, FloatInput
from owrx.form.converter import IntConverter, OptionalConverter
from owrx.controllers.settings import Section from owrx.controllers.settings import Section
from typing import List from typing import List
@ -375,14 +376,25 @@ class SdrDeviceDescription(object):
def getInputs(self) -> List[Input]: def getInputs(self) -> List[Input]:
return [ return [
TextInput("name", "Device name"), TextInput("name", "Device name"),
NumberInput("ppm", "Frequency correction", append="ppm"), NumberInput(
"ppm",
"Frequency correction",
append="ppm",
converter=OptionalConverter(IntConverter(), defaultFormValue="0"),
),
CheckboxInput( CheckboxInput(
"always-on", "always-on",
"", "",
checkboxText="Keep device running at all times", checkboxText="Keep device running at all times",
infotext="Prevents shutdown of the device when idle. Useful for devices with unreliable startup." infotext="Prevents shutdown of the device when idle. Useful for devices with unreliable startup.",
), ),
CheckboxInput("services", "", "Run services on this device"), CheckboxInput(
"services",
"",
"Run background services on this device",
converter=OptionalConverter(defaultFormValue=True),
),
FloatInput("rf_gain", "Device gain"),
] ]
def mergeInputs(self, *args): def mergeInputs(self, *args):

View File

@ -4,6 +4,7 @@ import socket
from owrx.command import Flag, Option from owrx.command import Flag, Option
from typing import List from typing import List
from owrx.form import Input, NumberInput from owrx.form import Input, NumberInput
from owrx.form.converter import OptionalConverter, IntConverter
import logging import logging
@ -84,6 +85,7 @@ class ConnectorDeviceDescription(SdrDeviceDescription):
infotext="Activate an rtl_tcp compatible interface on the port number specified.<br />" infotext="Activate an rtl_tcp compatible interface on the port number specified.<br />"
+ "Note: Port is only available on the local machine, not on the network.<br />" + "Note: Port is only available on the local machine, not on the network.<br />"
+ "Note: IQ data may be degraded by the downsampling process to 8 bits.", + "Note: IQ data may be degraded by the downsampling process to 8 bits.",
converter=OptionalConverter(IntConverter()),
) )
], ],
) )

View File

@ -20,4 +20,5 @@ class SdrplaySource(SoapyConnectorSource):
class SdrplayDeviceDescription(SoapyConnectorDeviceDescription): class SdrplayDeviceDescription(SoapyConnectorDeviceDescription):
pass def getGainStages(self):
return ["RFGR", "IFGR"]

View File

@ -3,6 +3,7 @@ from owrx.command import Option
from owrx.source.connector import ConnectorSource, ConnectorDeviceDescription from owrx.source.connector import ConnectorSource, ConnectorDeviceDescription
from typing import List from typing import List
from owrx.form import Input, TextInput from owrx.form import Input, TextInput
from owrx.form.soapy import SoapyGainInput
class SoapyConnectorSource(ConnectorSource, metaclass=ABCMeta): class SoapyConnectorSource(ConnectorSource, metaclass=ABCMeta):
@ -108,5 +109,13 @@ class SoapyConnectorDeviceDescription(ConnectorDeviceDescription):
"Device Identifier", "Device Identifier",
infotext='SoapySDR device identifier string (example: "serial=123456789")', infotext='SoapySDR device identifier string (example: "serial=123456789")',
), ),
SoapyGainInput(
"rf_gain",
"Device Gain",
gain_stages=self.getGainStages(),
),
], ],
) )
def getGainStages(self):
return []