1
0
mirror of https://github.com/craigerl/aprsd.git synced 2024-11-18 06:11:49 -05:00

Use new aprsd.callsign as the main callsign

This patch changes how aprsd identifies itself when connected to
any client, which is not relying on the login for each client.
There are 3 supported clients currently
aprsis,
tcpkiss
serialkiss.

Each client has their own potential login/callsign to connect
to the remote.  This patch tells aprsd to use the new config option
aprsd.callsign as a means to identify itself.  It will accept
packets as <aprsd.callsign> and reply as <aprsd.callsign> regardless
of which client object is being used to connect to the remote.

Note: this breaks backwards compatibility.  This patch now requires
the new config option
aprsd:
  callsign: <callsign>
This commit is contained in:
Hemna 2022-07-28 16:24:25 -04:00
parent 5f28788180
commit ad79ed1261
6 changed files with 89 additions and 39 deletions

View File

@ -156,8 +156,8 @@ class KISSClient(Client):
# Ensure that the config vars are correctly set # Ensure that the config vars are correctly set
if KISSClient.is_enabled(config): if KISSClient.is_enabled(config):
config.check_option( config.check_option(
"kiss.callsign", "aprsd.callsign",
default_fail=aprsd_config.DEFAULT_CONFIG_DICT["kiss"]["callsign"], default_fail=aprsd_config.DEFAULT_CONFIG_DICT["aprsd"]["callsign"],
) )
transport = KISSClient.transport(config) transport = KISSClient.transport(config)
if transport == TRANSPORT_SERIALKISS: if transport == TRANSPORT_SERIALKISS:

View File

