Add ability to change path on every TX packet

This patch adds the ability to webchat to set the path
on every outbound packet for the KISS clients as well as
the fake client.  The path dropdown includes the options for
Default path (which will default to the config setting)
WIDE1-1,WIDE2-1
ARISS
This commit is contained in:
Hemna 2023-10-05 10:33:07 -04:00
parent e2f89a6043
commit ddd4d25e9d
6 changed files with 107 additions and 32 deletions

View File

@ -2,6 +2,7 @@ import logging
import threading
import time
import aprslib
from oslo_config import cfg
import wrapt
@ -21,6 +22,11 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
thread_stop = False
lock = threading.Lock()
path = []
def __init__(self):
LOG.info("Starting APRSDFakeClient client.")
self.path = ["WIDE1-1", "WIDE2-1"]
def stop(self):
self.thread_stop = True
@ -34,16 +40,34 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
def send(self, packet: core.Packet):
"""Send an APRS Message object."""
LOG.info(f"Sending packet: {packet}")
payload = None
if isinstance(packet, core.Packet):
packet.prepare()
payload = packet.payload.encode("US-ASCII")
if packet.path:
packet.path
else:
self.path
else:
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
payload = (
":{:<9}:{}".format(
packet.to_call,
msg_payload,
)
).encode("US-ASCII")
LOG.debug(
f"FAKE::Send '{payload}' TO '{packet.to_call}' From "
f"'{packet.from_call}' with PATH \"{self.path}\"",
)
def consumer(self, callback, blocking=False, immortal=False, raw=False):
LOG.debug("Start non blocking FAKE consumer")
# Generate packets here?
pkt = core.MessagePacket(
from_call="N0CALL",
to_call=CONF.callsign,
message_text="Hello World",
msgNo=13,
)
raw = "GTOWN>APDW16,WIDE1-1,WIDE2-1:}KM6LYW-9>APZ100,TCPIP,GTOWN*::KM6LYW :KM6LYW: 19 Miles SW"
pkt_raw = aprslib.parse(raw)
pkt = core.Packet.factory(pkt_raw)
callback(packet=pkt)
LOG.debug(f"END blocking FAKE consumer {self}")
time.sleep(8)

View File

