diff --git a/README.md b/README.md index f3862d7..9d6ccfa 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,17 @@ It has the following features: - filter passband can be set from GUI - it extensively uses HTML5 features like WebSocket, Web Audio API, and Canvas - 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 - [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag) - [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 @@ -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 [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 You can zoom the waterfall display by the mouse wheel. You can also drag the waterfall to pan across it. diff --git a/htdocs/css/openwebrx.css b/htdocs/css/openwebrx.css index 5ede36a..3195997 100644 --- a/htdocs/css/openwebrx.css +++ b/htdocs/css/openwebrx.css @@ -927,6 +927,7 @@ img.openwebrx-mirror-img display: flex; flex-direction: column; + position: relative; } .openwebrx-meta-slot > * { @@ -944,8 +945,6 @@ img.openwebrx-mirror-img display: block; content: ""; background-image: url("../gfx/openwebrx-mute.png"); - width:100%; - height:133px; background-position: center; background-repeat: no-repeat; cursor: pointer; diff --git a/htdocs/lib/MessagePanel.js b/htdocs/lib/MessagePanel.js index 597475b..dc8995e 100644 --- a/htdocs/lib/MessagePanel.js +++ b/htdocs/lib/MessagePanel.js @@ -186,7 +186,7 @@ PacketMessagePanel.prototype.pushMessage = function(msg) { 'style="' + stylesToString(styles) + '"' ].join(' '); if (msg.lat && msg.lon) { - link = '' + overlay + ''; + link = '' + overlay + ''; } else { link = '
' + overlay + '
' } diff --git a/htdocs/lib/MetaPanel.js b/htdocs/lib/MetaPanel.js index 849cb21..8a7c85c 100644 --- a/htdocs/lib/MetaPanel.js +++ b/htdocs/lib/MetaPanel.js @@ -162,7 +162,7 @@ YsfMetaPanel.prototype.setLocation = function(lat, lon, callsign) { this.hasLocation = hasLocation; this.callsign = callsign; var html = ''; if (hasLocation) { - html = ''; + html = ''; } this.el.find('.openwebrx-ysf-source .location').html(html); }; diff --git a/htdocs/map.js b/htdocs/map.js index fd3e740..afc3448 100644 --- a/htdocs/map.js +++ b/htdocs/map.js @@ -9,7 +9,7 @@ }); var expectedCallsign; - if (query.callsign) expectedCallsign = query.callsign; + if (query.callsign) expectedCallsign = decodeURIComponent(query.callsign); var expectedLocator; if (query.locator) expectedLocator = query.locator; @@ -137,14 +137,13 @@ marker.band = update.band; marker.comment = update.location.comment; - // TODO the trim should happen on the server side - if (expectedCallsign && expectedCallsign == update.callsign.trim()) { + if (expectedCallsign && expectedCallsign == update.callsign) { map.panTo(pos); showMarkerInfoWindow(update.callsign, pos); expectedCallsign = false; } - if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign.trim()) { + if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign) { showMarkerInfoWindow(infowindow.callsign, pos); } break; @@ -319,6 +318,8 @@ delete infowindow.callsign; }); } + delete infowindow.locator; + delete infowindow.callsign; return infowindow; } diff --git a/owrx/meta.py b/owrx/meta.py index c7e9c1d..85de1ba 100644 --- a/owrx/meta.py +++ b/owrx/meta.py @@ -24,7 +24,7 @@ class DmrCache(object): self.cacheTimeout = timedelta(seconds=86400) def isValid(self, key): - if not key in self.cache: + if key not in self.cache: return False entry = self.cache[key] return entry["timestamp"] + self.cacheTimeout > datetime.now() @@ -55,20 +55,20 @@ class DmrMetaEnricher(object): def enrich(self, meta): if not Config.get()["digital_voice_dmr_id_lookup"]: - return None - if not "source" in meta: - return None + return meta + if "source" not in meta: + return meta id = meta["source"] cache = DmrCache.getSharedInstance() 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].start() - return None + return meta data = cache.get(id) if "count" in data and data["count"] > 0 and "results" in data: - return data["results"][0] - return None + meta["additional"] = data["results"][0] + return meta class YsfMetaEnricher(object): @@ -76,11 +76,17 @@ class YsfMetaEnricher(object): self.parser = parser 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: # 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()) - return None + return meta class MetaParser(Parser): @@ -95,7 +101,5 @@ class MetaParser(Parser): if "protocol" in meta: protocol = meta["protocol"] if protocol in self.enrichers: - additional_data = self.enrichers[protocol].enrich(meta) - if additional_data is not None: - meta["additional"] = additional_data + meta = self.enrichers[protocol].enrich(meta) self.handler.write_metadata(meta)