Merge branch 'develop' into pycsdr

This commit is contained in:
Jakob Ketterl 2021-01-17 20:58:02 +01:00
commit db83256bcf
6 changed files with 36 additions and 23 deletions

View File

@ -11,11 +11,17 @@ It has the following features:
- filter passband can be set from GUI - filter passband can be set from GUI
- it extensively uses HTML5 features like WebSocket, Web Audio API, and Canvas - it extensively uses HTML5 features like WebSocket, Web Audio API, and Canvas
- it works in Google Chrome, Chromium and Mozilla Firefox - it works in Google Chrome, Chromium and Mozilla Firefox
- currently supports RTL-SDR, HackRF, SDRplay, AirSpy, LimeSDR, PlutoSDR - supports a wide range of [SDR hardware](https://github.com/jketterl/openwebrx/wiki/Supported-Hardware#sdr-devices)
- Multiple SDR devices can be used simultaneously - Multiple SDR devices can be used simultaneously
- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag) - [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag)
- [dsd](https://github.com/f4exb/dsdcc) based demodulators (D-Star, NXDN) - [dsd](https://github.com/f4exb/dsdcc) based demodulators (D-Star, NXDN)
- [wsjt-x](https://physics.princeton.edu/pulsar/k1jt/wsjtx.html) based demodulators (FT8, FT4, WSPR, JT65, JT9) - [wsjt-x](https://physics.princeton.edu/pulsar/k1jt/wsjtx.html) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4,
FST4W)
- [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets
- [JS8Call](http://js8call.com/) support
- [DRM](https://github.com/jketterl/openwebrx/wiki/DRM-demodulator-notes) support
- [FreeDV](https://github.com/jketterl/openwebrx/wiki/FreeDV-demodulator-notes) support
- M17 support based on [m17-cxx-demod](https://github.com/mobilinkd/m17-cxx-demod)
## Setup ## Setup
@ -35,6 +41,9 @@ If you have trouble setting up or configuring your receiver, you have some great
you just generally want to have some OpenWebRX-related chat, come visit us over on you just generally want to have some OpenWebRX-related chat, come visit us over on
[our groups.io group](https://groups.io/g/openwebrx). [our groups.io group](https://groups.io/g/openwebrx).
If you want to hang out, chat, or get in touch directly with the developers, receiver operators or users, feel free to
drop by in [our Discord server](https://discord.gg/gnE9hPz).
## Usage tips ## Usage tips
You can zoom the waterfall display by the mouse wheel. You can also drag the waterfall to pan across it. You can zoom the waterfall display by the mouse wheel. You can also drag the waterfall to pan across it.

View File

@ -927,6 +927,7 @@ img.openwebrx-mirror-img
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
} }
.openwebrx-meta-slot > * { .openwebrx-meta-slot > * {
@ -944,8 +945,6 @@ img.openwebrx-mirror-img
display: block; display: block;
content: ""; content: "";
background-image: url("../gfx/openwebrx-mute.png"); background-image: url("../gfx/openwebrx-mute.png");
width:100%;
height:133px;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;

View File

@ -186,7 +186,7 @@ PacketMessagePanel.prototype.pushMessage = function(msg) {
'style="' + stylesToString(styles) + '"' 'style="' + stylesToString(styles) + '"'
].join(' '); ].join(' ');
if (msg.lat && msg.lon) { if (msg.lat && msg.lon) {
link = '<a ' + attrs + ' href="map?callsign=' + source + '" target="openwebrx-map">' + overlay + '</a>'; link = '<a ' + attrs + ' href="map?callsign=' + encodeURIComponent(source) + '" target="openwebrx-map">' + overlay + '</a>';
} else { } else {
link = '<div ' + attrs + '>' + overlay + '</div>' link = '<div ' + attrs + '>' + overlay + '</div>'
} }

View File

@ -162,7 +162,7 @@ YsfMetaPanel.prototype.setLocation = function(lat, lon, callsign) {
this.hasLocation = hasLocation; this.callsign = callsign; this.hasLocation = hasLocation; this.callsign = callsign;
var html = ''; var html = '';
if (hasLocation) { if (hasLocation) {
html = '<a class="openwebrx-maps-pin" href="map?callsign=' + callsign + '" target="_blank"></a>'; html = '<a class="openwebrx-maps-pin" href="map?callsign=' + encodeURIComponent(callsign) + '" target="_blank"></a>';
} }
this.el.find('.openwebrx-ysf-source .location').html(html); this.el.find('.openwebrx-ysf-source .location').html(html);
}; };

View File

@ -9,7 +9,7 @@
}); });
var expectedCallsign; var expectedCallsign;
if (query.callsign) expectedCallsign = query.callsign; if (query.callsign) expectedCallsign = decodeURIComponent(query.callsign);
var expectedLocator; var expectedLocator;
if (query.locator) expectedLocator = query.locator; if (query.locator) expectedLocator = query.locator;
@ -137,14 +137,13 @@
marker.band = update.band; marker.band = update.band;
marker.comment = update.location.comment; marker.comment = update.location.comment;
// TODO the trim should happen on the server side if (expectedCallsign && expectedCallsign == update.callsign) {
if (expectedCallsign && expectedCallsign == update.callsign.trim()) {
map.panTo(pos); map.panTo(pos);
showMarkerInfoWindow(update.callsign, pos); showMarkerInfoWindow(update.callsign, pos);
expectedCallsign = false; expectedCallsign = false;
} }
if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign.trim()) { if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign) {
showMarkerInfoWindow(infowindow.callsign, pos); showMarkerInfoWindow(infowindow.callsign, pos);
} }
break; break;
@ -319,6 +318,8 @@
delete infowindow.callsign; delete infowindow.callsign;
}); });
} }
delete infowindow.locator;
delete infowindow.callsign;
return infowindow; return infowindow;
} }

