mirror of
https://github.com/jketterl/openwebrx.git
synced 2025-12-06 07:12:09 +01:00
first shot at decoding ISM data with rtl_433
This commit is contained in:
parent
687bf1c3d2
commit
0c6de7cf2a
15
csdr/chain/rtl433.py
Normal file
15
csdr/chain/rtl433.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from owrx.ism.rtl433 import Rtl433Module, JsonParser
|
||||||
|
from csdr.chain.demodulator import ServiceDemodulator
|
||||||
|
|
||||||
|
|
||||||
|
class Rtl433(ServiceDemodulator):
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 250000
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(
|
||||||
|
[
|
||||||
|
Rtl433Module(),
|
||||||
|
JsonParser(),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
@ -1273,6 +1273,7 @@ img.openwebrx-mirror-img
|
||||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-content-container,
|
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-content-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-content-container,
|
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-content-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-content-container,
|
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-content-container,
|
||||||
|
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-content-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
|
#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="wspr"] #openwebrx-digimode-select-channel,
|
||||||
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
|
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
|
||||||
|
|
@ -1285,7 +1286,8 @@ img.openwebrx-mirror-img
|
||||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel,
|
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel,
|
||||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-select-channel,
|
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-select-channel,
|
||||||
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-select-channel,
|
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-select-channel,
|
||||||
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-select-channel
|
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-select-channel,
|
||||||
|
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-select-channel
|
||||||
{
|
{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -1302,7 +1304,8 @@ img.openwebrx-mirror-img
|
||||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container,
|
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-canvas-container,
|
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-canvas-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-canvas-container,
|
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-canvas-container,
|
||||||
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-canvas-container
|
#openwebrx-panel-digimodes[data-mode="adsb"] #openwebrx-digimode-canvas-container,
|
||||||
|
#openwebrx-panel-digimodes[data-mode="ism"] #openwebrx-digimode-canvas-container
|
||||||
{
|
{
|
||||||
height: 200px;
|
height: 200px;
|
||||||
margin: -10px;
|
margin: -10px;
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@
|
||||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-packet-message" style="display: none; width: 619px;" data-panel-name="aprs-message"></div>
|
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-packet-message" style="display: none; width: 619px;" data-panel-name="aprs-message"></div>
|
||||||
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-pocsag-message" style="display: none; width: 619px;" data-panel-name="pocsag-message"></div>
|
<div class="openwebrx-panel openwebrx-message-panel" id="openwebrx-panel-pocsag-message" style="display: none; width: 619px;" data-panel-name="pocsag-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-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-meta-panel" id="openwebrx-panel-metadata-m17" style="display: none;" data-panel-name="metadata-m17">
|
<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">
|
<div class="openwebrx-meta-slot">
|
||||||
<div class="openwebrx-meta-user-image">
|
<div class="openwebrx-meta-user-image">
|
||||||
|
|
|
||||||
|
|
@ -165,10 +165,9 @@ DemodulatorPanel.prototype.updatePanels = function() {
|
||||||
var mode = Modes.findByModulation(modulation);
|
var mode = Modes.findByModulation(modulation);
|
||||||
toggle_panel("openwebrx-panel-digimodes", modulation && (!mode || mode.secondaryFft));
|
toggle_panel("openwebrx-panel-digimodes", modulation && (!mode || mode.secondaryFft));
|
||||||
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0);
|
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0);
|
||||||
toggle_panel("openwebrx-panel-js8-message", modulation === "js8");
|
['js8', 'packet', 'pocsag', 'adsb', 'ism'].forEach(function(m) {
|
||||||
toggle_panel("openwebrx-panel-packet-message", modulation === "packet");
|
toggle_panel('openwebrx-panel-' + m + '-message', modulation === m);
|
||||||
toggle_panel("openwebrx-panel-pocsag-message", modulation === "pocsag");
|
});
|
||||||
toggle_panel('openwebrx-panel-adsb-message', modulation === 'adsb');
|
|
||||||
|
|
||||||
modulation = this.getDemodulator().get_modulation();
|
modulation = this.getDemodulator().get_modulation();
|
||||||
var showing = 'openwebrx-panel-metadata-' + modulation;
|
var showing = 'openwebrx-panel-metadata-' + modulation;
|
||||||
|
|
|
||||||
|
|
@ -393,4 +393,67 @@ $.fn.adsbMessagePanel = function () {
|
||||||
this.data('panel', new AdsbMessagePanel(this));
|
this.data('panel', new AdsbMessagePanel(this));
|
||||||
}
|
}
|
||||||
return this.data('panel');
|
return this.data('panel');
|
||||||
|
};
|
||||||
|
|
||||||
|
IsmMessagePanel = function(el) {
|
||||||
|
MessagePanel.call(this, el);
|
||||||
|
this.initClearTimer();
|
||||||
|
};
|
||||||
|
|
||||||
|
IsmMessagePanel.prototype = new MessagePanel();
|
||||||
|
|
||||||
|
IsmMessagePanel.prototype.supportsMessage = function(message) {
|
||||||
|
return message['mode'] === 'ISM';
|
||||||
|
};
|
||||||
|
|
||||||
|
IsmMessagePanel.prototype.render = function() {
|
||||||
|
$(this.el).append($(
|
||||||
|
'<table>' +
|
||||||
|
'<thead><tr>' +
|
||||||
|
'<th class="model">Model</th>' +
|
||||||
|
'<th class="id">ID</th>' +
|
||||||
|
'<th class="channel">Channel</th>' +
|
||||||
|
'<th class="message">Message</th>' +
|
||||||
|
'</tr></thead>' +
|
||||||
|
'<tbody></tbody>' +
|
||||||
|
'</table>'
|
||||||
|
));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IsmMessagePanel.prototype.pushMessage = function(message) {
|
||||||
|
var $t = $(this.el).find('table');
|
||||||
|
var $b = $t.find('tbody');
|
||||||
|
|
||||||
|
var ifDefined = function(input, formatter) {
|
||||||
|
if (typeof(input) !== 'undefined') {
|
||||||
|
if (formatter) return formatter(input);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
var mergeRemainingMessage = function(input, exclude) {
|
||||||
|
return Object.entries(input).map(function(entry) {
|
||||||
|
if (exclude.includes(entry[0])) return '';
|
||||||
|
return entry[0] + ': ' + entry[1] + ';';
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
$b.append($(
|
||||||
|
'<tr>' +
|
||||||
|
'<td class="model">' + ifDefined(message.model) + '</td>' +
|
||||||
|
'<td class="id">' + ifDefined(message.id) + '</td>' +
|
||||||
|
'<td class="channel">' + ifDefined(message.channel) + '</td>' +
|
||||||
|
'<td class="message">' + this.htmlEscape(mergeRemainingMessage(message, ['model', 'id', 'channel', 'mode', 'time'])) + '</td>' +
|
||||||
|
'</tr>'
|
||||||
|
));
|
||||||
|
$t.scrollTop($t[0].scrollHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.ismMessagePanel = function() {
|
||||||
|
if (!this.data('panel')) {
|
||||||
|
this.data('panel', new IsmMessagePanel(this));
|
||||||
|
}
|
||||||
|
return this.data('panel');
|
||||||
};
|
};
|
||||||
|
|
@ -864,6 +864,7 @@ function on_ws_recv(evt) {
|
||||||
$('#openwebrx-panel-packet-message').packetMessagePanel(),
|
$('#openwebrx-panel-packet-message').packetMessagePanel(),
|
||||||
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel(),
|
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel(),
|
||||||
$('#openwebrx-panel-adsb-message').adsbMessagePanel(),
|
$('#openwebrx-panel-adsb-message').adsbMessagePanel(),
|
||||||
|
$('#openwebrx-panel-ism-message').ismMessagePanel(),
|
||||||
$("#openwebrx-panel-js8-message").js8()
|
$("#openwebrx-panel-js8-message").js8()
|
||||||
];
|
];
|
||||||
if (!panels.some(function(panel) {
|
if (!panels.some(function(panel) {
|
||||||
|
|
@ -1470,6 +1471,7 @@ function secondary_demod_init() {
|
||||||
$('#openwebrx-panel-packet-message').packetMessagePanel();
|
$('#openwebrx-panel-packet-message').packetMessagePanel();
|
||||||
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel();
|
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel();
|
||||||
$('#openwebrx-panel-adsb-message').adsbMessagePanel();
|
$('#openwebrx-panel-adsb-message').adsbMessagePanel();
|
||||||
|
$('#openwebrx-panel-ism-message').ismMessagePanel();
|
||||||
$('#openwebrx-panel-js8-message').js8();
|
$('#openwebrx-panel-js8-message').js8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,9 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
|
||||||
elif mod == "adsb":
|
elif mod == "adsb":
|
||||||
from csdr.chain.dump1090 import Dump1090
|
from csdr.chain.dump1090 import Dump1090
|
||||||
return Dump1090()
|
return Dump1090()
|
||||||
|
elif mod == "ism":
|
||||||
|
from csdr.chain.rtl433 import Rtl433
|
||||||
|
return Rtl433()
|
||||||
|
|
||||||
def setSecondaryDemodulator(self, mod):
|
def setSecondaryDemodulator(self, mod):
|
||||||
demodulator = self._getSecondaryDemodulator(mod)
|
demodulator = self._getSecondaryDemodulator(mod)
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ class FeatureDetector(object):
|
||||||
"js8call": ["js8", "js8py"],
|
"js8call": ["js8", "js8py"],
|
||||||
"drm": ["dream"],
|
"drm": ["dream"],
|
||||||
"dump1090": ["dump1090"],
|
"dump1090": ["dump1090"],
|
||||||
|
"ism": ["rtl_433"],
|
||||||
}
|
}
|
||||||
|
|
||||||
def feature_availability(self):
|
def feature_availability(self):
|
||||||
|
|
@ -591,3 +592,13 @@ class FeatureDetector(object):
|
||||||
[Debian alternatives system](https://wiki.debian.org/DebianAlternatives) to achieve this.
|
[Debian alternatives system](https://wiki.debian.org/DebianAlternatives) to achieve this.
|
||||||
"""
|
"""
|
||||||
return self.command_is_runnable("dump1090 --version")
|
return self.command_is_runnable("dump1090 --version")
|
||||||
|
|
||||||
|
def has_rtl_433(self):
|
||||||
|
"""
|
||||||
|
OpenWebRX can make use of the `rtl_433` software to decode various signals in the ISM bands.
|
||||||
|
|
||||||
|
You can find more information [here](https://github.com/merbanan/rtl_433).
|
||||||
|
|
||||||
|
Debian and Ubuntu based systems should be able to install the package `rtl-433` from the package manager.
|
||||||
|
"""
|
||||||
|
return self.command_is_runnable("rtl_433 -h")
|
||||||
|
|
|
||||||
28
owrx/ism/rtl433.py
Normal file
28
owrx/ism/rtl433.py
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
from pycsdr.modules import ExecModule
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from csdr.module import LineBasedModule
|
||||||
|
import json
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Rtl433Module(ExecModule):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(
|
||||||
|
Format.COMPLEX_FLOAT,
|
||||||
|
Format.CHAR,
|
||||||
|
["rtl_433", "-r", "cf32:-", "-F", "json", "-M", "time:unix", "-C", "si"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class JsonParser(LineBasedModule):
|
||||||
|
def process(self, line):
|
||||||
|
try:
|
||||||
|
msg = json.loads(line.decode())
|
||||||
|
msg["mode"] = "ISM"
|
||||||
|
logger.debug(msg)
|
||||||
|
return msg
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.exception("error parsing rtl433 json")
|
||||||
|
|
@ -174,6 +174,14 @@ class Modes(object):
|
||||||
squelch=False,
|
squelch=False,
|
||||||
secondaryFft=False,
|
secondaryFft=False,
|
||||||
),
|
),
|
||||||
|
DigitalMode(
|
||||||
|
"ism",
|
||||||
|
"ISM",
|
||||||
|
underlying=["empty"],
|
||||||
|
bandpass=None,
|
||||||
|
requirements=["ism"],
|
||||||
|
squelch=False,
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue