diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js
index 4c61af24..0ae61904 100644
--- a/htdocs/lib/DemodulatorPanel.js
+++ b/htdocs/lib/DemodulatorPanel.js
@@ -165,10 +165,9 @@ DemodulatorPanel.prototype.updatePanels = function() {
var mode = Modes.findByModulation(modulation);
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-js8-message", modulation === "js8");
- toggle_panel("openwebrx-panel-packet-message", modulation === "packet");
- toggle_panel("openwebrx-panel-pocsag-message", modulation === "pocsag");
- toggle_panel('openwebrx-panel-adsb-message', modulation === 'adsb');
+ ['js8', 'packet', 'pocsag', 'adsb', 'ism'].forEach(function(m) {
+ toggle_panel('openwebrx-panel-' + m + '-message', modulation === m);
+ });
modulation = this.getDemodulator().get_modulation();
var showing = 'openwebrx-panel-metadata-' + modulation;
diff --git a/htdocs/lib/MessagePanel.js b/htdocs/lib/MessagePanel.js
index 2792cb38..f54364a0 100644
--- a/htdocs/lib/MessagePanel.js
+++ b/htdocs/lib/MessagePanel.js
@@ -393,4 +393,67 @@ $.fn.adsbMessagePanel = function () {
this.data('panel', new AdsbMessagePanel(this));
}
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($(
+ '
' +
+ '' +
+ '| Model | ' +
+ 'ID | ' +
+ 'Channel | ' +
+ 'Message | ' +
+ '
' +
+ '' +
+ '
'
+ ));
+
+};
+
+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($(
+ '
' +
+ '| ' + ifDefined(message.model) + ' | ' +
+ '' + ifDefined(message.id) + ' | ' +
+ '' + ifDefined(message.channel) + ' | ' +
+ '' + this.htmlEscape(mergeRemainingMessage(message, ['model', 'id', 'channel', 'mode', 'time'])) + ' | ' +
+ '
'
+ ));
+ $t.scrollTop($t[0].scrollHeight);
+};
+
+$.fn.ismMessagePanel = function() {
+ if (!this.data('panel')) {
+ this.data('panel', new IsmMessagePanel(this));
+ }
+ return this.data('panel');
};
\ No newline at end of file
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js
index 40f5240f..52a403f8 100644
--- a/htdocs/openwebrx.js
+++ b/htdocs/openwebrx.js
@@ -864,6 +864,7 @@ function on_ws_recv(evt) {
$('#openwebrx-panel-packet-message').packetMessagePanel(),
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel(),
$('#openwebrx-panel-adsb-message').adsbMessagePanel(),
+ $('#openwebrx-panel-ism-message').ismMessagePanel(),
$("#openwebrx-panel-js8-message").js8()
];
if (!panels.some(function(panel) {
@@ -1470,6 +1471,7 @@ function secondary_demod_init() {
$('#openwebrx-panel-packet-message').packetMessagePanel();
$('#openwebrx-panel-pocsag-message').pocsagMessagePanel();
$('#openwebrx-panel-adsb-message').adsbMessagePanel();
+ $('#openwebrx-panel-ism-message').ismMessagePanel();
$('#openwebrx-panel-js8-message').js8();
}
diff --git a/owrx/dsp.py b/owrx/dsp.py
index 3156a693..16068d10 100644
--- a/owrx/dsp.py
+++ b/owrx/dsp.py
@@ -620,6 +620,9 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
elif mod == "adsb":
from csdr.chain.dump1090 import Dump1090
return Dump1090()
+ elif mod == "ism":
+ from csdr.chain.rtl433 import Rtl433
+ return Rtl433()
def setSecondaryDemodulator(self, mod):
demodulator = self._getSecondaryDemodulator(mod)
diff --git a/owrx/feature.py b/owrx/feature.py
index 4f5690ac..772fc320 100644
--- a/owrx/feature.py
+++ b/owrx/feature.py
@@ -85,6 +85,7 @@ class FeatureDetector(object):
"js8call": ["js8", "js8py"],
"drm": ["dream"],
"dump1090": ["dump1090"],
+ "ism": ["rtl_433"],
}
def feature_availability(self):
@@ -591,3 +592,13 @@ class FeatureDetector(object):
[Debian alternatives system](https://wiki.debian.org/DebianAlternatives) to achieve this.
"""
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")
diff --git a/owrx/ism/rtl433.py b/owrx/ism/rtl433.py
new file mode 100644
index 00000000..4f83e3bd
--- /dev/null
+++ b/owrx/ism/rtl433.py
@@ -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")
diff --git a/owrx/modes.py b/owrx/modes.py
index 582bf70a..9261aab3 100644
--- a/owrx/modes.py
+++ b/owrx/modes.py
@@ -174,6 +174,14 @@ class Modes(object):
squelch=False,
secondaryFft=False,
),
+ DigitalMode(
+ "ism",
+ "ISM",
+ underlying=["empty"],
+ bandpass=None,
+ requirements=["ism"],
+ squelch=False,
+ )
]
@staticmethod