mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-25 09:28:38 -05:00
Got TX/RX working with aioax25+direwolf over TCP
This patch gets APRSD fully working with the TCPKISS socket to direwolf.
This commit is contained in:
parent
54c9a6b55a
commit
f4dee4b202
@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from aioax25 import frame as axframe
|
||||
from aioax25 import interface
|
||||
from aioax25 import kiss as kiss
|
||||
from aioax25.aprs import APRSInterface
|
||||
@ -38,7 +37,7 @@ class KISSClient:
|
||||
return True
|
||||
|
||||
if "tcp" in config["kiss"]:
|
||||
if config["kiss"]["serial"].get("enabled", False):
|
||||
if config["kiss"]["tcp"].get("enabled", False):
|
||||
return True
|
||||
|
||||
@property
|
||||
@ -88,14 +87,15 @@ class Aioax25Client:
|
||||
):
|
||||
LOG.debug(
|
||||
"Setting up KISSTCP Connection to {}:{}".format(
|
||||
self.config["kiss"]["host"],
|
||||
self.config["kiss"]["port"],
|
||||
self.config["kiss"]["tcp"]["host"],
|
||||
self.config["kiss"]["tcp"]["port"],
|
||||
),
|
||||
)
|
||||
self.kissdev = kiss.TCPKISSDevice(
|
||||
self.config["kiss"]["host"],
|
||||
self.config["kiss"]["port"],
|
||||
self.config["kiss"]["tcp"]["host"],
|
||||
self.config["kiss"]["tcp"]["port"],
|
||||
loop=self.loop,
|
||||
log=LOG,
|
||||
)
|
||||
|
||||
self.kissdev.open()
|
||||
@ -107,7 +107,7 @@ class Aioax25Client:
|
||||
LOG.debug("Creating APRSInterface")
|
||||
self.aprsint = APRSInterface(
|
||||
ax25int=self.ax25int,
|
||||
mycall=self.config["ham"]["callsign"],
|
||||
mycall=self.config["kiss"]["callsign"],
|
||||
log=LOG,
|
||||
)
|
||||
|
||||
@ -119,20 +119,17 @@ class Aioax25Client:
|
||||
def consumer(self, callback, callsign=None):
|
||||
if not callsign:
|
||||
callsign = self.config["ham"]["callsign"]
|
||||
self.aprsint.bind(callback=callback, callsign=callsign, regex=True)
|
||||
self.aprsint.bind(callback=callback, callsign="WB4BOR", ssid=12, regex=False)
|
||||
|
||||
def send(self, msg):
|
||||
"""Send an APRS Message object."""
|
||||
payload = msg._filter_for_send()
|
||||
frame = axframe.AX25UnnumberedInformationFrame(
|
||||
msg.tocall,
|
||||
msg.fromcall.encode("UTF-8"),
|
||||
pid=0xF0,
|
||||
repeaters=b"WIDE2-1",
|
||||
payload=payload,
|
||||
payload = f"{msg._filter_for_send()}"
|
||||
self.aprsint.send_message(
|
||||
addressee=msg.tocall,
|
||||
message=payload,
|
||||
path=["WIDE1-1", "WIDE2-1"],
|
||||
oneshot=True,
|
||||
)
|
||||
LOG.debug(frame)
|
||||
self.ax25int.transmit(frame)
|
||||
|
||||
|
||||
def get_client():
|
||||
|
@ -469,6 +469,12 @@ def server(
|
||||
cl.client
|
||||
except LoginError:
|
||||
sys.exit(-1)
|
||||
|
||||
rx_thread = threads.APRSDRXThread(
|
||||
msg_queues=threads.msg_queues,
|
||||
config=config,
|
||||
)
|
||||
rx_thread.start()
|
||||
else:
|
||||
LOG.info(
|
||||
"APRS network connection Not Enabled in config. This is"
|
||||
@ -486,13 +492,6 @@ def server(
|
||||
|
||||
packets.PacketList(config=config)
|
||||
|
||||
rx_thread = threads.APRSDRXThread(
|
||||
msg_queues=threads.msg_queues,
|
||||
config=config,
|
||||
)
|
||||
|
||||
rx_thread.start()
|
||||
|
||||
if "watch_list" in config["aprsd"] and config["aprsd"]["watch_list"].get(
|
||||
"enabled",
|
||||
True,
|
||||
|
@ -489,6 +489,9 @@ class AckMessage(Message):
|
||||
self.id,
|
||||
)
|
||||
|
||||
def _filter_for_send(self):
|
||||
return f"ack{self.id}"
|
||||
|
||||
def send(self):
|
||||
LOG.debug(f"Send ACK({self.tocall}:{self.id}) to radio.")
|
||||
thread = SendAckThread(self)
|
||||
|
138
aprsd/threads.py
138
aprsd/threads.py
@ -8,9 +8,7 @@ import tracemalloc
|
||||
|
||||
import aprslib
|
||||
|
||||
from aprsd import (
|
||||
client, kissclient, messaging, packets, plugin, stats, trace, utils,
|
||||
)
|
||||
from aprsd import client, kissclient, messaging, packets, plugin, stats, utils
|
||||
|
||||
|
||||
LOG = logging.getLogger("APRSD")
|
||||
@ -182,9 +180,10 @@ class APRSDRXThread(APRSDThread):
|
||||
|
||||
class APRSDProcessPacketThread(APRSDThread):
|
||||
|
||||
def __init__(self, packet, config):
|
||||
def __init__(self, packet, config, transport="aprsis"):
|
||||
self.packet = packet
|
||||
self.config = config
|
||||
self.transport = transport
|
||||
name = self.packet["raw"][:10]
|
||||
super().__init__(f"RX_PACKET-{name}")
|
||||
|
||||
@ -239,6 +238,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
msg_id=msg_id,
|
||||
transport=self.transport,
|
||||
)
|
||||
ack.send()
|
||||
|
||||
@ -257,6 +257,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
subreply,
|
||||
transport=self.transport,
|
||||
)
|
||||
msg.send()
|
||||
|
||||
@ -273,6 +274,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=self.transport,
|
||||
)
|
||||
msg.send()
|
||||
|
||||
@ -285,6 +287,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=self.transport,
|
||||
)
|
||||
msg.send()
|
||||
except Exception as ex:
|
||||
@ -296,6 +299,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=self.transport,
|
||||
)
|
||||
msg.send()
|
||||
|
||||
@ -349,7 +353,7 @@ class KISSRXThread(APRSDThread):
|
||||
# and the aprslib developer didn't want to allow a PR to add
|
||||
# kwargs. :(
|
||||
# https://github.com/rossengeorgiev/aprs-python/pull/56
|
||||
kiss_client.consumer(self.process_packet, callsign="APN382")
|
||||
kiss_client.consumer(self.process_packet, callsign=self.config["kiss"]["callsign"])
|
||||
kiss_client.loop.run_forever()
|
||||
|
||||
except aprslib.exceptions.ConnectionDrop:
|
||||
@ -361,131 +365,21 @@ class KISSRXThread(APRSDThread):
|
||||
client.Client().reset()
|
||||
# Continue to loop
|
||||
|
||||
@trace.trace
|
||||
def process_packet(self, interface, frame, match):
|
||||
def process_packet(self, interface, frame):
|
||||
"""Process a packet recieved from aprs-is server."""
|
||||
|
||||
LOG.debug(f"Got an APRS Frame '{frame}'")
|
||||
|
||||
# try and nuke the * from the fromcall sign.
|
||||
frame.header._source._ch = False
|
||||
payload = str(frame.payload.decode())
|
||||
msg = f"{str(frame.header)}:{payload}"
|
||||
LOG.debug(f"Decoding {msg}")
|
||||
|
||||
packet = aprslib.parse(msg)
|
||||
LOG.debug(packet)
|
||||
|
||||
try:
|
||||
stats.APRSDStats().msgs_rx_inc()
|
||||
|
||||
msg = packet.get("message_text", None)
|
||||
msg_format = packet.get("format", None)
|
||||
msg_response = packet.get("response", None)
|
||||
if msg_format == "message" and msg:
|
||||
# we want to send the message through the
|
||||
# plugins
|
||||
self.process_message_packet(packet)
|
||||
return
|
||||
elif msg_response == "ack":
|
||||
self.process_ack_packet(packet)
|
||||
return
|
||||
|
||||
if msg_format == "mic-e":
|
||||
# process a mic-e packet
|
||||
self.process_mic_e_packet(packet)
|
||||
return
|
||||
|
||||
except (aprslib.ParseError, aprslib.UnknownFormat) as exp:
|
||||
LOG.exception("Failed to parse packet from aprs-is", exp)
|
||||
|
||||
@trace.trace
|
||||
def process_message_packet(self, packet):
|
||||
LOG.debug("Message packet rx")
|
||||
fromcall = packet["from"]
|
||||
message = packet.get("message_text", None)
|
||||
msg_id = packet.get("msgNo", "0")
|
||||
messaging.log_message(
|
||||
"Received Message",
|
||||
packet["raw"],
|
||||
message,
|
||||
fromcall=fromcall,
|
||||
msg_num=msg_id,
|
||||
)
|
||||
found_command = False
|
||||
# Get singleton of the PM
|
||||
pm = plugin.PluginManager()
|
||||
try:
|
||||
results = pm.run(fromcall=fromcall, message=message, ack=msg_id)
|
||||
for reply in results:
|
||||
found_command = True
|
||||
# A plugin can return a null message flag which signals
|
||||
# us that they processed the message correctly, but have
|
||||
# nothing to reply with, so we avoid replying with a usage string
|
||||
if reply is not messaging.NULL_MESSAGE:
|
||||
LOG.debug(f"Sending '{reply}'")
|
||||
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=messaging.MESSAGE_TRANSPORT_TCPKISS,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
else:
|
||||
LOG.debug("Got NULL MESSAGE from plugin")
|
||||
|
||||
if not found_command:
|
||||
plugins = pm.get_plugins()
|
||||
names = [x.command_name for x in plugins]
|
||||
names.sort()
|
||||
|
||||
# reply = "Usage: {}".format(", ".join(names))
|
||||
reply = "Usage: weather, locate [call], time, fortune, ping"
|
||||
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=messaging.MESSAGE_TRANSPORT_TCPKISS,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
except Exception as ex:
|
||||
LOG.exception("Plugin failed!!!", ex)
|
||||
reply = "A Plugin failed! try again?"
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
transport=messaging.MESSAGE_TRANSPORT_TCPKISS,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
|
||||
# let any threads do their thing, then ack
|
||||
# send an ack last
|
||||
ack = messaging.AckMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
msg_id=msg_id,
|
||||
thread = APRSDProcessPacketThread(
|
||||
packet=packet, config=self.config,
|
||||
transport=messaging.MESSAGE_TRANSPORT_TCPKISS,
|
||||
)
|
||||
self.msg_queues["tx"].put(ack)
|
||||
LOG.debug("Packet processing complete")
|
||||
|
||||
def process_ack_packet(self, packet):
|
||||
ack_num = packet.get("msgNo")
|
||||
LOG.info(f"Got ack for message {ack_num}")
|
||||
messaging.log_message(
|
||||
"ACK",
|
||||
packet["raw"],
|
||||
None,
|
||||
ack=ack_num,
|
||||
fromcall=packet["from"],
|
||||
)
|
||||
tracker = messaging.MsgTrack()
|
||||
tracker.remove(ack_num)
|
||||
stats.APRSDStats().ack_rx_inc()
|
||||
return
|
||||
|
||||
def process_mic_e_packet(self, packet):
|
||||
LOG.info("Mic-E Packet detected. Currenlty unsupported.")
|
||||
messaging.log_packet(packet)
|
||||
stats.APRSDStats().msgs_mice_inc()
|
||||
thread.start()
|
||||
return
|
||||
|
@ -1,4 +1,4 @@
|
||||
aioax25
|
||||
aioax25>=0.0.10
|
||||
aprslib
|
||||
click
|
||||
click-completion
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# pip-compile requirements.in
|
||||
#
|
||||
aioax25==0.0.9
|
||||
aioax25==0.0.10
|
||||
# via -r requirements.in
|
||||
aprslib==0.6.47
|
||||
# via -r requirements.in
|
||||
|
Loading…
Reference in New Issue
Block a user