Adding UI for the DSC decoder.
This commit is contained in:
parent
1b9a525449
commit
8fdbf90303
|
|
@ -8,6 +8,7 @@ from pycsdr.types import Format
|
|||
from owrx.aprs.direwolf import DirewolfModule
|
||||
from owrx.sstv import SstvParser
|
||||
from owrx.fax import FaxParser
|
||||
from owrx.dsc import DscParser
|
||||
from owrx.config import Config
|
||||
|
||||
|
||||
|
|
@ -258,10 +259,11 @@ class SitorBDemodulator(SecondaryDemodulator, SecondarySelectorChain):
|
|||
|
||||
|
||||
class DscDemodulator(SecondaryDemodulator, SecondarySelectorChain):
|
||||
def __init__(self, baudRate=100, bandWidth=170, invert=False):
|
||||
self.baudRate = baudRate
|
||||
self.bandWidth = bandWidth
|
||||
self.invert = invert
|
||||
def __init__(self, baudRate=100, bandWidth=170, invert=False, service=False):
|
||||
self.baudRate = baudRate
|
||||
self.bandWidth = bandWidth
|
||||
self.invert = invert
|
||||
self.parser = DscParser(service=service)
|
||||
# this is an assumption, we will adjust in setSampleRate
|
||||
self.sampleRate = 12000
|
||||
secondary_samples_per_bit = int(round(self.sampleRate / self.baudRate))
|
||||
|
|
@ -274,6 +276,7 @@ class DscDemodulator(SecondaryDemodulator, SecondarySelectorChain):
|
|||
TimingRecovery(Format.FLOAT, secondary_samples_per_bit, loop_gain, 10),
|
||||
Ccir493Decoder(invert=invert),
|
||||
DscDecoder(),
|
||||
self.parser
|
||||
]
|
||||
super().__init__(workers)
|
||||
|
||||
|
|
@ -289,3 +292,4 @@ class DscDemodulator(SecondaryDemodulator, SecondarySelectorChain):
|
|||
loop_gain = self.sampleRate / self.getBandwidth() / 5
|
||||
self.replace(2, Lowpass(Format.FLOAT, cutoff))
|
||||
self.replace(3, TimingRecovery(Format.FLOAT, secondary_samples_per_bit, loop_gain, 10))
|
||||
|
||||
|
|
|
|||
|
|
@ -1360,6 +1360,45 @@ img.openwebrx-mirror-img
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message {
|
||||
height: 310px;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message tbody {
|
||||
height: 280px;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message .timestamp {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message .src {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message .dst {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message .data {
|
||||
width: 326px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#openwebrx-panel-dsc-message .message {
|
||||
width: 566px;
|
||||
max-width: 566px;
|
||||
column-span: all;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#openwebrx-panel-ism-message {
|
||||
height: 310px;
|
||||
}
|
||||
|
|
@ -1533,6 +1572,7 @@ img.openwebrx-mirror-img
|
|||
#openwebrx-panel-digimodes[data-mode="sstv"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fax"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="dsc"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
|
||||
|
|
@ -1580,7 +1620,8 @@ img.openwebrx-mirror-img
|
|||
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="sstv"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fax"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-canvas-container
|
||||
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="dsc"] #openwebrx-digimode-canvas-container
|
||||
{
|
||||
height: 200px;
|
||||
margin: -10px;
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-hfdl-message" style="display: none; width: 619px;" data-panel-name="hfdl-message"></div>
|
||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-adsb-message" style="display: none; width: 619px;" data-panel-name="adsb-message"></div>
|
||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-ism-message" style="display: none; width: 619px;" data-panel-name="ism-message"></div>
|
||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-dsc-message" style="display: none; width: 619px;" data-panel-name="dsc-message"></div>
|
||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-rds-message" style="display: none; width: 92%; max-width: 450px;" data-panel-name="rds-message"></div>
|
||||
<div class="openwebrx-panel openwebrx-meta-panel" id="openwebrx-panel-metadata-m17" style="display: none;" data-panel-name="metadata-m17">
|
||||
<div class="openwebrx-meta-slot">
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ DemodulatorPanel.prototype.updatePanels = function() {
|
|||
// Packet modes share the same panel
|
||||
toggle_panel("openwebrx-panel-packet-message", ['packet', 'ais'].indexOf(modulation) >= 0);
|
||||
// these modes come with their own
|
||||
['js8', 'page', 'pocsag', 'sstv', 'fax', 'ism', 'rds'].forEach(function(m) {
|
||||
['js8', 'page', 'pocsag', 'sstv', 'fax', 'ism', 'dsc', 'rds'].forEach(function(m) {
|
||||
toggle_panel('openwebrx-panel-' + m + '-message', modulation === m);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -562,6 +562,66 @@ $.fn.adsbMessagePanel = function() {
|
|||
return this.data('panel');
|
||||
};
|
||||
|
||||
DscMessagePanel = function(el) {
|
||||
MessagePanel.call(this, el);
|
||||
this.initClearTimer();
|
||||
}
|
||||
|
||||
DscMessagePanel.prototype = Object.create(MessagePanel.prototype);
|
||||
|
||||
DscMessagePanel.prototype.supportsMessage = function(message) {
|
||||
return message['mode'] === 'DSC';
|
||||
};
|
||||
|
||||
DscMessagePanel.prototype.render = function() {
|
||||
$(this.el).append($(
|
||||
'<table>' +
|
||||
'<thead><tr>' +
|
||||
'<th class="timestamp">Time</th>' +
|
||||
'<th class="src">From</th>' +
|
||||
'<th class="dst">To</th>' +
|
||||
'<th class="data">Data</th>' +
|
||||
'</tr></thead>' +
|
||||
'<tbody></tbody>' +
|
||||
'</table>'
|
||||
));
|
||||
};
|
||||
|
||||
DscMessagePanel.prototype.pushMessage = function(msg) {
|
||||
var tstamp = 0;
|
||||
var src = '*';
|
||||
var dst = '*';
|
||||
var data = '';
|
||||
|
||||
// Append report
|
||||
var $b = $(this.el).find('tbody');
|
||||
$b.append($(
|
||||
'<tr>' +
|
||||
'<td class="timestamp">' + tstamp + '</td>' +
|
||||
'<td class="src">' + src + '</td>' +
|
||||
'<td class="dst">' + dst + '</td>' +
|
||||
'<td class="data" style="text-align:left;">' + data + '</td>' +
|
||||
'</tr>'
|
||||
));
|
||||
|
||||
// Append messsage if present
|
||||
if (msg.message) {
|
||||
$b.append($(
|
||||
'<tr><td class="message" colspan="4">' + Utils.htmlEscape(msg.message) + '</td></tr>'
|
||||
))
|
||||
}
|
||||
|
||||
// Jump list to the last received message
|
||||
this.scrollToBottom();
|
||||
};
|
||||
|
||||
$.fn.dscMessagePanel = function() {
|
||||
if (!this.data('panel')) {
|
||||
this.data('panel', new DscMessagePanel(this));
|
||||
}
|
||||
return this.data('panel');
|
||||
};
|
||||
|
||||
IsmMessagePanel = function(el) {
|
||||
MessagePanel.call(this, el);
|
||||
this.initClearTimer();
|
||||
|
|
|
|||
|
|
@ -1169,7 +1169,7 @@ function on_ws_recv(evt) {
|
|||
break;
|
||||
case 'secondary_demod':
|
||||
var value = json['value'];
|
||||
var panels = ['wsjt', 'packet', 'pocsag', 'page', 'sstv', 'fax', 'ism', 'hfdl', 'adsb'].map(function(id) {
|
||||
var panels = ['wsjt', 'packet', 'pocsag', 'page', 'sstv', 'fax', 'ism', 'hfdl', 'adsb', 'dsc'].map(function(id) {
|
||||
return $('#openwebrx-panel-' + id + '-message')[id + 'MessagePanel']();
|
||||
});
|
||||
panels.push($('#openwebrx-panel-js8-message').js8());
|
||||
|
|
@ -1846,7 +1846,7 @@ function secondary_demod_init() {
|
|||
.mousedown(secondary_demod_canvas_container_mousedown)
|
||||
.mouseenter(secondary_demod_canvas_container_mousein)
|
||||
.mouseleave(secondary_demod_canvas_container_mouseleave);
|
||||
['wsjt', 'packet', 'pocsag', 'page', 'sstv', 'fax', 'ism', 'hfdl', 'adsb'].forEach(function(id){
|
||||
['wsjt', 'packet', 'pocsag', 'page', 'sstv', 'fax', 'ism', 'hfdl', 'adsb', 'dsc'].forEach(function(id){
|
||||
$('#openwebrx-panel-' + id + '-message')[id + 'MessagePanel']();
|
||||
})
|
||||
$('#openwebrx-panel-js8-message').js8();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
from owrx.toolbox import TextParser
|
||||
from owrx.color import ColorCache
|
||||
import json
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DscParser(TextParser):
|
||||
def __init__(self, service: bool = False):
|
||||
# Colors will be assigned via this cache
|
||||
self.colors = ColorCache()
|
||||
# Construct parent object
|
||||
super().__init__(filePrefix="DSC", service=service)
|
||||
|
||||
def parse(self, msg: bytes):
|
||||
# Do not parse in service mode
|
||||
if self.service:
|
||||
return None
|
||||
# Expect JSON data in text form
|
||||
out = json.loads(msg)
|
||||
# Add mode name and a color to identify the sender
|
||||
out["mode"] = "DSC"
|
||||
out["color"] = self.colors.getColor(out["src"])
|
||||
logger.debug("{0}".format(out))
|
||||
return out
|
||||
|
|
@ -142,8 +142,7 @@ class Modes(object):
|
|||
DigitalMode("rtty450", "RTTY-450 (50N)", underlying=["usb", "lsb"]),
|
||||
DigitalMode("rtty85", "RTTY-85 (50N)", underlying=["usb", "lsb"]),
|
||||
DigitalMode("sitorb", "SITOR-B", underlying=["usb"]),
|
||||
# Currently in development
|
||||
# DigitalMode("dsc", "DSC", underlying=["usb"]),
|
||||
DigitalMode("dsc", "DSC", underlying=["usb"]),
|
||||
WsjtMode("ft8", "FT8"),
|
||||
WsjtMode("ft4", "FT4"),
|
||||
WsjtMode("jt65", "JT65"),
|
||||
|
|
|
|||
Loading…
Reference in New Issue