1
0
mirror of https://github.com/craigerl/aprsd.git synced 2024-12-22 01:20:59 -05:00

Fix sending packets over KISS interface

The KISS client sends the path as part of the headers, so we had
to strip out the path from the payload of each message so the path
wouldn't get listed twice.
This commit is contained in:
Hemna 2023-07-28 17:25:06 -04:00
parent 011cfc55e1
commit 9ebf2f9a30
3 changed files with 70 additions and 55 deletions

View File

@ -81,27 +81,18 @@ class KISS3Client:
LOG.debug("Start blocking KISS consumer") LOG.debug("Start blocking KISS consumer")
self._parse_callback = callback self._parse_callback = callback
self.kiss.read(callback=self.parse_frame, min_frames=None) self.kiss.read(callback=self.parse_frame, min_frames=None)
LOG.debug("END blocking KISS consumer") LOG.debug(f"END blocking KISS consumer {self.kiss}")
def send(self, packet): def send(self, packet):
"""Send an APRS Message object.""" """Send an APRS Message object."""
# payload = (':%-9s:%s' % (
# msg.tocall,
# payload
# )).encode('US-ASCII'),
# payload = str(msg).encode('US-ASCII')
payload = None payload = None
path = ["WIDE1-1", "WIDE2-1"] path = ["WIDE1-1", "WIDE2-1"]
if isinstance(packet, core.AckPacket): if isinstance(packet, core.Packet):
msg_payload = f"ack{packet.msgNo}" packet.prepare()
elif isinstance(packet, core.Packet): payload = packet.payload.encode("US-ASCII")
payload = packet.raw.encode("US-ASCII")
path = ["WIDE2-1"]
else: else:
msg_payload = f"{packet.raw}{{{str(packet.msgNo)}" msg_payload = f"{packet.raw}{{{str(packet.msgNo)}"
if not payload:
payload = ( payload = (
":{:<9}:{}".format( ":{:<9}:{}".format(
packet.to_call, packet.to_call,
@ -109,9 +100,12 @@ class KISS3Client:
) )
).encode("US-ASCII") ).encode("US-ASCII")
LOG.debug(f"Send '{payload}' TO KISS") LOG.debug(
f"KISS Send '{payload}' TO '{packet.to_call}' From "
f"'{packet.from_call}' with PATH '{path}'",
)
frame = Frame.ui( frame = Frame.ui(
destination=packet.to_call, destination="APZ100",
source=packet.from_call, source=packet.from_call,
path=path, path=path,
info=payload, info=payload,

View File

@ -57,6 +57,8 @@ class Packet(metaclass=abc.ABCMeta):
# or holds the raw string from input packet # or holds the raw string from input packet
raw: str = None raw: str = None
raw_dict: dict = field(repr=False, default_factory=lambda: {}) raw_dict: dict = field(repr=False, default_factory=lambda: {})
# Built by calling prepare(). raw needs this built first.
payload: str = None
# Fields related to sending packets out # Fields related to sending packets out
send_count: int = field(repr=False, default=0) send_count: int = field(repr=False, default=0)
@ -92,11 +94,24 @@ class Packet(metaclass=abc.ABCMeta):
def prepare(self): def prepare(self):
"""Do stuff here that is needed prior to sending over the air.""" """Do stuff here that is needed prior to sending over the air."""
# now build the raw message for sending # now build the raw message for sending
self._build_payload()
self._build_raw() self._build_raw()
def _build_payload(self):
"""The payload is the non headers portion of the packet."""
msg = self._filter_for_send().rstrip("\n")
self.payload = (
f":{self.to_call.ljust(9)}"
f":{msg}"
)
def _build_raw(self): def _build_raw(self):
"""Build the self.raw string which is what is sent over the air.""" """Build the self.raw which is what is sent over the air."""
self.raw = self._filter_for_send().rstrip("\n") self.raw = "{}>APZ100:{}".format(
self.from_call,
self.payload,
)
LOG.debug(f"_build_raw: payload '{self.payload}' raw '{self.raw}'")
@staticmethod @staticmethod
def factory(raw_packet): def factory(raw_packet):
@ -233,7 +248,7 @@ class PathPacket(Packet):
path: List[str] = field(default_factory=list) path: List[str] = field(default_factory=list)
via: str = None via: str = None
def _build_raw(self): def _build_payload(self):
raise NotImplementedError raise NotImplementedError
@ -245,13 +260,8 @@ class AckPacket(PathPacket):
if self.response: if self.response:
LOG.warning("Response set!") LOG.warning("Response set!")
def _build_raw(self): def _build_payload(self):
"""Build the self.raw which is what is sent over the air.""" self.payload = f":{self.to_call.ljust(9)}:ack{self.msgNo}"
self.raw = "{}>APZ100::{}:ack{}".format(
self.from_call,
self.to_call.ljust(9),
self.msgNo,
)
@dataclass @dataclass
@ -262,13 +272,8 @@ class RejectPacket(PathPacket):
if self.response: if self.response:
LOG.warning("Response set!") LOG.warning("Response set!")
def _build_raw(self): def _build_payload(self):
"""Build the self.raw which is what is sent over the air.""" self.payload = f":{self.to_call.ljust(9)} :rej{self.msgNo}"
self.raw = "{}>APZ100::{} :rej{}".format(
self.from_call,
self.to_call.ljust(9),
self.msgNo,
)
@dataclass @dataclass
@ -285,10 +290,8 @@ class MessagePacket(PathPacket):
# We all miss George Carlin # We all miss George Carlin
return re.sub("fuck|shit|cunt|piss|cock|bitch", "****", message) return re.sub("fuck|shit|cunt|piss|cock|bitch", "****", message)
def _build_raw(self): def _build_payload(self):
"""Build the self.raw which is what is sent over the air.""" self.payload = ":{}:{}{{{}".format(
self.raw = "{}>APZ100::{}:{}{{{}".format(
self.from_call,
self.to_call.ljust(9), self.to_call.ljust(9),
self._filter_for_send().rstrip("\n"), self._filter_for_send().rstrip("\n"),
str(self.msgNo), str(self.msgNo),
@ -301,7 +304,7 @@ class StatusPacket(PathPacket):
messagecapable: bool = False messagecapable: bool = False
comment: str = None comment: str = None
def _build_raw(self): def _build_payload(self):
raise NotImplementedError raise NotImplementedError
@ -400,16 +403,24 @@ class GPSPacket(PathPacket):
time_zulu = result_utc_datetime.strftime("%d%H%M") time_zulu = result_utc_datetime.strftime("%d%H%M")
return time_zulu return time_zulu
def _build_raw(self): def _build_payload(self):
"""The payload is the non headers portion of the packet."""
time_zulu = self._build_time_zulu() time_zulu = self._build_time_zulu()
lat = self.latitude
long = self.longitude
self.payload = (
f"@{time_zulu}z{lat}{self.symbol_table}"
f"{long}{self.symbol}"
)
if self.comment:
self.payload = f"{self.payload}{self.comment}"
def _build_raw(self):
self.raw = ( self.raw = (
f"{self.from_call}>{self.to_call},WIDE2-1:" f"{self.from_call}>{self.to_call},WIDE2-1:"
f"@{time_zulu}z{self.latitude}{self.symbol_table}" f"{self.payload}"
f"{self.longitude}{self.symbol}"
) )
if self.comment:
self.raw = f"{self.raw}{self.comment}"
@dataclass @dataclass
@ -422,7 +433,7 @@ class MicEPacket(GPSPacket):
# 0 to 360 # 0 to 360
course: int = 0 course: int = 0
def _build_raw(self): def _build_payload(self):
raise NotImplementedError raise NotImplementedError
@ -436,6 +447,19 @@ class ObjectPacket(GPSPacket):
# 0 to 360 # 0 to 360
course: int = 0 course: int = 0
def _build_payload(self):
time_zulu = self._build_time_zulu()
lat = self.convert_latitude(self.latitude)
long = self.convert_longitude(self.longitude)
self.payload = (
f"*{time_zulu}z{lat}{self.symbol_table}"
f"{long}{self.symbol}"
)
if self.comment:
self.payload = f"{self.payload}{self.comment}"
def _build_raw(self): def _build_raw(self):
""" """
REPEAT builds packets like REPEAT builds packets like
@ -446,17 +470,11 @@ class ObjectPacket(GPSPacket):
callsign is the station callsign for the object callsign is the station callsign for the object
The frequency, uplink_tone, offset is part of the comment The frequency, uplink_tone, offset is part of the comment
""" """
time_zulu = self._build_time_zulu()
lat = self.convert_latitude(self.latitude)
long = self.convert_longitude(self.longitude)
self.raw = ( self.raw = (
f"{self.from_call}>APZ100:;{self.to_call:9s}" f"{self.from_call}>APZ100:;{self.to_call:9s}"
f"*{time_zulu}z{lat}{self.symbol_table}" f"{self.payload}"
f"{long}{self.symbol}"
) )
if self.comment:
self.raw = f"{self.raw}{self.comment}"
@dataclass() @dataclass()
@ -474,7 +492,7 @@ class WeatherPacket(GPSPacket):
pressure: float = 0.00 pressure: float = 0.00
comment: str = None comment: str = None
def _build_raw(self): def _build_payload(self):
"""Build an uncompressed weather packet """Build an uncompressed weather packet
Format = Format =
@ -502,7 +520,6 @@ class WeatherPacket(GPSPacket):
time_zulu = self._build_time_zulu() time_zulu = self._build_time_zulu()
contents = [ contents = [
f"{self.from_call}>{self.to_call},WIDE1-1,WIDE2-1:",
f"@{time_zulu}z{self.latitude}{self.symbol_table}", f"@{time_zulu}z{self.latitude}{self.symbol_table}",
f"{self.longitude}{self.symbol}", f"{self.longitude}{self.symbol}",
f"{self.wind_direction:03d}", f"{self.wind_direction:03d}",
@ -523,11 +540,16 @@ class WeatherPacket(GPSPacket):
# Barometric pressure (in tenths of millibars/tenths of hPascal) # Barometric pressure (in tenths of millibars/tenths of hPascal)
f"b{self.pressure:05.0f}", f"b{self.pressure:05.0f}",
] ]
if self.comment: if self.comment:
contents.append(self.comment) contents.append(self.comment)
self.payload = "".join(contents)
self.raw = "".join(contents) def _build_raw(self):
self.raw = (
f"{self.from_call}>{self.to_call},WIDE1-1,WIDE2-1:"
f"{self.payload}"
)
TYPE_LOOKUP = { TYPE_LOOKUP = {

View File

@ -246,7 +246,6 @@ class APRSDStats:
}, },
"plugins": plugin_stats, "plugins": plugin_stats,
} }
LOG.debug(f"STATS = {stats}")
LOG.info("APRSD Stats: DONE") LOG.info("APRSD Stats: DONE")
return stats return stats