mirror of
https://github.com/craigerl/aprsd.git
synced 2025-07-02 17:05:18 -04:00
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:
parent
e2f89a6043
commit
ddd4d25e9d
@ -2,6 +2,7 @@ import logging
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import aprslib
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import wrapt
|
import wrapt
|
||||||
|
|
||||||
@ -21,6 +22,11 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
|
|||||||
thread_stop = False
|
thread_stop = False
|
||||||
|
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
path = []
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
LOG.info("Starting APRSDFakeClient client.")
|
||||||
|
self.path = ["WIDE1-1", "WIDE2-1"]
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.thread_stop = True
|
self.thread_stop = True
|
||||||
@ -34,16 +40,34 @@ class APRSDFakeClient(metaclass=trace.TraceWrapperMetaclass):
|
|||||||
def send(self, packet: core.Packet):
|
def send(self, packet: core.Packet):
|
||||||
"""Send an APRS Message object."""
|
"""Send an APRS Message object."""
|
||||||
LOG.info(f"Sending packet: {packet}")
|
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):
|
def consumer(self, callback, blocking=False, immortal=False, raw=False):
|
||||||
LOG.debug("Start non blocking FAKE consumer")
|
LOG.debug("Start non blocking FAKE consumer")
|
||||||
# Generate packets here?
|
# Generate packets here?
|
||||||
pkt = core.MessagePacket(
|
raw = "GTOWN>APDW16,WIDE1-1,WIDE2-1:}KM6LYW-9>APZ100,TCPIP,GTOWN*::KM6LYW :KM6LYW: 19 Miles SW"
|
||||||
from_call="N0CALL",
|
pkt_raw = aprslib.parse(raw)
|
||||||
to_call=CONF.callsign,
|
pkt = core.Packet.factory(pkt_raw)
|
||||||
message_text="Hello World",
|
|
||||||
msgNo=13,
|
|
||||||
)
|
|
||||||
callback(packet=pkt)
|
callback(packet=pkt)
|
||||||
LOG.debug(f"END blocking FAKE consumer {self}")
|
LOG.debug(f"END blocking FAKE consumer {self}")
|
||||||
time.sleep(8)
|
time.sleep(8)
|
||||||
|
@ -14,6 +14,8 @@ LOG = logging.getLogger("APRSD")
|
|||||||
|
|
||||||
|
|
||||||
class KISS3Client:
|
class KISS3Client:
|
||||||
|
path = []
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
@ -34,6 +36,7 @@ class KISS3Client:
|
|||||||
speed=CONF.kiss_serial.baudrate,
|
speed=CONF.kiss_serial.baudrate,
|
||||||
strip_df_start=True,
|
strip_df_start=True,
|
||||||
)
|
)
|
||||||
|
self.path = CONF.kiss_serial.path
|
||||||
elif CONF.kiss_tcp.enabled:
|
elif CONF.kiss_tcp.enabled:
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
"KISS({}) TCP Connection to {}:{}".format(
|
"KISS({}) TCP Connection to {}:{}".format(
|
||||||
@ -47,6 +50,7 @@ class KISS3Client:
|
|||||||
port=CONF.kiss_tcp.port,
|
port=CONF.kiss_tcp.port,
|
||||||
strip_df_start=True,
|
strip_df_start=True,
|
||||||
)
|
)
|
||||||
|
self.path = CONF.kiss_serial.path
|
||||||
|
|
||||||
LOG.debug("Starting KISS interface connection")
|
LOG.debug("Starting KISS interface connection")
|
||||||
self.kiss.start()
|
self.kiss.start()
|
||||||
@ -87,10 +91,12 @@ class KISS3Client:
|
|||||||
"""Send an APRS Message object."""
|
"""Send an APRS Message object."""
|
||||||
|
|
||||||
payload = None
|
payload = None
|
||||||
path = ["WIDE1-1", "WIDE2-1"]
|
self.path
|
||||||
if isinstance(packet, core.Packet):
|
if isinstance(packet, core.Packet):
|
||||||
packet.prepare()
|
packet.prepare()
|
||||||
payload = packet.payload.encode("US-ASCII")
|
payload = packet.payload.encode("US-ASCII")
|
||||||
|
if packet.path:
|
||||||
|
packet.path
|
||||||
else:
|
else:
|
||||||
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
|
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
|
||||||
payload = (
|
payload = (
|
||||||
@ -102,12 +108,12 @@ class KISS3Client:
|
|||||||
|
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
f"KISS Send '{payload}' TO '{packet.to_call}' From "
|
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(
|
frame = Frame.ui(
|
||||||
destination="APZ100",
|
destination="APZ100",
|
||||||
source=packet.from_call,
|
source=packet.from_call,
|
||||||
path=path,
|
path=self.path,
|
||||||
info=payload,
|
info=payload,
|
||||||
)
|
)
|
||||||
self.kiss.write(frame)
|
self.kiss.write(frame)
|
||||||
|
@ -157,25 +157,26 @@ def _get_transport(stats):
|
|||||||
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
"APRS-IS Server: <a href='http://status.aprs2.net' >"
|
||||||
"{}</a>".format(stats["stats"]["aprs-is"]["server"])
|
"{}</a>".format(stats["stats"]["aprs-is"]["server"])
|
||||||
)
|
)
|
||||||
else:
|
elif client.KISSClient.is_enabled():
|
||||||
# We might be connected to a KISS socket?
|
transport = client.KISSClient.transport()
|
||||||
if client.KISSClient.is_enabled():
|
if transport == client.TRANSPORT_TCPKISS:
|
||||||
transport = client.KISSClient.transport()
|
aprs_connection = (
|
||||||
if transport == client.TRANSPORT_TCPKISS:
|
"TCPKISS://{}:{}".format(
|
||||||
aprs_connection = (
|
CONF.kiss_tcp.host,
|
||||||
"TCPKISS://{}:{}".format(
|
CONF.kiss_tcp.port,
|
||||||
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 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
|
return transport, aprs_connection
|
||||||
|
|
||||||
@ -279,10 +280,18 @@ class SendMessageNamespace(Namespace):
|
|||||||
LOG.debug(f"WS: on_send {data}")
|
LOG.debug(f"WS: on_send {data}")
|
||||||
self.request = data
|
self.request = data
|
||||||
data["from"] = CONF.callsign
|
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(
|
pkt = packets.MessagePacket(
|
||||||
from_call=data["from"],
|
from_call=data["from"],
|
||||||
to_call=data["to"].upper(),
|
to_call=data["to"].upper(),
|
||||||
message_text=data["message"],
|
message_text=data["message"],
|
||||||
|
path=path,
|
||||||
)
|
)
|
||||||
pkt.prepare()
|
pkt.prepare()
|
||||||
self.msg = pkt
|
self.msg = pkt
|
||||||
|
@ -11,10 +11,12 @@ aprs_group = cfg.OptGroup(
|
|||||||
name="aprs_network",
|
name="aprs_network",
|
||||||
title="APRS-IS Network settings",
|
title="APRS-IS Network settings",
|
||||||
)
|
)
|
||||||
|
|
||||||
kiss_serial_group = cfg.OptGroup(
|
kiss_serial_group = cfg.OptGroup(
|
||||||
name="kiss_serial",
|
name="kiss_serial",
|
||||||
title="KISS Serial device connection",
|
title="KISS Serial device connection",
|
||||||
)
|
)
|
||||||
|
|
||||||
kiss_tcp_group = cfg.OptGroup(
|
kiss_tcp_group = cfg.OptGroup(
|
||||||
name="kiss_tcp",
|
name="kiss_tcp",
|
||||||
title="KISS TCP/IP Device connection",
|
title="KISS TCP/IP Device connection",
|
||||||
@ -70,6 +72,11 @@ kiss_serial_opts = [
|
|||||||
default=9600,
|
default=9600,
|
||||||
help="The Serial device baud rate for communication",
|
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 = [
|
kiss_tcp_opts = [
|
||||||
@ -87,6 +94,11 @@ kiss_tcp_opts = [
|
|||||||
default=8001,
|
default=8001,
|
||||||
help="The KISS TCP/IP network port",
|
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 = [
|
fake_client_opts = [
|
||||||
|
@ -61,6 +61,7 @@ function init_chat() {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
to_call = $('#to_call').val();
|
to_call = $('#to_call').val();
|
||||||
message = $('#message').val();
|
message = $('#message').val();
|
||||||
|
path = $('#pkt_path option:selected').val();
|
||||||
if (to_call == "") {
|
if (to_call == "") {
|
||||||
raise_error("You must enter a callsign to send a message")
|
raise_error("You must enter a callsign to send a message")
|
||||||
return false;
|
return false;
|
||||||
@ -69,7 +70,8 @@ function init_chat() {
|
|||||||
raise_error("You must enter a message to send")
|
raise_error("You must enter a message to send")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
msg = {'to': to_call, 'message': message, }
|
msg = {'to': to_call, 'message': message, 'path': path};
|
||||||
|
console.log(msg);
|
||||||
socket.emit("send", msg);
|
socket.emit("send", msg);
|
||||||
$('#message').val('');
|
$('#message').val('');
|
||||||
}
|
}
|
||||||
@ -294,7 +296,7 @@ function delete_tab(callsign) {
|
|||||||
save_data();
|
save_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_callsign(callsign) {
|
function add_callsign(callsign, msg) {
|
||||||
/* Ensure a callsign exists in the left hand nav */
|
/* Ensure a callsign exists in the left hand nav */
|
||||||
if (callsign in callsign_list) {
|
if (callsign in callsign_list) {
|
||||||
return false
|
return false
|
||||||
@ -306,10 +308,19 @@ function add_callsign(callsign) {
|
|||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
create_callsign_tab(callsign, active);
|
create_callsign_tab(callsign, active);
|
||||||
callsign_list[callsign] = true;
|
callsign_list[callsign] = '';
|
||||||
return true;
|
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) {
|
function append_message(callsign, msg, msg_html) {
|
||||||
new_callsign = false
|
new_callsign = false
|
||||||
if (!message_list.hasOwnProperty(callsign)) {
|
if (!message_list.hasOwnProperty(callsign)) {
|
||||||
@ -330,7 +341,9 @@ function append_message(callsign, msg, msg_html) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the right div to place the 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);
|
append_message_html(callsign, msg_html, new_callsign);
|
||||||
if (new_callsign) {
|
if (new_callsign) {
|
||||||
//Now click the tab
|
//Now click the tab
|
||||||
@ -486,4 +499,6 @@ function callsign_select(callsign) {
|
|||||||
tab_notify_id = tab_notification_id(callsign, true);
|
tab_notify_id = tab_notification_id(callsign, true);
|
||||||
$(tab_notify_id).addClass('visually-hidden');
|
$(tab_notify_id).addClass('visually-hidden');
|
||||||
$(tab_notify_id).text(0);
|
$(tab_notify_id).text(0);
|
||||||
|
// Now update the path
|
||||||
|
$('#pkt_path').val(callsign_list[callsign]);
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<form class="row gx-1 gy-1 justify-content-center align-items-center" id="sendform" name="sendmsg" action="">
|
<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>
|
<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">
|
<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>
|
||||||
|
<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">
|
<div class="col-sm-3">
|
||||||
<label for="message" class="visually-hidden">Message</label>
|
<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">
|
<input type="search" class="form-control mb-2 mr-sm-2" name="message" id="message" size="40" maxlength="67" placeholder="Message">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user