restore js8 functionality

This commit is contained in:
Jakob Ketterl 2021-09-06 22:50:57 +02:00
parent 6014ce8921
commit f9f0bdde12
8 changed files with 45 additions and 78 deletions

View File

@ -70,7 +70,7 @@ Js8Thread.prototype.getMessageDuration = function() {
Js8Thread.prototype.getMode = function() {
// we filter messages by mode, so the first one is as good as any
if (!this.messages.length) return;
return this.messages[0].mode;
return this.messages[0].js8mode;
};
Js8Thread.prototype.acceptsMode = function(mode) {
@ -117,6 +117,10 @@ Js8Threader = function(el){
Js8Threader.prototype = new MessagePanel();
Js8Threader.prototype.supportsMessage = function(message) {
return message['mode'] === 'JS8';
};
Js8Threader.prototype.render = function() {
$(this.el).append($(
'<table>' +
@ -158,7 +162,7 @@ Js8Threader.prototype.pushMessage = function(message) {
var thread;
// only look for exising threads if the message is not a starting message
if ((message.thread_type & 1) === 0) {
thread = this.findThread(message.freq, message.mode);
thread = this.findThread(message.freq, message.js8mode);
}
if (!thread) {
var line = $("<tr></tr>");

View File

@ -821,9 +821,6 @@ function on_ws_recv(evt) {
this.update(json['value']);
});
break;
case "js8_message":
$("#openwebrx-panel-js8-message").js8().pushMessage(json['value']);
break;
case "dial_frequencies":
var as_bookmarks = json['value'].map(function (d) {
return {
@ -849,7 +846,8 @@ function on_ws_recv(evt) {
var panels = [
$("#openwebrx-panel-wsjt-message").wsjtMessagePanel(),
$('#openwebrx-panel-packet-message').packetMessagePanel(),
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel()
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel(),
$("#openwebrx-panel-js8-message").js8()
];
if (!panels.some(function(panel) {
if (!panel.supportsMessage(value)) return false;

View File

@ -437,22 +437,6 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
def write_backoff_message(self, reason):
self.send({"type": "backoff", "reason": reason})
def write_js8_message(self, frame: Js8Frame, freq: int):
self.send(
{
"type": "js8_message",
"value": {
"msg": str(frame),
"timestamp": frame.timestamp,
"db": frame.db,
"dt": frame.dt,
"freq": freq + frame.freq,
"thread_type": frame.thread_type,
"mode": frame.mode,
},
}
)
def write_modes(self, modes):
def to_json(m):
res = {

View File

@ -281,7 +281,6 @@ class DspManager(Output, SdrSourceEventClient):
self.sdrSource = sdrSource
self.parsers = {
"meta": MetaParser(self.handler),
"js8_demod": Js8Parser(self.handler),
}
self.props = PropertyStack()
@ -364,18 +363,6 @@ class DspManager(Output, SdrSourceEventClient):
# TODO there's multiple outputs depending on the modulation right now
self.wireOutput("secondary_demod", buffer)
def set_dial_freq(changes):
if (
"center_freq" not in self.props
or self.props["center_freq"] is None
or "offset_freq" not in self.props
or self.props["offset_freq"] is None
):
return
freq = self.props["center_freq"] + self.props["offset_freq"]
for parser in self.parsers.values():
parser.setDialFrequency(freq)
if "start_mod" in self.props:
self.setDemodulator(self.props["start_mod"])
mode = Modes.findByModulation(self.props["start_mod"])
@ -409,7 +396,6 @@ class DspManager(Output, SdrSourceEventClient):
# self.props.wireProperty("wfm_deemphasis_tau", self.dsp.set_wfm_deemphasis_tau),
# TODO
# self.props.wireProperty("digital_voice_codecserver", self.dsp.set_codecserver),
self.props.filter("center_freq", "offset_freq").wire(set_dial_freq),
]
# TODO
@ -489,6 +475,8 @@ class DspManager(Output, SdrSourceEventClient):
# TODO add remaining modes
if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]:
return AudioChopperDemodulator(mod, WsjtParser())
elif mod == "js8":
return AudioChopperDemodulator(mod, Js8Parser())
elif mod == "packet":
return PacketDemodulator()
elif mod == "pocsag":

View File

@ -1,5 +1,4 @@
from owrx.audio import AudioChopperProfile, ConfigWiredProfileSource
from owrx.parser import Parser
import re
from js8py import Js8
from js8py.frames import Js8FrameHeartbeat, Js8FrameCompound
@ -8,6 +7,7 @@ from owrx.metrics import Metrics, CounterMetric
from owrx.config import Config
from abc import ABCMeta, abstractmethod
from owrx.reporting import ReportingEngine
from owrx.bands import Bandplan
from typing import List
import logging
@ -81,13 +81,15 @@ class Js8TurboProfile(Js8Profile):
return "C"
class Js8Parser(Parser):
class Js8Parser:
decoderRegex = re.compile(" ?<Decode(Started|Debug|Finished)>")
def parse(self, raw):
def parse(self, profile, freq, raw_msg):
try:
profile, freq, raw_msg = raw
self.setDialFrequency(freq)
band = None
if freq is not None:
band = Bandplan.getSharedInstance().findBand(freq)
msg = raw_msg.decode().rstrip()
if Js8Parser.decoderRegex.match(msg):
return
@ -95,38 +97,48 @@ class Js8Parser(Parser):
return
frame = Js8().parse_message(msg)
self.handler.write_js8_message(frame, self.dial_freq)
self.pushDecode()
self.pushDecode(band)
if (isinstance(frame, Js8FrameHeartbeat) or isinstance(frame, Js8FrameCompound)) and frame.grid:
Map.getSharedInstance().updateLocation(
frame.callsign, LocatorLocation(frame.grid), "JS8", self.band
frame.callsign, LocatorLocation(frame.grid), "JS8", band
)
ReportingEngine.getSharedInstance().spot(
{
"callsign": frame.callsign,
"mode": "JS8",
"locator": frame.grid,
"freq": self.dial_freq + frame.freq,
"freq": freq + frame.freq,
"db": frame.db,
"timestamp": frame.timestamp,
"msg": str(frame),
}
)
out = {
"mode": "JS8",
"msg": str(frame),
"timestamp": frame.timestamp,
"db": frame.db,
"dt": frame.dt,
"freq": freq + frame.freq,
"thread_type": frame.thread_type,
"js8mode": frame.mode,
}
return out
except Exception:
logger.exception("error while parsing js8 message")
def pushDecode(self):
def pushDecode(self, band):
metrics = Metrics.getSharedInstance()
band = "unknown"
if self.band is not None:
band = self.band.getName()
if band is None:
band = "unknown"
bandName = "unknown"
if band is not None:
bandName = band.getName()
name = "js8call.decodes.{band}.JS8".format(band=band)
name = "js8call.decodes.{band}.JS8".format(band=bandName)
metric = metrics.getMetric(name)
if metric is None:
metric = CounterMetric()

View File

@ -5,7 +5,6 @@ from datetime import datetime, timedelta
import logging
import threading
from owrx.map import Map, LatLngLocation
from owrx.parser import Parser
from owrx.aprs import AprsParser, AprsLocation
from abc import ABC, abstractmethod
@ -159,9 +158,9 @@ class DStarEnricher(Enricher):
return meta
class MetaParser(Parser):
class MetaParser:
def __init__(self, handler):
super().__init__(handler)
self.handler = handler
self.enrichers = {
"DMR": RadioIDEnricher("dmr", self),
"YSF": YsfMetaEnricher(self),

View File

@ -1,20 +0,0 @@
from abc import ABC, abstractmethod
from owrx.bands import Bandplan
class Parser(ABC):
def __init__(self, handler):
self.handler = handler
self.dial_freq = None
self.band = None
@abstractmethod
def parse(self, raw):
pass
def setDialFrequency(self, freq):
self.dial_freq = freq
self.band = Bandplan.getSharedInstance().findBand(freq)
def getBand(self):
return self.band

View File

@ -3,10 +3,10 @@ from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass
from owrx.sdr import SdrService
from owrx.bands import Bandplan
from owrx.wsjt import WsjtParser
from owrx.js8 import Js8Parser
from owrx.config import Config
from owrx.source.resampler import Resampler
from owrx.property import PropertyLayer, PropertyDeleted
from js8py import Js8Frame
from owrx.service.schedule import ServiceScheduler
from owrx.service.chain import ServiceDemodulatorChain
from owrx.modes import Modes, DigitalMode
@ -250,7 +250,7 @@ class ServiceHandler(SdrSourceEventClient):
logger.warning("mode is not a digimode: %s", mode)
return None
demod = self._getDemodulator(modeObject.get_modulation(), source.getProps())
demod = self._getDemodulator(modeObject.get_modulation())
secondaryDemod = self._getSecondaryDemodulator(modeObject.modulation)
center_freq = source.getProps()["center_freq"]
sampleRate = source.getProps()["samp_rate"]
@ -269,7 +269,7 @@ class ServiceHandler(SdrSourceEventClient):
return chain
# TODO move this elsewhere
def _getDemodulator(self, demod: Union[str, BaseDemodulatorChain], props):
def _getDemodulator(self, demod: Union[str, BaseDemodulatorChain]):
if isinstance(demod, BaseDemodulatorChain):
return demod
# TODO: move this to Modes
@ -288,6 +288,8 @@ class ServiceHandler(SdrSourceEventClient):
# TODO add remaining modes
if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]:
return AudioChopperDemodulator(mod, WsjtParser())
elif mod == "js8":
return AudioChopperDemodulator(mod, Js8Parser())
elif mod == "packet":
return PacketDemodulator(service=True)
return None