@ -32,6 +32,7 @@ class Aioax25Client:
device=self.config["kiss"]["serial"]["device"], device=self.config["kiss"]["serial"]["device"],
baudrate=self.config["kiss"]["serial"].get("baudrate", 9600), baudrate=self.config["kiss"]["serial"].get("baudrate", 9600),
loop=self.loop, loop=self.loop,
log=LOG,
) )
elif "tcp" in self.config["kiss"] and self.config["kiss"]["tcp"].get( elif "tcp" in self.config["kiss"] and self.config["kiss"]["tcp"].get(
"enabled", "enabled",
@ -50,30 +51,32 @@ class Aioax25Client:
log=LOG, log=LOG,
) )
self.kissdev.open()
self.kissport0 = self.kissdev[0]
LOG.debug("Creating AX25Interface") LOG.debug("Creating AX25Interface")
self.ax25int = interface.AX25Interface(kissport=self.kissport0, loop=self.loop) self.ax25int = interface.AX25Interface(
kissport=self.kissdev[0],
loop=self.loop,
log=LOG,
)
LOG.debug("Creating APRSInterface") LOG.debug("Creating APRSInterface")
self.aprsint = APRSInterface( self.aprsint = APRSInterface(
ax25int=self.ax25int, ax25int=self.ax25int,
mycall=self.config["kiss"]["callsign"], mycall=self.config["aprsd"]["callsign"],
log=LOG, log=LOG,
) )
self.kissdev.open()
def stop(self): def stop(self):
LOG.debug(self.kissdev) LOG.debug(self.kissdev)
self.kissdev._close()
self.loop.stop() self.loop.stop()
self.kissdev.close()
def set_filter(self, filter): def set_filter(self, filter):
# This does nothing right now. # This does nothing right now.
pass pass
def consumer(self, callback, blocking=True, immortal=False, raw=False): def consumer(self, callback, blocking=False, immortal=False, raw=False):
callsign = self.config["kiss"]["callsign"] callsign = self.config["aprsd"]["callsign"]
call = callsign.split("-") call = callsign.split("-")
if len(call) > 1: if len(call) > 1:
callsign = call[0] callsign = call[0]
@ -81,10 +84,28 @@ class Aioax25Client:
else: else:
ssid = 0 ssid = 0
self.aprsint.bind(callback=callback, callsign=callsign, ssid=ssid, regex=False) self.aprsint.bind(callback=callback, callsign=callsign, ssid=ssid, regex=False)
# async def set_after(fut, delay, value):
# # Sleep for *delay* seconds.
# await asyncio.sleep(delay)
#
# # Set *value* as a result of *fut* Future.
# fut.set_result(value)
#
# async def my_wait(fut):
# await fut
#
# fut = self.loop.create_future()
# self.loop.create_task(
# set_after(fut, 5, "nothing")
# )
LOG.debug("RUN FOREVER")
self.loop.run_forever() self.loop.run_forever()
# my_wait(fut)
def send(self, msg): def send(self, msg):
"""Send an APRS Message object.""" """Send an APRS Message object."""
LOG.debug(f"Send {msg} TO KISS")
payload = f"{msg._filter_for_send()}" payload = f"{msg._filter_for_send()}"
self.aprsint.send_message( self.aprsint.send_message(
addressee=msg.tocall, addressee=msg.tocall,

View File

@ -93,18 +93,21 @@ class SentMessages(objectstore.ObjectStoreMixin):
@wrapt.synchronized(lock) @wrapt.synchronized(lock)
def set_status(self, id, status): def set_status(self, id, status):
if id in self.data:
self.data[id]["last_update"] = str(datetime.datetime.now()) self.data[id]["last_update"] = str(datetime.datetime.now())
self.data[id]["status"] = status self.data[id]["status"] = status
@wrapt.synchronized(lock) @wrapt.synchronized(lock)
def ack(self, id): def ack(self, id):
"""The message got an ack!""" """The message got an ack!"""
if id in self.data:
self.data[id]["last_update"] = str(datetime.datetime.now()) self.data[id]["last_update"] = str(datetime.datetime.now())
self.data[id]["ack"] = True self.data[id]["ack"] = True
@wrapt.synchronized(lock) @wrapt.synchronized(lock)
def reply(self, id, packet): def reply(self, id, packet):
"""We got a packet back from the sent message.""" """We got a packet back from the sent message."""
if id in self.data:
self.data[id]["reply"] = packet self.data[id]["reply"] = packet
@ -126,7 +129,6 @@ class WebChatRXThread(rx.APRSDRXThread):
self.connected = connected self.connected = connected
def loop(self): def loop(self):
# setup the consumer of messages and block until a messages # setup the consumer of messages and block until a messages
msg = None msg = None
try: try:
@ -227,15 +229,16 @@ class WebChatTXThread(aprsd_thread.APRSDThread):
self.got_ack = True self.got_ack = True
def process_packet(self, packet): def process_packet(self, packet):
LOG.info(f"process PACKET {packet}")
tocall = packet.get("addresse", None) tocall = packet.get("addresse", None)
fromcall = packet["from"] fromcall = packet["from"]
msg = packet.get("message_text", None) msg = packet.get("message_text", None)
msg_id = packet.get("msgNo", "0") msg_id = packet.get("msgNo", "0")
msg_response = packet.get("response", None) msg_response = packet.get("response", None)
if tocall == self.config["aprs"]["login"] and msg_response == "ack": if tocall == self.config["aprsd"]["callsign"] and msg_response == "ack":
self.process_ack_packet(packet) self.process_ack_packet(packet)
elif tocall == self.config["aprs"]["login"]: elif tocall == self.config["aprsd"]["callsign"]:
messaging.log_message( messaging.log_message(
"Received Message", "Received Message",
packet["raw"], packet["raw"],
@ -246,11 +249,11 @@ class WebChatTXThread(aprsd_thread.APRSDThread):
# let any threads do their thing, then ack # let any threads do their thing, then ack
# send an ack last # send an ack last
ack = messaging.AckMessage( ack = messaging.AckMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
msg_id=msg_id, msg_id=msg_id,
) )
self.msg_queues["tx"].put(ack) ack.send()
packets.PacketList().add(packet) packets.PacketList().add(packet)
stats.APRSDStats().msgs_rx_inc() stats.APRSDStats().msgs_rx_inc()
@ -299,7 +302,7 @@ class WebChatFlask(flask_classful.FlaskView):
) )
else: else:
# We might be connected to a KISS socket? # We might be connected to a KISS socket?
if client.KISSClient.kiss_enabled(self.config): if client.KISSClient.is_enabled(self.config):
transport = client.KISSClient.transport(self.config) transport = client.KISSClient.transport(self.config)
if transport == client.TRANSPORT_TCPKISS: if transport == client.TRANSPORT_TCPKISS:
aprs_connection = ( aprs_connection = (
@ -324,7 +327,7 @@ class WebChatFlask(flask_classful.FlaskView):
"index.html", "index.html",
initial_stats=stats, initial_stats=stats,
aprs_connection=aprs_connection, aprs_connection=aprs_connection,
callsign=self.config["aprs"]["login"], callsign=self.config["aprsd"]["callsign"],
version=aprsd.__version__, version=aprsd.__version__,
) )
@ -335,7 +338,6 @@ class WebChatFlask(flask_classful.FlaskView):
info = msgs.get_all() info = msgs.get_all()
return json.dumps(info) return json.dumps(info)
@trace.trace
def _stats(self): def _stats(self):
stats_obj = stats.APRSDStats() stats_obj = stats.APRSDStats()
now = datetime.datetime.now() now = datetime.datetime.now()
@ -406,8 +408,8 @@ class SendMessageNamespace(Namespace):
"sent", SentMessages().get(self.msg.id), "sent", SentMessages().get(self.msg.id),
namespace="/sendmsg", namespace="/sendmsg",
) )
msg.send()
self._msg_queues["tx"].put(msg) # self._msg_queues["tx"].put(msg)
def handle_message(self, data): def handle_message(self, data):
LOG.debug(f"WS Data {data}") LOG.debug(f"WS Data {data}")

