aprsd/aprsd/clients/kiss.py

120 lines
3.5 KiB
Python

import logging
import aprslib
from ax253 import Frame
import kiss
from aprsd.packets import core
from aprsd.utils import trace
LOG = logging.getLogger("APRSD")
class KISS3Client:
def __init__(self, config):
self.config = config
self.setup()
def setup(self):
# we can be TCP kiss or Serial kiss
if "serial" in self.config["kiss"] and self.config["kiss"]["serial"].get(
"enabled",
False,
):
LOG.debug(
"KISS({}) Serial connection to {}".format(
kiss.__version__,
self.config["kiss"]["serial"]["device"],
),
)
self.kiss = kiss.SerialKISS(
port=self.config["kiss"]["serial"]["device"],
speed=self.config["kiss"]["serial"].get("baudrate", 9600),
strip_df_start=True,
)
elif "tcp" in self.config["kiss"] and self.config["kiss"]["tcp"].get(
"enabled",
False,
):
LOG.debug(
"KISS({}) TCP Connection to {}:{}".format(
kiss.__version__,
self.config["kiss"]["tcp"]["host"],
self.config["kiss"]["tcp"]["port"],
),
)
self.kiss = kiss.TCPKISS(
host=self.config["kiss"]["tcp"]["host"],
port=int(self.config["kiss"]["tcp"]["port"]),
strip_df_start=True,
)
LOG.debug("Starting KISS interface connection")
self.kiss.start()
@trace.trace
def stop(self):
try:
self.kiss.stop()
self.kiss.loop.call_soon_threadsafe(
self.kiss.protocol.transport.close,
)
except Exception as ex:
LOG.exception(ex)
def set_filter(self, filter):
# This does nothing right now.
pass
def parse_frame(self, frame_bytes):
frame = Frame.from_bytes(frame_bytes)
# Now parse it with aprslib
packet = aprslib.parse(str(frame))
kwargs = {
"frame": str(frame),
"packet": packet,
}
self._parse_callback(**kwargs)
def consumer(self, callback, blocking=False, immortal=False, raw=False):
LOG.debug("Start blocking KISS consumer")
self._parse_callback = callback
self.kiss.read(callback=self.parse_frame, min_frames=None)
LOG.debug("END blocking KISS consumer")
def send(self, packet):
"""Send an APRS Message object."""
# payload = (':%-9s:%s' % (
# msg.tocall,
# payload
# )).encode('US-ASCII'),
# payload = str(msg).encode('US-ASCII')
payload = None
path = ["WIDE1-1", "WIDE2-1"]
if isinstance(packet, core.AckPacket):
msg_payload = f"ack{packet.msgNo}"
elif isinstance(packet, core.Packet):
payload = packet.raw.encode("US-ASCII")
path = ["WIDE2-1"]
else:
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
if not payload:
payload = (
":{:<9}:{}".format(
packet.to_call,
msg_payload,
)
).encode("US-ASCII")
LOG.debug(f"Send '{payload}' TO KISS")
frame = Frame.ui(
destination=packet.to_call,
source=packet.from_call,
path=path,
info=payload,
)
self.kiss.write(frame)