restore pocsag functionality
This commit is contained in:
@ -2,14 +2,9 @@ from owrx.map import Map, LatLngLocation
|
||||
from owrx.metrics import Metrics, CounterMetric
|
||||
from owrx.bands import Bandplan
|
||||
from datetime import datetime, timezone
|
||||
from csdr.module import Module
|
||||
from pycsdr.modules import Reader
|
||||
from pycsdr.types import Format
|
||||
from threading import Thread
|
||||
from io import BytesIO
|
||||
from csdr.module import PickleModule
|
||||
import re
|
||||
import logging
|
||||
import pickle
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -50,41 +45,8 @@ def getSymbolData(symbol, table):
|
||||
return {"symbol": symbol, "table": table, "index": ord(symbol) - 33, "tableindex": ord(table) - 33}
|
||||
|
||||
|
||||
class Ax25Parser(Module, Thread):
|
||||
def __init__(self):
|
||||
self.doRun = True
|
||||
super().__init__()
|
||||
|
||||
def getInputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def getOutputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def setReader(self, reader: Reader) -> None:
|
||||
super().setReader(reader)
|
||||
self.start()
|
||||
|
||||
def stop(self):
|
||||
self.doRun = False
|
||||
self.reader.stop()
|
||||
|
||||
def run(self):
|
||||
while self.doRun:
|
||||
data = self.reader.read()
|
||||
if data is None:
|
||||
self.doRun = False
|
||||
break
|
||||
io = BytesIO(data.tobytes())
|
||||
try:
|
||||
while True:
|
||||
frame = self.parse(pickle.load(io))
|
||||
if frame is not None:
|
||||
self.writer.write(pickle.dumps(frame))
|
||||
except EOFError:
|
||||
pass
|
||||
|
||||
def parse(self, ax25frame):
|
||||
class Ax25Parser(PickleModule):
|
||||
def process(self, ax25frame):
|
||||
control_pid = ax25frame.find(bytes([0x03, 0xF0]))
|
||||
if control_pid % 7 > 0:
|
||||
logger.warning("aprs packet framing error: control/pid position not aligned with 7-octet callsign data")
|
||||
@ -189,45 +151,15 @@ class AprsLocation(LatLngLocation):
|
||||
return res
|
||||
|
||||
|
||||
class AprsParser(Module, Thread):
|
||||
class AprsParser(PickleModule):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.metrics = {}
|
||||
self.doRun = True
|
||||
self.band = None
|
||||
|
||||
def setDialFrequency(self, freq):
|
||||
self.band = Bandplan.getSharedInstance().findBand(freq)
|
||||
|
||||
def setReader(self, reader: Reader) -> None:
|
||||
super().setReader(reader)
|
||||
self.start()
|
||||
|
||||
def getInputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def getOutputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def run(self):
|
||||
while self.doRun:
|
||||
data = self.reader.read()
|
||||
if data is None:
|
||||
self.doRun = False
|
||||
break
|
||||
io = BytesIO(data.tobytes())
|
||||
try:
|
||||
while True:
|
||||
frame = self.parse(pickle.load(io))
|
||||
if frame is not None:
|
||||
self.writer.write(pickle.dumps(frame))
|
||||
except EOFError:
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
self.doRun = False
|
||||
self.reader.stop()
|
||||
|
||||
def getMetric(self, category):
|
||||
if category not in self.metrics:
|
||||
band = "unknown"
|
||||
@ -250,7 +182,7 @@ class AprsParser(Module, Thread):
|
||||
return False
|
||||
return True
|
||||
|
||||
def parse(self, data):
|
||||
def process(self, data):
|
||||
try:
|
||||
# TODO how can we tell if this is an APRS frame at all?
|
||||
aprsData = self.parseAprsData(data)
|
||||
|
@ -1,9 +1,6 @@
|
||||
from pycsdr.modules import Reader
|
||||
from pycsdr.types import Format
|
||||
from csdr.module import Module
|
||||
from threading import Thread
|
||||
import socket
|
||||
import time
|
||||
from csdr.module import ThreadModule
|
||||
import pickle
|
||||
|
||||
import logging
|
||||
@ -16,11 +13,10 @@ TFEND = 0xDC
|
||||
TFESC = 0xDD
|
||||
|
||||
|
||||
class KissDeframer(Module, Thread):
|
||||
class KissDeframer(ThreadModule):
|
||||
def __init__(self):
|
||||
self.escaped = False
|
||||
self.buf = bytearray()
|
||||
self.doRun = True
|
||||
super().__init__()
|
||||
|
||||
def getInputFormat(self) -> Format:
|
||||
@ -29,10 +25,6 @@ class KissDeframer(Module, Thread):
|
||||
def getOutputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def setReader(self, reader: Reader) -> None:
|
||||
super().setReader(reader)
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
while self.doRun:
|
||||
data = self.reader.read()
|
||||
@ -42,10 +34,6 @@ class KissDeframer(Module, Thread):
|
||||
for frame in self.parse(data):
|
||||
self.writer.write(pickle.dumps(frame))
|
||||
|
||||
def stop(self):
|
||||
self.doRun = False
|
||||
self.reader.stop()
|
||||
|
||||
def parse(self, input):
|
||||
for b in input:
|
||||
if b == FESC:
|
||||
|
@ -1,10 +1,9 @@
|
||||
from owrx.modes import Modes, AudioChopperMode
|
||||
from itertools import groupby
|
||||
import threading
|
||||
from owrx.audio import ProfileSourceSubscriber
|
||||
from owrx.audio.wav import AudioWriter
|
||||
from owrx.audio.queue import QueueJob
|
||||
from csdr.module import Module
|
||||
from csdr.module import ThreadModule
|
||||
from pycsdr.types import Format
|
||||
import pickle
|
||||
|
||||
@ -14,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class AudioChopper(threading.Thread, Module, ProfileSourceSubscriber):
|
||||
class AudioChopper(ThreadModule, ProfileSourceSubscriber):
|
||||
# TODO parser typing
|
||||
def __init__(self, mode_str: str, parser):
|
||||
self.parser = parser
|
||||
@ -26,7 +25,6 @@ class AudioChopper(threading.Thread, Module, ProfileSourceSubscriber):
|
||||
raise ValueError("Mode {} is not an audio chopper mode".format(mode_str))
|
||||
self.profile_source = mode.get_profile_source()
|
||||
super().__init__()
|
||||
Module.__init__(self)
|
||||
|
||||
def getInputFormat(self) -> Format:
|
||||
return Format.SHORT
|
||||
@ -49,14 +47,6 @@ class AudioChopper(threading.Thread, Module, ProfileSourceSubscriber):
|
||||
w.start()
|
||||
self.writers = writers
|
||||
|
||||
def setReader(self, reader):
|
||||
super().setReader(reader)
|
||||
self.start()
|
||||
|
||||
def stop(self):
|
||||
self.reader.stop()
|
||||
super().stop()
|
||||
|
||||
def run(self) -> None:
|
||||
logger.debug("Audio chopper starting up")
|
||||
self.setup_writers()
|
||||
|
@ -434,9 +434,6 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
|
||||
def write_sdr_error(self, message):
|
||||
self.send({"type": "sdr_error", "value": message})
|
||||
|
||||
def write_pocsag_data(self, data):
|
||||
self.send({"type": "pocsag_data", "value": data})
|
||||
|
||||
def write_backoff_message(self, reason):
|
||||
self.send({"type": "backoff", "reason": reason})
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
from owrx.meta import MetaParser
|
||||
from owrx.wsjt import WsjtParser
|
||||
from owrx.js8 import Js8Parser
|
||||
from owrx.aprs import AprsParser
|
||||
from owrx.pocsag import PocsagParser
|
||||
from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass
|
||||
from owrx.property import PropertyStack, PropertyLayer, PropertyValidator
|
||||
from owrx.property.validators import OrValidator, RegexValidator, BoolValidator
|
||||
@ -15,7 +13,7 @@ from csdr.chain.clientaudio import ClientAudioChain
|
||||
from csdr.chain.analog import NFm, WFm, Am, Ssb
|
||||
from csdr.chain.digiham import DigihamChain, Dmr, Dstar, Nxdn, Ysf
|
||||
from csdr.chain.fft import FftChain
|
||||
from csdr.chain.digimodes import AudioChopperDemodulator, PacketDemodulator
|
||||
from csdr.chain.digimodes import AudioChopperDemodulator, PacketDemodulator, PocsagDemodulator
|
||||
from pycsdr.modules import Buffer, Writer
|
||||
from pycsdr.types import Format
|
||||
from typing import Union
|
||||
@ -283,7 +281,6 @@ class DspManager(Output, SdrSourceEventClient):
|
||||
self.sdrSource = sdrSource
|
||||
self.parsers = {
|
||||
"meta": MetaParser(self.handler),
|
||||
"pocsag_demod": PocsagParser(self.handler),
|
||||
"js8_demod": Js8Parser(self.handler),
|
||||
}
|
||||
|
||||
@ -494,6 +491,8 @@ class DspManager(Output, SdrSourceEventClient):
|
||||
return AudioChopperDemodulator(mod, WsjtParser())
|
||||
elif mod == "packet":
|
||||
return PacketDemodulator()
|
||||
elif mod == "pocsag":
|
||||
return PocsagDemodulator()
|
||||
return None
|
||||
|
||||
def setSecondaryDemodulator(self, mod):
|
||||
|
@ -1,17 +1,38 @@
|
||||
from owrx.parser import Parser
|
||||
from csdr.module import ThreadModule
|
||||
from pycsdr.types import Format
|
||||
import pickle
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PocsagParser(Parser):
|
||||
class PocsagParser(ThreadModule):
|
||||
def getInputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def getOutputFormat(self) -> Format:
|
||||
return Format.CHAR
|
||||
|
||||
def run(self):
|
||||
while self.doRun:
|
||||
data = self.reader.read()
|
||||
if data is None:
|
||||
self.doRun = False
|
||||
else:
|
||||
for frame in self.parse(data.tobytes()):
|
||||
self.writer.write(pickle.dumps(frame))
|
||||
|
||||
def parse(self, raw):
|
||||
try:
|
||||
fields = raw.decode("ascii", "replace").rstrip("\n").split(";")
|
||||
meta = {v[0]: "".join(v[1:]) for v in map(lambda x: x.split(":"), fields) if v[0] != ""}
|
||||
if "address" in meta:
|
||||
meta["address"] = int(meta["address"])
|
||||
self.handler.write_pocsag_data(meta)
|
||||
except Exception:
|
||||
logger.exception("Exception while parsing Pocsag message")
|
||||
for line in raw.split(b"\n"):
|
||||
if not len(line):
|
||||
continue
|
||||
try:
|
||||
fields = line.decode("ascii", "replace").split(";")
|
||||
meta = {v[0]: "".join(v[1:]) for v in map(lambda x: x.split(":"), fields) if v[0] != ""}
|
||||
if "address" in meta:
|
||||
meta["address"] = int(meta["address"])
|
||||
meta["mode"] = "Pocsag"
|
||||
yield meta
|
||||
except Exception:
|
||||
logger.exception("Exception while parsing Pocsag message")
|
||||
|
Reference in New Issue
Block a user