keep more parameters on the server side

This commit is contained in:
Jakob Ketterl 2020-04-26 18:45:41 +02:00
parent 449b3b3986
commit 26321ab68b
6 changed files with 106 additions and 123 deletions

View File

@ -607,6 +607,8 @@ class dsp(object):
self.restart()
def set_demodulator(self, demodulator):
if demodulator in ["usb", "lsb", "cw"]:
demodulator = "ssb"
if self.demodulator == demodulator:
return
self.demodulator = demodulator

View File

@ -446,6 +446,10 @@ input[type=range]:focus::-ms-fill-upper
margin-right: 5px;
}
.openwebrx-demodulator-button.disabled {
color: #B6B6B6;
}
.openwebrx-square-button img
{
height: 27px;

View File

@ -15,9 +15,8 @@ var Modes = {
},
updateModePanel:function() {
var available = this.modes.filter(function(m){ return m.isAvailable(); });
var normalModes = available.filter(function(m){ return !m.digimode; });
var digiModes = available.filter(function(m){ return m.digimode; });
var normalModes = available.filter(function(m){ return m.type === 'analog'; });
var digiModes = available.filter(function(m){ return m.type === 'digimode'; });
var html = []
@ -63,8 +62,14 @@ var Modes = {
var Mode = function(json){
this.modulation = json.modulation;
this.name = json.name;
this.digimode = json.digimode;
this.type = json.type;
this.requirements = json.requirements;
if (json.bandpass) {
this.bandpass = json.bandpass;
}
if (this.type === 'digimode') {
this.underlying = json.underlying;
}
};
Mode.prototype.isAvailable = function(){

View File

@ -374,40 +374,10 @@ function Demodulator_default_analog(offset_frequency, subtype) {
};
}
};
//Subtypes only define some filter parameters and the mod string sent to server,
//so you may set these parameters in your custom child class.
//Why? As of demodulation is done on the server, difference is mainly on the server side.
this.server_mod = subtype;
if (subtype === "lsb") {
this.low_cut = -3000;
this.high_cut = -300;
this.server_mod = "ssb";
}
else if (subtype === "usb") {
this.low_cut = 300;
this.high_cut = 3000;
this.server_mod = "ssb";
}
else if (subtype === "cw") {
this.low_cut = 700;
this.high_cut = 900;
this.server_mod = "ssb";
}
else if (subtype === "nfm") {
this.low_cut = -4000;
this.high_cut = 4000;
}
else if (subtype === "dmr" || subtype === "ysf") {
this.low_cut = -4000;
this.high_cut = 4000;
}
else if (subtype === "dstar" || subtype === "nxdn") {
this.low_cut = -3250;
this.high_cut = 3250;
}
else if (subtype === "am") {
this.low_cut = -4000;
this.high_cut = 4000;
var mode = Modes.findByModulation(subtype);
if (mode) {
this.low_cut = mode.bandpass.low_cut;
this.high_cut = mode.bandpass.high_cut;
}
this.wait_for_timer = false;
@ -433,7 +403,7 @@ function Demodulator_default_analog(offset_frequency, subtype) {
"high_cut": this.high_cut,
"offset_freq": this.offset_frequency
};
if (first_time) params.mod = this.server_mod;
if (first_time) params.mod = this.subtype;
ws.send(JSON.stringify({"type": "dspcontrol", "params": params}));
mkenvelopes(get_visible_freq_range());
};
@ -1174,6 +1144,7 @@ function on_ws_recv(evt) {
break;
case 'modes':
Modes.setModes(json['value']);
demodulator_buttons_update();
break;
default:
console.warn('received message of unknown type: ' + json['type']);
@ -1947,29 +1918,24 @@ function initPanels() {
}
function demodulator_buttons_update() {
$(".openwebrx-demodulator-button").removeClass("highlighted");
var $buttons = $(".openwebrx-demodulator-button");
$buttons.removeClass("highlighted").removeClass('disabled');
if (!demodulators.length) return;
var mod = demodulators[0].subtype;
$("#openwebrx-button-" + mod).addClass("highlighted");
if (secondary_demod) {
$("#openwebrx-button-dig").addClass("highlighted");
$('#openwebrx-secondary-demod-listbox').val(secondary_demod);
} else switch (demodulators[0].subtype) {
case "lsb":
case "usb":
case "cw":
if (demodulators[0].high_cut - demodulators[0].low_cut < 300)
$("#openwebrx-button-cw").addClass("highlighted");
else {
if (demodulators[0].high_cut < 0)
$("#openwebrx-button-lsb").addClass("highlighted");
else if (demodulators[0].low_cut > 0)
$("#openwebrx-button-usb").addClass("highlighted");
else $("#openwebrx-button-lsb, #openwebrx-button-usb").addClass("highlighted");
}
break;
default:
var mod = demodulators[0].subtype;
$("#openwebrx-button-" + mod).addClass("highlighted");
break;
var mode = Modes.findByModulation(secondary_demod);
if (mode) {
var active = mode.underlying.map(function(u){ return 'openwebrx-button-' + u; });
console.info(active);
$buttons.filter(function(){
console.info(this.id);
console.info(active.indexOf(this.id));
return this.id !== "openwebrx-button-dig" && active.indexOf(this.id) < 0;
}).addClass('disabled');
}
}
}
@ -2013,41 +1979,19 @@ function demodulator_digital_replace_last() {
function demodulator_digital_replace(subtype) {
if (secondary_demod === subtype) return;
var mode = Modes.findByModulation(subtype);
if (mode && !mode.isAvailable()) {
if (!mode) {
return;
}
if (!mode.isAvailable()) {
divlog('Digital mode "' + mode.name + '" not supported. Please check requirements', true);
return;
}
switch (subtype) {
case "bpsk31":
case "bpsk63":
case "rtty":
case "ft8":
case "jt65":
case "jt9":
case "ft4":
case "js8":
secondary_demod_start(subtype);
demodulator_analog_replace('usb', true);
break;
case "wspr":
secondary_demod_start(subtype);
demodulator_analog_replace('usb', true);
// WSPR only samples between 1400 and 1600 Hz
demodulators[0].low_cut = 1350;
demodulators[0].high_cut = 1650;
demodulators[0].set();
break;
case "packet":
secondary_demod_start(subtype);
demodulator_analog_replace('nfm', true);
break;
case "pocsag":
secondary_demod_start(subtype);
demodulator_analog_replace('nfm', true);
demodulators[0].low_cut = -6000;
demodulators[0].high_cut = 6000;
demodulators[0].set();
break;
secondary_demod_start(subtype);
demodulator_analog_replace(mode.underlying[0], true);
if (mode.bandpass) {
demodulators[0].low_cut = mode.bandpass.low_cut;
demodulators[0].high_cut = mode.bandpass.high_cut;
demodulators[0].set();
}
demodulator_buttons_update();
$('#openwebrx-panel-digimodes').attr('data-mode', subtype);

View File

@ -11,7 +11,7 @@ from owrx.bookmarks import Bookmarks
from owrx.map import Map
from owrx.locator import Locator
from owrx.property import PropertyStack
from owrx.modes import Modes
from owrx.modes import Modes, DigitalMode
from multiprocessing import Queue
from queue import Full
from js8py import Js8Frame
@ -114,18 +114,18 @@ class OpenWebRxReceiverClient(Client):
receiver_info["locator"] = Locator.fromCoordinates(receiver_info["receiver_gps"])
self.write_receiver_details(receiver_info)
# TODO unsubscribe
receiver_details.wire(send_receiver_info)
send_receiver_info()
self.__sendProfiles()
features = FeatureDetector().feature_availability()
self.write_features(features)
modes = Modes.getModes()
self.write_modes(modes)
# TODO unsubscribe
receiver_details.wire(send_receiver_info)
send_receiver_info()
self.__sendProfiles()
CpuUsageThread.getSharedInstance().add_client(self)
def __sendProfiles(self):
@ -350,12 +350,23 @@ class OpenWebRxReceiverClient(Client):
}})
def write_modes(self, modes):
self.send({"type": "modes", "value": [{
"modulation": m.modulation,
"name": m.name,
"digimode": m.digimode,
"requirements": m.requirements
} for m in modes]})
def to_json(m):
res = {
"modulation": m.modulation,
"name": m.name,
"type": "digimode" if isinstance(m, DigitalMode) else "analog",
"requirements": m.requirements
}
if m.bandpass is not None:
res["bandpass"] = {
"low_cut": m.bandpass.low_cut,
"high_cut": m.bandpass.high_cut
}
if isinstance(m, DigitalMode):
res["underlying"] = m.underlying
return res
self.send({"type": "modes", "value": [to_json(m) for m in modes]})
class MapConnection(Client):

View File

@ -2,13 +2,19 @@ from owrx.feature import FeatureDetector
from functools import reduce
class Bandpass(object):
def __init__(self, low_cut, high_cut):
self.low_cut = low_cut
self.high_cut = high_cut
class Mode(object):
def __init__(self, modulation, name, requirements=None, service=False, digimode=False):
def __init__(self, modulation, name, bandpass: Bandpass = None, requirements=None, service=False):
self.modulation = modulation
self.name = name
self.digimode = digimode
self.requirements = requirements if requirements is not None else []
self.service = service
self.bandpass = bandpass
def is_available(self):
fd = FeatureDetector()
@ -20,26 +26,37 @@ class Mode(object):
return self.service
class AnalogMode(Mode):
pass
class DigitalMode(Mode):
def __init__(self, modulation, name, underlying, bandpass: Bandpass = None, requirements=None, service=False):
super().__init__(modulation, name, bandpass, requirements, service)
self.underlying = underlying
class Modes(object):
mappings = [
Mode("nfm", "FM"),
Mode("am", "AM"),
Mode("lsb", "LSB"),
Mode("usb", "USB"),
Mode("cw", "CW"),
Mode("dmr", "DMR", requirements=["digital_voice_digiham"]),
Mode("dstar", "DStar", requirements=["digital_voice_dsd"]),
Mode("nxdn", "NXDN", requirements=["digital_voice_dsd"]),
Mode("ysf", "YSF", requirements=["digital_voice_digiham"]),
Mode("bpsk31", "BPSK31", digimode=True),
Mode("bpsk63", "BPSK63", digimode=True),
Mode("ft8", "FT8", requirements=["wsjt-x"], service=True, digimode=True),
Mode("ft4", "FT4", requirements=["wsjt-x"], service=True, digimode=True),
Mode("jt65", "JT65", requirements=["wsjt-x"], service=True, digimode=True),
Mode("jt9", "JT9", requirements=["wsjt-x"], service=True, digimode=True),
Mode("wspr", "WSPR", requirements=["wsjt-x"], service=True, digimode=True),
Mode("packet", "Packet", ["packet"], service=True, digimode=True),
Mode("js8", "JS8Call", requirements=["js8call"], service=True, digimode=True),
AnalogMode("nfm", "FM", bandpass=Bandpass(-4000, 4000)),
AnalogMode("am", "AM", bandpass=Bandpass(-4000, 4000)),
AnalogMode("lsb", "LSB", bandpass=Bandpass(-3000, -300)),
AnalogMode("usb", "USB", bandpass=Bandpass(300, 3000)),
AnalogMode("cw", "CW", bandpass=Bandpass(700, 900)),
AnalogMode("dmr", "DMR", bandpass=Bandpass(-4000, 4000), requirements=["digital_voice_digiham"]),
AnalogMode("dstar", "DStar", bandpass=Bandpass(-3250, 3250), requirements=["digital_voice_dsd"]),
AnalogMode("nxdn", "NXDN", bandpass=Bandpass(-3250, 3250), requirements=["digital_voice_dsd"]),
AnalogMode("ysf", "YSF", bandpass=Bandpass(-4000, 4000), requirements=["digital_voice_digiham"]),
DigitalMode("bpsk31", "BPSK31", underlying=["usb"]),
DigitalMode("bpsk63", "BPSK63", underlying=["usb"]),
DigitalMode("ft8", "FT8", underlying=["usb"], requirements=["wsjt-x"], service=True),
DigitalMode("ft4", "FT4", underlying=["usb"], requirements=["wsjt-x"], service=True),
DigitalMode("jt65", "JT65", underlying=["usb"], requirements=["wsjt-x"], service=True),
DigitalMode("jt9", "JT9", underlying=["usb"], requirements=["wsjt-x"], service=True),
DigitalMode("wspr", "WSPR", underlying=["usb"], bandpass=Bandpass(1350, 1650), requirements=["wsjt-x"], service=True),
DigitalMode("js8", "JS8Call", underlying=["usb"], requirements=["js8call"], service=True),
DigitalMode("packet", "Packet", underlying=["nfm", "usb", "lsb"], requirements=["packet"], service=True),
DigitalMode("pocsag", "Pocsag", underlying=["nfm"], bandpass=Bandpass(-6000, 6000), requirements=["pocsag"])
]
@staticmethod