2022-12-15 17:23:54 -05:00
|
|
|
import datetime
|
2024-04-19 12:53:12 -04:00
|
|
|
import logging
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2022-12-24 13:53:06 -05:00
|
|
|
from oslo_config import cfg
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2024-04-17 14:41:43 -04:00
|
|
|
from aprsd.packets import collector, core
|
2022-12-15 17:23:54 -05:00
|
|
|
from aprsd.utils import objectstore
|
|
|
|
|
|
|
|
|
2022-12-24 13:53:06 -05:00
|
|
|
CONF = cfg.CONF
|
2024-04-19 12:53:12 -04:00
|
|
|
LOG = logging.getLogger("APRSD")
|
2022-12-24 13:53:06 -05:00
|
|
|
|
|
|
|
|
2022-12-15 17:23:54 -05:00
|
|
|
class PacketTrack(objectstore.ObjectStoreMixin):
|
|
|
|
"""Class to keep track of outstanding text messages.
|
|
|
|
|
|
|
|
This is a thread safe class that keeps track of active
|
|
|
|
messages.
|
|
|
|
|
|
|
|
When a message is asked to be sent, it is placed into this
|
|
|
|
class via it's id. The TextMessage class's send() method
|
|
|
|
automatically adds itself to this class. When the ack is
|
|
|
|
recieved from the radio, the message object is removed from
|
|
|
|
this class.
|
|
|
|
"""
|
|
|
|
|
|
|
|
_instance = None
|
|
|
|
_start_time = None
|
|
|
|
|
2022-12-17 20:02:49 -05:00
|
|
|
data: dict = {}
|
|
|
|
total_tracked: int = 0
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
if cls._instance is None:
|
|
|
|
cls._instance = super().__new__(cls)
|
|
|
|
cls._instance._start_time = datetime.datetime.now()
|
|
|
|
cls._instance._init_store()
|
|
|
|
return cls._instance
|
|
|
|
|
|
|
|
def __getitem__(self, name):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self.data[name]
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def __iter__(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return iter(self.data)
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def keys(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self.data.keys()
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def items(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self.data.items()
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def values(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self.data.values()
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2024-04-02 14:07:37 -04:00
|
|
|
def stats(self, serializable=False):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
stats = {
|
|
|
|
"total_tracked": self.total_tracked,
|
2024-03-29 11:51:15 -04:00
|
|
|
}
|
2024-04-24 13:49:55 -04:00
|
|
|
pkts = {}
|
|
|
|
for key in self.data:
|
|
|
|
last_send_time = self.data[key].last_send_time
|
|
|
|
pkts[key] = {
|
|
|
|
"last_send_time": last_send_time,
|
|
|
|
"send_count": self.data[key].send_count,
|
|
|
|
"retry_count": self.data[key].retry_count,
|
|
|
|
"message": self.data[key].raw,
|
|
|
|
}
|
|
|
|
stats["packets"] = pkts
|
2024-03-29 11:51:15 -04:00
|
|
|
return stats
|
|
|
|
|
2024-04-17 14:41:43 -04:00
|
|
|
def rx(self, packet: type[core.Packet]) -> None:
|
|
|
|
"""When we get a packet from the network, check if we should remove it."""
|
|
|
|
if isinstance(packet, core.AckPacket):
|
|
|
|
self._remove(packet.msgNo)
|
|
|
|
elif isinstance(packet, core.RejectPacket):
|
|
|
|
self._remove(packet.msgNo)
|
2024-04-24 10:45:47 -04:00
|
|
|
elif hasattr(packet, "ackMsgNo"):
|
2024-04-17 14:41:43 -04:00
|
|
|
# Got a piggyback ack, so remove the original message
|
|
|
|
self._remove(packet.ackMsgNo)
|
|
|
|
|
|
|
|
def tx(self, packet: type[core.Packet]) -> None:
|
|
|
|
"""Add a packet that was sent."""
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
key = packet.msgNo
|
|
|
|
packet.send_count = 0
|
|
|
|
self.data[key] = packet
|
|
|
|
self.total_tracked += 1
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2023-09-27 14:55:47 -04:00
|
|
|
def remove(self, key):
|
2024-04-17 14:41:43 -04:00
|
|
|
self._remove(key)
|
|
|
|
|
|
|
|
def _remove(self, key):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
try:
|
|
|
|
del self.data[key]
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2024-04-17 14:41:43 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Now register the PacketList with the collector
|
|
|
|
# every packet we RX and TX goes through the collector
|
|
|
|
# for processing for whatever reason is needed.
|
|
|
|
collector.PacketCollector().register(PacketTrack)
|