View File

@ -57,13 +57,13 @@ DEFAULT_CONFIG_DICT = {
"ham": {"callsign": "NOCALL"}, "ham": {"callsign": "NOCALL"},
"aprs": { "aprs": {
"enabled": True, "enabled": True,
# Only used as the login for aprsis.
"login": "CALLSIGN", "login": "CALLSIGN",
"password": "00000", "password": "00000",
"host": "rotate.aprs2.net", "host": "rotate.aprs2.net",
"port": 14580, "port": 14580,
}, },
"kiss": { "kiss": {
"callsign": "NOCALL",
"tcp": { "tcp": {
"enabled": False, "enabled": False,
"host": "direwolf.ip.address", "host": "direwolf.ip.address",
@ -76,11 +76,14 @@ DEFAULT_CONFIG_DICT = {
}, },
}, },
"aprsd": { "aprsd": {
# Callsign to use for all packets to/from aprsd instance
# regardless of the client (aprsis vs kiss)
"callsign": "NOCALL",
"logfile": "/tmp/aprsd.log", "logfile": "/tmp/aprsd.log",
"logformat": DEFAULT_LOG_FORMAT, "logformat": DEFAULT_LOG_FORMAT,
"dateformat": DEFAULT_DATE_FORMAT, "dateformat": DEFAULT_DATE_FORMAT,
"save_location": DEFAULT_CONFIG_DIR, "save_location": DEFAULT_CONFIG_DIR,
"rich_logging": False, "rich_logging": True,
"trace": False, "trace": False,
"enabled_plugins": CORE_MESSAGE_PLUGINS, "enabled_plugins": CORE_MESSAGE_PLUGINS,
"units": "imperial", "units": "imperial",
@ -177,16 +180,35 @@ class Config(collections.UserDict):
if not self.exists(path): if not self.exists(path):
if type(path) is list: if type(path) is list:
path = ".".join(path) path = ".".join(path)
raise exception.MissingConfigOption(path) raise exception.MissingConfigOptionException(path)
val = self.get(path) val = self.get(path)
if val == default_fail: if val == default_fail:
# We have to fail and bail if the user hasn't edited # We have to fail and bail if the user hasn't edited
# this config option. # this config option.
raise exception.ConfigOptionBogusDefaultException(path, default_fail) raise exception.ConfigOptionBogusDefaultException(
path, default_fail,
)
def add_config_comments(raw_yaml): def add_config_comments(raw_yaml):
end_idx = utils.end_substr(raw_yaml, "ham:")
if end_idx != -1:
# lets insert a comment
raw_yaml = utils.insert_str(
raw_yaml,
"\n # Callsign that owns this instance of APRSD.",
end_idx,
)
end_idx = utils.end_substr(raw_yaml, "aprsd:")
if end_idx != -1:
# lets insert a comment
raw_yaml = utils.insert_str(
raw_yaml,
"\n # Callsign to use for all APRSD Packets as the to/from."
"\n # regardless of client type (aprsis vs tcpkiss vs serial)",
end_idx,
)
end_idx = utils.end_substr(raw_yaml, "aprs:") end_idx = utils.end_substr(raw_yaml, "aprs:")
if end_idx != -1: if end_idx != -1:
# lets insert a comment # lets insert a comment
@ -326,6 +348,11 @@ def parse_config(config_file):
config, config,
["aprsd"], ["aprsd"],
) )
check_option(
config,
"aprsd.callsign",
default_fail=DEFAULT_CONFIG_DICT["aprsd"]["callsign"],
)
# Ensure they change the admin password # Ensure they change the admin password
if config.get("aprsd.web.enabled") is True: if config.get("aprsd.web.enabled") is True:

View File

@ -41,7 +41,7 @@ class KeepAliveThread(APRSDThread):
stats_obj.set_memory_peak(peak) stats_obj.set_memory_peak(peak)
try: try:
login = self.config["aprs"]["login"] login = self.config["aprsd"]["callsign"]
except KeyError: except KeyError:
login = self.config["ham"]["callsign"] login = self.config["ham"]["callsign"]

View File

@ -101,7 +101,7 @@ class APRSDProcessPacketThread(APRSDThread):
# We don't put ack packets destined for us through the # We don't put ack packets destined for us through the
# plugins. # plugins.
if tocall == self.config["aprs"]["login"] and msg_response == "ack": if tocall == self.config["aprsd"]["callsign"] and msg_response == "ack":
self.process_ack_packet(packet) self.process_ack_packet(packet)
else: else:
# It's not an ACK for us, so lets run it through # It's not an ACK for us, so lets run it through
@ -115,12 +115,12 @@ class APRSDProcessPacketThread(APRSDThread):
) )
# Only ack messages that were sent directly to us # Only ack messages that were sent directly to us
if tocall == self.config["aprs"]["login"]: if tocall == self.config["aprsd"]["callsign"]:
stats.APRSDStats().msgs_rx_inc() stats.APRSDStats().msgs_rx_inc()
# let any threads do their thing, then ack # let any threads do their thing, then ack
# send an ack last # send an ack last
ack = messaging.AckMessage( ack = messaging.AckMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
msg_id=msg_id, msg_id=msg_id,
) )
@ -142,7 +142,7 @@ class APRSDProcessPacketThread(APRSDThread):
subreply.send() subreply.send()
else: else:
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
subreply, subreply,
) )
@ -162,7 +162,7 @@ class APRSDProcessPacketThread(APRSDThread):
LOG.debug(f"Sending '{reply}'") LOG.debug(f"Sending '{reply}'")
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
reply, reply,
) )
@ -170,10 +170,10 @@ class APRSDProcessPacketThread(APRSDThread):
# If the message was for us and we didn't have a # If the message was for us and we didn't have a
# response, then we send a usage statement. # response, then we send a usage statement.
if tocall == self.config["aprs"]["login"] and not replied: if tocall == self.config["aprsd"]["callsign"] and not replied:
LOG.warning("Sending help!") LOG.warning("Sending help!")
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
"Unknown command! Send 'help' message for help", "Unknown command! Send 'help' message for help",
) )
@ -182,10 +182,10 @@ class APRSDProcessPacketThread(APRSDThread):
LOG.error("Plugin failed!!!") LOG.error("Plugin failed!!!")
LOG.exception(ex) LOG.exception(ex)
# Do we need to send a reply? # Do we need to send a reply?
if tocall == self.config["aprs"]["login"]: if tocall == self.config["aprsd"]["callsign"]:
reply = "A Plugin failed! try again?" reply = "A Plugin failed! try again?"
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprsd"]["callsign"],
fromcall, fromcall,
reply, reply,
) )