@ -14,6 +14,8 @@ LOG = logging.getLogger("APRSD")
class KISS3Client:
path = []
def __init__(self):
self.setup()
@ -34,6 +36,7 @@ class KISS3Client:
speed=CONF.kiss_serial.baudrate,
strip_df_start=True,
)
self.path = CONF.kiss_serial.path
elif CONF.kiss_tcp.enabled:
LOG.debug(
"KISS({}) TCP Connection to {}:{}".format(
@ -47,6 +50,7 @@ class KISS3Client:
port=CONF.kiss_tcp.port,
strip_df_start=True,
)
self.path = CONF.kiss_serial.path
LOG.debug("Starting KISS interface connection")
self.kiss.start()
@ -87,10 +91,12 @@ class KISS3Client:
"""Send an APRS Message object."""
payload = None
path = ["WIDE1-1", "WIDE2-1"]
self.path
if isinstance(packet, core.Packet):
packet.prepare()
payload = packet.payload.encode("US-ASCII")
if packet.path:
packet.path
else:
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
payload = (
@ -102,12 +108,12 @@ class KISS3Client:
LOG.debug(
f"KISS Send '{payload}' TO '{packet.to_call}' From "
f"'{packet.from_call}' with PATH '{path}'",
f"'{packet.from_call}' with PATH '{self.path}'",
)
frame = Frame.ui(
destination="APZ100",
source=packet.from_call,
path=path,
path=self.path,
info=payload,
)
self.kiss.write(frame)

View File

@ -157,25 +157,26 @@ def _get_transport(stats):
"APRS-IS Server: <a href='http://status.aprs2.net' >"
"{}</a>".format(stats["stats"]["aprs-is"]["server"])
)
else:
# We might be connected to a KISS socket?
if client.KISSClient.is_enabled():
transport = client.KISSClient.transport()
if transport == client.TRANSPORT_TCPKISS:
aprs_connection = (
"TCPKISS://{}:{}".format(
CONF.kiss_tcp.host,
CONF.kiss_tcp.port,
)
)
elif transport == client.TRANSPORT_SERIALKISS:
# for pep8 violation
aprs_connection = (
"SerialKISS://{}@{} baud".format(
CONF.kiss_serial.device,
CONF.kiss_serial.baudrate,
),
elif client.KISSClient.is_enabled():
transport = client.KISSClient.transport()
if transport == client.TRANSPORT_TCPKISS:
aprs_connection = (
"TCPKISS://{}:{}".format(
CONF.kiss_tcp.host,
CONF.kiss_tcp.port,
)
)
elif transport == client.TRANSPORT_SERIALKISS:
# for pep8 violation
aprs_connection = (
"SerialKISS://{}@{} baud".format(
CONF.kiss_serial.device,
CONF.kiss_serial.baudrate,
),
)
elif CONF.fake_client.enabled:
transport = client.TRANSPORT_FAKE
aprs_connection = "Fake Client"
return transport, aprs_connection
@ -279,10 +280,18 @@ class SendMessageNamespace(Namespace):
LOG.debug(f"WS: on_send {data}")
self.request = data
data["from"] = CONF.callsign
path = data.get("path", None)
if "," in path:
path_opts = path.split(",")
path = [x.strip() for x in path_opts]
else:
path = [path]
pkt = packets.MessagePacket(
from_call=data["from"],
to_call=data["to"].upper(),
message_text=data["message"],
path=path,
)
pkt.prepare()
self.msg = pkt

View File

@ -11,10 +11,12 @@ aprs_group = cfg.OptGroup(
name="aprs_network",
title="APRS-IS Network settings",
)
kiss_serial_group = cfg.OptGroup(
name="kiss_serial",
title="KISS Serial device connection",
)
kiss_tcp_group = cfg.OptGroup(
name="kiss_tcp",
title="KISS TCP/IP Device connection",
@ -70,6 +72,11 @@ kiss_serial_opts = [
default=9600,
help="The Serial device baud rate for communication",
),
cfg.MultiStrOpt(
"path",
default=["WIDE1-1", "WIDE2-1"],
help="The APRS path to use for wide area coverage.",
),
]
kiss_tcp_opts = [
@ -87,6 +94,11 @@ kiss_tcp_opts = [
default=8001,
help="The KISS TCP/IP network port",
),
cfg.MultiStrOpt(
"path",
default=["WIDE1-1", "WIDE2-1"],
help="The APRS path to use for wide area coverage.",
),
]
fake_client_opts = [

View File

@ -61,6 +61,7 @@ function init_chat() {
event.preventDefault();
to_call = $('#to_call').val();
message = $('#message').val();
path = $('#pkt_path option:selected').val();
if (to_call == "") {
raise_error("You must enter a callsign to send a message")
return false;
@ -69,7 +70,8 @@ function init_chat() {
raise_error("You must enter a message to send")
return false;
}
msg = {'to': to_call, 'message': message, }
msg = {'to': to_call, 'message': message, 'path': path};
console.log(msg);
socket.emit("send", msg);
$('#message').val('');
}
@ -294,7 +296,7 @@ function delete_tab(callsign) {
save_data();
}
function add_callsign(callsign) {
function add_callsign(callsign, msg) {
/* Ensure a callsign exists in the left hand nav */
if (callsign in callsign_list) {
return false
@ -306,10 +308,19 @@ function add_callsign(callsign) {
active = false;
}
create_callsign_tab(callsign, active);
callsign_list[callsign] = true;
callsign_list[callsign] = '';
return true;
}
function update_callsign_path(callsign, path) {
//Get the selected path to save for this callsign
path = msg['path']
console.log("Path is " + path);
$('#pkt_path').val(path);
callsign_list[callsign] = path;
}
function append_message(callsign, msg, msg_html) {
new_callsign = false
if (!message_list.hasOwnProperty(callsign)) {
@ -330,7 +341,9 @@ function append_message(callsign, msg, msg_html) {
}
// Find the right div to place the html
new_callsign = add_callsign(callsign);
new_callsign = add_callsign(callsign, msg);
update_callsign_path(callsign, msg['path']);
append_message_html(callsign, msg_html, new_callsign);
if (new_callsign) {
//Now click the tab
@ -486,4 +499,6 @@ function callsign_select(callsign) {
tab_notify_id = tab_notification_id(callsign, true);
$(tab_notify_id).addClass('visually-hidden');
$(tab_notify_id).text(0);
// Now update the path
$('#pkt_path').val(callsign_list[callsign]);
}

View File

@ -90,10 +90,19 @@
</div>
<div class="row">
<form class="row gx-1 gy-1 justify-content-center align-items-center" id="sendform" name="sendmsg" action="">
<div class="col-sm-3">
<div class="col-sm-2" style="width:150px;">
<label for="to_call" class="visually-hidden">Callsign</label>
<input type="search" class="form-control mb-2 mr-sm-2" name="to_call" id="to_call" placeholder="To Callsign" size="11" maxlength="9">
</div>
<div class="col-auto">
<label for="pkt_path" class="visually-hidden">PATH</label>
<select class="form-control mb-2 mr-sm-2" name="pkt_path" id="pkt_path" style="width:auto;">
<option value="">Default Path</option>
<option value="WIDE1-1,WIDE2-2" selected>WIDE1-1,WIDE2-2</option>
<option value="WIDE1-1">WIDE1-1</option>
<option value="ARISS">ARISS</option>
</select>
</div>
<div class="col-sm-3">
<label for="message" class="visually-hidden">Message</label>
<input type="search" class="form-control mb-2 mr-sm-2" name="message" id="message" size="40" maxlength="67" placeholder="Message">