From 7427fa3608b0c6d303649b09bcaff566a9923bed Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Fri, 10 May 2019 16:14:16 +0200 Subject: [PATCH] sdr profile selection frontend --- config_webrx.py | 57 ++++++++++++++++++++++++++++++++++++-------- htdocs/index.wrx | 4 ++++ htdocs/openwebrx.css | 22 +++++++++++------ htdocs/openwebrx.js | 11 +++++++++ owrx/controllers.py | 10 ++++++++ owrx/source.py | 37 +++++++++++++++++++++++----- 6 files changed, 118 insertions(+), 23 deletions(-) diff --git a/config_webrx.py b/config_webrx.py index 1ea9b06..4d04fdb 100644 --- a/config_webrx.py +++ b/config_webrx.py @@ -104,22 +104,59 @@ sdrs = { "rtlsdr": { "name": "RTL-SDR USB Stick", "type": "rtl_sdr", - "center_freq": 438800000, - "rf_gain": 30, - "samp_rate": 2400000, "ppm": 0, - "start_freq": 439275000, - "start_mod": "nfm" + "profiles": { + "70cm": { + "name": "70cm Relais", + "center_freq": 438800000, + "rf_gain": 30, + "samp_rate": 2400000, + "start_freq": 439275000, + "start_mod": "nfm" + }, + "2m": { + "name": "2m komplett", + "center_freq": 145000000, + "rf_gain": 30, + "samp_rate": 2400000, + "start_freq": 145725000, + "start_mod": "nfm" + } + } }, "sdrplay": { "name": "SDRPlay RSP2", "type": "sdrplay", - "center_freq": 14150000, - "rf_gain": 30, - "samp_rate": 500000, "ppm": 0, - "start_freq": 14070000, - "start_mod": "usb" + "profiles": { + "20m": { + "name":"20m", + "center_freq": 14150000, + "rf_gain": 30, + "samp_rate": 500000, + "start_freq": 14070000, + "start_mod": "usb" + }, + "40m": { + "name":"40m", + "center_freq": 7100000, + "rf_gain": 30, + "samp_rate": 500000, + "start_freq": 7070000, + "start_mod": "usb" + }, + "80m": { + "name":"80m", + "center_freq": 3650000, + "rf_gain": 30, + "samp_rate": 500000, + "start_freq": 3570000, + "start_mod": "usb" + } + } + }, + "test": { + "type": "test" } } diff --git a/htdocs/index.wrx b/htdocs/index.wrx index c2f5a00..ceb080d 100644 --- a/htdocs/index.wrx +++ b/htdocs/index.wrx @@ -82,6 +82,10 @@
---.--- MHz
---.--- MHz
+
+ +
FM
diff --git a/htdocs/openwebrx.css b/htdocs/openwebrx.css index e2c1c44..620b711 100644 --- a/htdocs/openwebrx.css +++ b/htdocs/openwebrx.css @@ -790,10 +790,7 @@ img.openwebrx-mirror-img transition: width 500ms, left 500ms; } -#openwebrx-secondary-demod-listbox -{ - width: 201px; - height: 27px; +.openwebrx-panel select { border-radius: 5px; background-color: #373737; color: White; @@ -805,16 +802,27 @@ img.openwebrx-mirror-img border-color: transparent; border-width: 0px; -moz-appearance: none; - padding-left:3px; } -#openwebrx-secondary-demod-listbox option -{ +.openwebrx-panel select option { border-width: 0px; background-color: #373737; color: White; } +#openwebrx-secondary-demod-listbox +{ + width: 201px; + height: 27px; + padding-left:3px; +} + +#openwebrx-sdr-profiles-listbox { + width: 100%; + font-size: 10pt; + height: 27px; +} + #openwebrx-cursor-blink { animation: cursor-blink 1s infinite; diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 2d622b0..d378ef4 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -1208,6 +1208,12 @@ function on_ws_recv(evt) var server_cpu_usage = json.value; progressbar_set(e("openwebrx-bar-server-cpu"),server_cpu_usage/100,"Server CPU [" + server_cpu_usage + "%]",server_cpu_usage>85); break; + case "profiles": + var listbox = e("openwebrx-sdr-profiles-listbox"); + listbox.innerHTML = json.value.map(function(profile){ + return '"; + }).join(""); + break; default: console.warn('received message of unknown type: ' + json.type); } @@ -2749,3 +2755,8 @@ function secondary_demod_waterfall_set_zoom(low_cut, high_cut) secondary_demod_canvases.map((x)=>{$(x).css("left",secondary_demod_canvas_left+"px").css("width",secondary_demod_canvas_width+"px");}); secondary_demod_update_channel_freq_from_event(); } + +function sdr_profile_changed() { + value = $('#openwebrx-sdr-profiles-listbox').val(); + ws.send(JSON.stringify({ type:"selectprofile", params:{ profile:value }})); +} diff --git a/owrx/controllers.py b/owrx/controllers.py index b18dfe9..239ee72 100644 --- a/owrx/controllers.py +++ b/owrx/controllers.py @@ -83,6 +83,9 @@ class OpenWebRxClient(object): receiver_details = dict((key, pm.getPropertyValue(key)) for key in receiver_keys) self.write_receiver_details(receiver_details) + profiles = [{"name": s.getName() + " " + p["name"], "id":sid + "|" + pid} for (sid, s) in SdrService.getSources().items() for (pid, p) in s.getProfiles().items()] + self.write_profiles(profiles) + CpuUsageThread.getSharedInstance().add_client(self) def sendConfig(self, key, value): @@ -149,6 +152,8 @@ class OpenWebRxClient(object): self.conn.send({"type":"config","value":cfg}) def write_receiver_details(self, details): self.conn.send({"type":"receiver_details","value":details}) + def write_profiles(self, profiles): + self.conn.send({"type":"profiles","value":profiles}) class WebSocketMessageHandler(object): def __init__(self): @@ -187,6 +192,11 @@ class WebSocketMessageHandler(object): if message["type"] == "setsdr": if "params" in message: self.client.setSdr(message["params"]["sdr"]) + if message["type"] == "selectprofile": + if "params" in message and "profile" in message["params"]: + profile = message["params"]["profile"].split("|") + self.client.setSdr(profile[0]) + self.client.sdr.activateProfile(profile[1]) else: print("received message without type: {0}".format(message)) diff --git a/owrx/source.py b/owrx/source.py index 4584520..650c15b 100644 --- a/owrx/source.py +++ b/owrx/source.py @@ -52,16 +52,24 @@ class SdrService(object): if id is None: # TODO: configure default sdr in config? right now it will pick the first one off the list. id = list(SdrService.sdrProps.keys())[0] - if not id in SdrService.sources: - props = SdrService.sdrProps[id] - className = ''.join(x for x in props["type"].title() if x.isalnum()) + "Source" - cls = getattr(sys.modules[__name__], className) - SdrService.sources[id] = cls(props, SdrService.getNextPort()) - return SdrService.sources[id] + sources = SdrService.getSources() + return sources[id] + @staticmethod + def getSources(): + SdrService.loadProps() + for id in SdrService.sdrProps.keys(): + if not id in SdrService.sources: + props = SdrService.sdrProps[id] + className = ''.join(x for x in props["type"].title() if x.isalnum()) + "Source" + cls = getattr(sys.modules[__name__], className) + SdrService.sources[id] = cls(props, SdrService.getNextPort()) + return SdrService.sources + class SdrSource(object): def __init__(self, props, port): self.props = props + self.activateProfile() self.rtlProps = self.props.collect( "type", "samp_rate", "nmux_memory", "center_freq", "ppm", "rf_gain", "lna_gain", "rf_amp" ).defaults(PropertyManager.getSharedInstance()) @@ -85,6 +93,23 @@ class SdrSource(object): self.command = None self.format_conversion = None + def activateProfile(self, id = None): + profiles = self.props["profiles"] + if id is None: + id = list(profiles.keys())[0] + print("activating profile {0}".format(id)) + profile = profiles[id] + for (key, value) in profile.items(): + # skip the name, that would overwrite the source name. + if key == "name": continue + self.props[key] = value + + def getProfiles(self): + return self.props["profiles"] + + def getName(self): + return self.props["name"] + def getProps(self): return self.props