diff --git a/aprsd/packets/core.py b/aprsd/packets/core.py index 8a2ddcd..351c9c5 100644 --- a/aprsd/packets/core.py +++ b/aprsd/packets/core.py @@ -18,6 +18,7 @@ LOG = logging.getLogger("APRSD") PACKET_TYPE_MESSAGE = "message" PACKET_TYPE_ACK = "ack" +PACKET_TYPE_REJECT = "reject" PACKET_TYPE_MICE = "mic-e" PACKET_TYPE_WX = "weather" PACKET_TYPE_OBJECT = "object" @@ -209,6 +210,23 @@ class AckPacket(PathPacket): ) +@dataclass +class RejectPacket(PathPacket): + response: str = None + + def __post__init__(self): + if self.response: + LOG.warning("Response set!") + + def _build_raw(self): + """Build the self.raw which is what is sent over the air.""" + self.raw = "{}>APZ100::{} :rej{}".format( + self.from_call, + self.to_call.ljust(9), + self.msgNo, + ) + + @dataclass class MessagePacket(PathPacket): message_text: str = None @@ -469,6 +487,7 @@ TYPE_LOOKUP = { PACKET_TYPE_WX: WeatherPacket, PACKET_TYPE_MESSAGE: MessagePacket, PACKET_TYPE_ACK: AckPacket, + PACKET_TYPE_REJECT: RejectPacket, PACKET_TYPE_MICE: MicEPacket, PACKET_TYPE_OBJECT: ObjectPacket, PACKET_TYPE_STATUS: StatusPacket, @@ -485,6 +504,8 @@ def get_packet_type(packet: dict): packet_type = "unknown" if pkt_format == "message" and msg_response == "ack": packet_type = PACKET_TYPE_ACK + elif pkt_format == "message" and msg_response == "rej": + packet_type = PACKET_TYPE_REJECT elif pkt_format == "message": packet_type = PACKET_TYPE_MESSAGE elif pkt_format == "mic-e": diff --git a/aprsd/threads/rx.py b/aprsd/threads/rx.py index 3689040..f6cc35e 100644 --- a/aprsd/threads/rx.py +++ b/aprsd/threads/rx.py @@ -87,11 +87,18 @@ class APRSDProcessPacketThread(APRSDThread): self._loop_cnt = 1 def process_ack_packet(self, packet): + """We got an ack for a message, no need to resend it.""" ack_num = packet.msgNo LOG.info(f"Got ack for message {ack_num}") pkt_tracker = packets.PacketTrack() pkt_tracker.remove(ack_num) - return + + def process_reject_packet(self, packet): + """We got a reject message for a packet. Stop sending the message.""" + ack_num = packet.msgNo + LOG.info(f"Got REJECT for message {ack_num}") + pkt_tracker = packets.PacketTrack() + pkt_tracker.remove(ack_num) def loop(self): try: @@ -124,6 +131,11 @@ class APRSDProcessPacketThread(APRSDThread): and packet.addresse.lower() == our_call ): self.process_ack_packet(packet) + elif ( + isinstance(packet, packets.RejectPacket) + and packet.addresse.lower() == our_call + ): + self.process_reject_packet(packet) else: # Only ack messages that were sent directly to us if isinstance(packet, packets.MessagePacket):