add support for DMR locations
This commit is contained in:
parent
6fbe6b4983
commit
78dcdd5715
@ -115,7 +115,7 @@
|
||||
<img class="directcall" src="static/gfx/openwebrx-directcall.svg">
|
||||
<img class="groupcall" src="static/gfx/openwebrx-groupcall.svg">
|
||||
</div>
|
||||
<div class="openwebrx-dmr-id"></div>
|
||||
<div class="openwebrx-dmr-id"><span class="location"></span><span class="dmr-id"></span></div>
|
||||
<div class="openwebrx-dmr-name"></div>
|
||||
<div class="openwebrx-dmr-target"></div>
|
||||
<div class="mute">
|
||||
@ -128,7 +128,7 @@
|
||||
<img class="directcall" src="static/gfx/openwebrx-directcall.svg">
|
||||
<img class="groupcall" src="static/gfx/openwebrx-groupcall.svg">
|
||||
</div>
|
||||
<div class="openwebrx-dmr-id"></div>
|
||||
<div class="openwebrx-dmr-id"><span class="location"></span><span class="dmr-id"></span></div>
|
||||
<div class="openwebrx-dmr-name"></div>
|
||||
<div class="openwebrx-dmr-target"></div>
|
||||
<div class="mute">
|
||||
|
@ -26,16 +26,27 @@ DmrMetaSlot.prototype.update = function(data) {
|
||||
this.setName(data['additional'] && data['additional']['fname']);
|
||||
this.setMode(['group', 'direct'].includes(data['type']) ? data['type'] : undefined);
|
||||
this.setTarget(data['target']);
|
||||
this.setLocation(data['lat'], data['lon'], this.getCallsign(data));
|
||||
this.el.addClass("active");
|
||||
} else {
|
||||
this.clear();
|
||||
}
|
||||
};
|
||||
|
||||
DmrMetaSlot.prototype.getCallsign = function(data) {
|
||||
if ('additional' in data) {
|
||||
return data['additional']['callsign'];
|
||||
}
|
||||
if ('talkeralias' in data) {
|
||||
var matches = /^([A-Z0-9]+)(\s.*)?$/.exec(data['talkeralias']);
|
||||
if (matches) return matches[1];
|
||||
}
|
||||
};
|
||||
|
||||
DmrMetaSlot.prototype.setId = function(id) {
|
||||
if (this.id === id) return;
|
||||
this.id = id;
|
||||
this.el.find('.openwebrx-dmr-id').text(id || '');
|
||||
this.el.find('.openwebrx-dmr-id .dmr-id').text(id || '');
|
||||
}
|
||||
|
||||
DmrMetaSlot.prototype.setName = function(name) {
|
||||
@ -59,11 +70,23 @@ DmrMetaSlot.prototype.setTarget = function(target) {
|
||||
this.el.find('.openwebrx-dmr-target').text(target || '');
|
||||
}
|
||||
|
||||
DmrMetaSlot.prototype.setLocation = function(lat, lon, callsign) {
|
||||
var hasLocation = lat && lon && callsign && callsign != '';
|
||||
if (hasLocation === this.hasLocation && this.callsign === callsign) return;
|
||||
this.hasLocation = hasLocation; this.callsign = callsign;
|
||||
var html = '';
|
||||
if (hasLocation) {
|
||||
html = '<a class="openwebrx-maps-pin" href="map?callsign=' + encodeURIComponent(callsign) + '" target="_blank"><svg viewBox="0 0 20 35"><use xlink:href="static/gfx/svg-defs.svg#maps-pin"></use></svg></a>';
|
||||
}
|
||||
this.el.find('.openwebrx-dmr-id .location').html(html);
|
||||
}
|
||||
|
||||
DmrMetaSlot.prototype.clear = function() {
|
||||
this.setId();
|
||||
this.setName();
|
||||
this.setMode();
|
||||
this.setTarget();
|
||||
this.setLocation();
|
||||
this.el.removeClass("active");
|
||||
};
|
||||
|
||||
@ -250,7 +273,7 @@ NxdnMetaPanel.prototype = new MetaPanel();
|
||||
NxdnMetaPanel.prototype.update = function(data) {
|
||||
if (!this.isSupported(data)) return;
|
||||
|
||||
if (data['sync'] && data['sync'] == 'voice') {
|
||||
if (data['sync'] && data['sync'] === 'voice') {
|
||||
this.el.find(".openwebrx-meta-slot").addClass("active");
|
||||
this.setSource(data['additional'] && data['additional']['callsign'] || data['source']);
|
||||
this.setName(data['additional'] && data['additional']['fname']);
|
||||
|
@ -1266,6 +1266,9 @@ function digimodes_init() {
|
||||
$('.openwebrx-dmr-timeslot-panel').click(function (e) {
|
||||
$(e.currentTarget).toggleClass("muted");
|
||||
update_dmr_timeslot_filtering();
|
||||
// don't mute when the location icon is clicked
|
||||
}).find('.location').click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$('.openwebrx-meta-panel').metaPanel();
|
||||
|
76
owrx/meta.py
76
owrx/meta.py
@ -2,7 +2,8 @@ import json
|
||||
import logging
|
||||
import threading
|
||||
import pickle
|
||||
from abc import ABC, abstractmethod
|
||||
import re
|
||||
from abc import ABC, ABCMeta, abstractmethod
|
||||
from datetime import datetime, timedelta
|
||||
from urllib import request
|
||||
from urllib.error import HTTPError
|
||||
@ -120,28 +121,71 @@ class RadioIDEnricher(Enricher):
|
||||
return meta
|
||||
|
||||
|
||||
class YsfMetaEnricher(Enricher):
|
||||
def enrich(self, meta, callback):
|
||||
for key in ["source", "up", "down", "target"]:
|
||||
if key in meta:
|
||||
meta[key] = meta[key].strip()
|
||||
class DigihamEnricher(Enricher, metaclass=ABCMeta):
|
||||
def parseCoordinate(self, meta, mode):
|
||||
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:
|
||||
callsign = self.getCallsign(meta)
|
||||
if callsign is not None and "lat" in meta and "lon" in meta:
|
||||
loc = LatLngLocation(meta["lat"], meta["lon"])
|
||||
Map.getSharedInstance().updateLocation(meta["source"], loc, "YSF", self.parser.getBand())
|
||||
Map.getSharedInstance().updateLocation(callsign, loc, mode, self.parser.getBand())
|
||||
return meta
|
||||
|
||||
@abstractmethod
|
||||
def getCallsign(self, meta):
|
||||
pass
|
||||
|
||||
|
||||
class DmrEnricher(DigihamEnricher, RadioIDEnricher):
|
||||
# callsign must be uppercase alphanumeric and at the beginning
|
||||
# if there's anything after the callsign, it must be separated by a whitespace
|
||||
talkerAliasRegex = re.compile("^([A-Z0-9]+)(\\s.*)?$")
|
||||
|
||||
def __init__(self, parser):
|
||||
super().__init__("dmr", parser)
|
||||
|
||||
def getCallsign(self, meta):
|
||||
# there's no explicit callsign data in dmr, so we can only rely on one of the following:
|
||||
# a) a callsign provided by a radioid lookup
|
||||
if "additional" in meta and "callsign" in meta["additional"]:
|
||||
return meta["additional"]["callsign"]
|
||||
# b) a callsign in the talker alias
|
||||
if "talkeralias" in meta:
|
||||
matches = DmrEnricher.talkerAliasRegex.match(meta["talkeralias"])
|
||||
if matches:
|
||||
return matches.group(1)
|
||||
|
||||
def enrich(self, meta, callback):
|
||||
def asyncParse(meta):
|
||||
self.parseCoordinate(meta, "DMR")
|
||||
callback(meta)
|
||||
meta = super().enrich(meta, asyncParse)
|
||||
meta = self.parseCoordinate(meta, "DMR")
|
||||
return meta
|
||||
|
||||
|
||||
class DStarEnricher(Enricher):
|
||||
class YsfMetaEnricher(DigihamEnricher):
|
||||
def getCallsign(self, meta):
|
||||
if "source" in meta:
|
||||
return meta["source"]
|
||||
|
||||
def enrich(self, meta, callback):
|
||||
for key in ["lat", "lon"]:
|
||||
if key in meta:
|
||||
meta[key] = float(meta[key])
|
||||
if "ourcall" in meta and "lat" in meta and "lon" in meta:
|
||||
loc = LatLngLocation(meta["lat"], meta["lon"])
|
||||
Map.getSharedInstance().updateLocation(meta["ourcall"], loc, "D-Star", self.parser.getBand())
|
||||
meta = self.parseCoordinate(meta, "YSF")
|
||||
return meta
|
||||
|
||||
|
||||
class DStarEnricher(DigihamEnricher):
|
||||
def getCallsign(self, meta):
|
||||
if "ourcall" in meta:
|
||||
return meta["ourcall"]
|
||||
|
||||
def enrich(self, meta, callback):
|
||||
meta = self.parseCoordinate(meta, "D-Star")
|
||||
meta = self.parseDprs(meta)
|
||||
return meta
|
||||
|
||||
def parseDprs(self, meta):
|
||||
if "dprs" in meta:
|
||||
try:
|
||||
# we can send the DPRS stuff through our APRS parser to extract the information
|
||||
@ -168,7 +212,7 @@ class DStarEnricher(Enricher):
|
||||
class MetaParser(PickleModule):
|
||||
def __init__(self):
|
||||
self.enrichers = {
|
||||
"DMR": RadioIDEnricher("dmr", self),
|
||||
"DMR": DmrEnricher(self),
|
||||
"YSF": YsfMetaEnricher(self),
|
||||
"DSTAR": DStarEnricher(self),
|
||||
"NXDN": RadioIDEnricher("nxdn", self),
|
||||
|
Loading…
Reference in New Issue
Block a user