View File

@ -24,7 +24,7 @@ class DmrCache(object):
self.cacheTimeout = timedelta(seconds=86400) self.cacheTimeout = timedelta(seconds=86400)
def isValid(self, key): def isValid(self, key):
if not key in self.cache: if key not in self.cache:
return False return False
entry = self.cache[key] entry = self.cache[key]
return entry["timestamp"] + self.cacheTimeout > datetime.now() return entry["timestamp"] + self.cacheTimeout > datetime.now()
@ -55,20 +55,20 @@ class DmrMetaEnricher(object):
def enrich(self, meta): def enrich(self, meta):
if not Config.get()["digital_voice_dmr_id_lookup"]: if not Config.get()["digital_voice_dmr_id_lookup"]:
return None return meta
if not "source" in meta: if "source" not in meta:
return None return meta
id = meta["source"] id = meta["source"]
cache = DmrCache.getSharedInstance() cache = DmrCache.getSharedInstance()
if not cache.isValid(id): if not cache.isValid(id):
if not id in self.threads: if id not in self.threads:
self.threads[id] = threading.Thread(target=self.downloadRadioIdData, args=[id], daemon=True) self.threads[id] = threading.Thread(target=self.downloadRadioIdData, args=[id], daemon=True)
self.threads[id].start() self.threads[id].start()
return None return meta
data = cache.get(id) data = cache.get(id)
if "count" in data and data["count"] > 0 and "results" in data: if "count" in data and data["count"] > 0 and "results" in data:
return data["results"][0] meta["additional"] = data["results"][0]
return None return meta
class YsfMetaEnricher(object): class YsfMetaEnricher(object):
@ -76,11 +76,17 @@ class YsfMetaEnricher(object):
self.parser = parser self.parser = parser
def enrich(self, meta): def enrich(self, meta):
for key in ["source", "up", "down", "target"]:
if key in meta:
meta[key] = meta[key].strip()
for key in ["lat", "lon"]:
if key in meta:
meta[key] = float(meta[key])
if "source" in meta and "lat" in meta and "lon" in meta: if "source" in meta and "lat" in meta and "lon" in meta:
# TODO parsing the float values should probably happen earlier # TODO parsing the float values should probably happen earlier
loc = LatLngLocation(float(meta["lat"]), float(meta["lon"])) loc = LatLngLocation(meta["lat"], meta["lon"])
Map.getSharedInstance().updateLocation(meta["source"], loc, "YSF", self.parser.getBand()) Map.getSharedInstance().updateLocation(meta["source"], loc, "YSF", self.parser.getBand())
return None return meta
class MetaParser(Parser): class MetaParser(Parser):
@ -95,7 +101,5 @@ class MetaParser(Parser):
if "protocol" in meta: if "protocol" in meta:
protocol = meta["protocol"] protocol = meta["protocol"]
if protocol in self.enrichers: if protocol in self.enrichers:
additional_data = self.enrichers[protocol].enrich(meta) meta = self.enrichers[protocol].enrich(meta)
if additional_data is not None:
meta["additional"] = additional_data
self.handler.write_metadata(meta) self.handler.write_metadata(meta)