mirror of
https://github.com/craigerl/aprsd.git
synced 2025-06-13 20:02:26 -04:00
Updated packet_list to allow infinit max store
This patch adds logic of setting packet_list_stats_maxlen -1 meaning keep every packet for stats.
This commit is contained in:
parent
1606585d41
commit
19c12e70f3
@ -3,220 +3,219 @@ from pathlib import Path
|
||||
from oslo_config import cfg
|
||||
|
||||
home = str(Path.home())
|
||||
DEFAULT_CONFIG_DIR = f"{home}/.config/aprsd/"
|
||||
APRSD_DEFAULT_MAGIC_WORD = "CHANGEME!!!"
|
||||
DEFAULT_CONFIG_DIR = f'{home}/.config/aprsd/'
|
||||
APRSD_DEFAULT_MAGIC_WORD = 'CHANGEME!!!'
|
||||
|
||||
watch_list_group = cfg.OptGroup(
|
||||
name="watch_list",
|
||||
title="Watch List settings",
|
||||
name='watch_list',
|
||||
title='Watch List settings',
|
||||
)
|
||||
|
||||
registry_group = cfg.OptGroup(
|
||||
name="aprs_registry",
|
||||
title="APRS Registry settings",
|
||||
name='aprs_registry',
|
||||
title='APRS Registry settings',
|
||||
)
|
||||
|
||||
aprsd_opts = [
|
||||
cfg.StrOpt(
|
||||
"callsign",
|
||||
'callsign',
|
||||
required=True,
|
||||
help="Callsign to use for messages sent by APRSD",
|
||||
help='Callsign to use for messages sent by APRSD',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"enable_save",
|
||||
'enable_save',
|
||||
default=True,
|
||||
help="Enable saving of watch list, packet tracker between restarts.",
|
||||
help='Enable saving of watch list, packet tracker between restarts.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"save_location",
|
||||
'save_location',
|
||||
default=DEFAULT_CONFIG_DIR,
|
||||
help="Save location for packet tracking files.",
|
||||
help='Save location for packet tracking files.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"trace_enabled",
|
||||
'trace_enabled',
|
||||
default=False,
|
||||
help="Enable code tracing",
|
||||
help='Enable code tracing',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"units",
|
||||
default="imperial",
|
||||
help="Units for display, imperial or metric",
|
||||
'units',
|
||||
default='imperial',
|
||||
help='Units for display, imperial or metric',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"ack_rate_limit_period",
|
||||
'ack_rate_limit_period',
|
||||
default=1,
|
||||
help="The wait period in seconds per Ack packet being sent."
|
||||
"1 means 1 ack packet per second allowed."
|
||||
"2 means 1 pack packet every 2 seconds allowed",
|
||||
help='The wait period in seconds per Ack packet being sent.'
|
||||
'1 means 1 ack packet per second allowed.'
|
||||
'2 means 1 pack packet every 2 seconds allowed',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"msg_rate_limit_period",
|
||||
'msg_rate_limit_period',
|
||||
default=2,
|
||||
help="Wait period in seconds per non AckPacket being sent."
|
||||
"2 means 1 packet every 2 seconds allowed."
|
||||
"5 means 1 pack packet every 5 seconds allowed",
|
||||
help='Wait period in seconds per non AckPacket being sent.'
|
||||
'2 means 1 packet every 2 seconds allowed.'
|
||||
'5 means 1 pack packet every 5 seconds allowed',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"packet_dupe_timeout",
|
||||
'packet_dupe_timeout',
|
||||
default=300,
|
||||
help="The number of seconds before a packet is not considered a duplicate.",
|
||||
help='The number of seconds before a packet is not considered a duplicate.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"enable_beacon",
|
||||
'enable_beacon',
|
||||
default=False,
|
||||
help="Enable sending of a GPS Beacon packet to locate this service. "
|
||||
"Requires latitude and longitude to be set.",
|
||||
help='Enable sending of a GPS Beacon packet to locate this service. '
|
||||
'Requires latitude and longitude to be set.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"beacon_interval",
|
||||
'beacon_interval',
|
||||
default=1800,
|
||||
help="The number of seconds between beacon packets.",
|
||||
help='The number of seconds between beacon packets.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"beacon_symbol",
|
||||
default="/",
|
||||
help="The symbol to use for the GPS Beacon packet. See: http://www.aprs.net/vm/DOS/SYMBOLS.HTM",
|
||||
'beacon_symbol',
|
||||
default='/',
|
||||
help='The symbol to use for the GPS Beacon packet. See: http://www.aprs.net/vm/DOS/SYMBOLS.HTM',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"latitude",
|
||||
'latitude',
|
||||
default=None,
|
||||
help="Latitude for the GPS Beacon button. If not set, the button will not be enabled.",
|
||||
help='Latitude for the GPS Beacon button. If not set, the button will not be enabled.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"longitude",
|
||||
'longitude',
|
||||
default=None,
|
||||
help="Longitude for the GPS Beacon button. If not set, the button will not be enabled.",
|
||||
help='Longitude for the GPS Beacon button. If not set, the button will not be enabled.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"log_packet_format",
|
||||
choices=["compact", "multiline", "both"],
|
||||
default="compact",
|
||||
'log_packet_format',
|
||||
choices=['compact', 'multiline', 'both'],
|
||||
default='compact',
|
||||
help="When logging packets 'compact' will use a single line formatted for each packet."
|
||||
"'multiline' will use multiple lines for each packet and is the traditional format."
|
||||
"both will log both compact and multiline.",
|
||||
'both will log both compact and multiline.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"default_packet_send_count",
|
||||
'default_packet_send_count',
|
||||
default=3,
|
||||
help="The number of times to send a non ack packet before giving up.",
|
||||
help='The number of times to send a non ack packet before giving up.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"default_ack_send_count",
|
||||
'default_ack_send_count',
|
||||
default=3,
|
||||
help="The number of times to send an ack packet in response to recieving a packet.",
|
||||
help='The number of times to send an ack packet in response to recieving a packet.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"packet_list_maxlen",
|
||||
'packet_list_maxlen',
|
||||
default=100,
|
||||
help="The maximum number of packets to store in the packet list.",
|
||||
help='The maximum number of packets to store in the packet list.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"packet_list_stats_maxlen",
|
||||
'packet_list_stats_maxlen',
|
||||
default=20,
|
||||
help="The maximum number of packets to send in the stats dict for admin ui.",
|
||||
help='The maximum number of packets to send in the stats dict for admin ui. -1 means no max.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"enable_seen_list",
|
||||
'enable_seen_list',
|
||||
default=True,
|
||||
help="Enable the Callsign seen list tracking feature. This allows aprsd to keep track of "
|
||||
"callsigns that have been seen and when they were last seen.",
|
||||
help='Enable the Callsign seen list tracking feature. This allows aprsd to keep track of '
|
||||
'callsigns that have been seen and when they were last seen.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"enable_packet_logging",
|
||||
'enable_packet_logging',
|
||||
default=True,
|
||||
help="Set this to False, to disable logging of packets to the log file.",
|
||||
help='Set this to False, to disable logging of packets to the log file.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"load_help_plugin",
|
||||
'load_help_plugin',
|
||||
default=True,
|
||||
help="Set this to False to disable the help plugin.",
|
||||
help='Set this to False to disable the help plugin.',
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
"enable_sending_ack_packets",
|
||||
'enable_sending_ack_packets',
|
||||
default=True,
|
||||
help="Set this to False, to disable sending of ack packets. This will entirely stop"
|
||||
"APRSD from sending ack packets.",
|
||||
help='Set this to False, to disable sending of ack packets. This will entirely stop'
|
||||
'APRSD from sending ack packets.',
|
||||
),
|
||||
]
|
||||
|
||||
watch_list_opts = [
|
||||
cfg.BoolOpt(
|
||||
"enabled",
|
||||
'enabled',
|
||||
default=False,
|
||||
help="Enable the watch list feature. Still have to enable "
|
||||
"the correct plugin. Built-in plugin to use is "
|
||||
"aprsd.plugins.notify.NotifyPlugin",
|
||||
help='Enable the watch list feature. Still have to enable '
|
||||
'the correct plugin. Built-in plugin to use is '
|
||||
'aprsd.plugins.notify.NotifyPlugin',
|
||||
),
|
||||
cfg.ListOpt(
|
||||
"callsigns",
|
||||
help="Callsigns to watch for messsages",
|
||||
'callsigns',
|
||||
help='Callsigns to watch for messsages',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"alert_callsign",
|
||||
help="The Ham Callsign to send messages to for watch list alerts.",
|
||||
'alert_callsign',
|
||||
help='The Ham Callsign to send messages to for watch list alerts.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"packet_keep_count",
|
||||
'packet_keep_count',
|
||||
default=10,
|
||||
help="The number of packets to store.",
|
||||
help='The number of packets to store.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"alert_time_seconds",
|
||||
'alert_time_seconds',
|
||||
default=3600,
|
||||
help="Time to wait before alert is sent on new message for "
|
||||
"users in callsigns.",
|
||||
help='Time to wait before alert is sent on new message for users in callsigns.',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
enabled_plugins_opts = [
|
||||
cfg.ListOpt(
|
||||
"enabled_plugins",
|
||||
'enabled_plugins',
|
||||
default=[
|
||||
"aprsd.plugins.fortune.FortunePlugin",
|
||||
"aprsd.plugins.location.LocationPlugin",
|
||||
"aprsd.plugins.ping.PingPlugin",
|
||||
"aprsd.plugins.time.TimePlugin",
|
||||
"aprsd.plugins.weather.OWMWeatherPlugin",
|
||||
"aprsd.plugins.version.VersionPlugin",
|
||||
"aprsd.plugins.notify.NotifySeenPlugin",
|
||||
'aprsd.plugins.fortune.FortunePlugin',
|
||||
'aprsd.plugins.location.LocationPlugin',
|
||||
'aprsd.plugins.ping.PingPlugin',
|
||||
'aprsd.plugins.time.TimePlugin',
|
||||
'aprsd.plugins.weather.OWMWeatherPlugin',
|
||||
'aprsd.plugins.version.VersionPlugin',
|
||||
'aprsd.plugins.notify.NotifySeenPlugin',
|
||||
],
|
||||
help="Comma separated list of enabled plugins for APRSD."
|
||||
"To enable installed external plugins add them here."
|
||||
"The full python path to the class name must be used",
|
||||
help='Comma separated list of enabled plugins for APRSD.'
|
||||
'To enable installed external plugins add them here.'
|
||||
'The full python path to the class name must be used',
|
||||
),
|
||||
]
|
||||
|
||||
registry_opts = [
|
||||
cfg.BoolOpt(
|
||||
"enabled",
|
||||
'enabled',
|
||||
default=False,
|
||||
help="Enable sending aprs registry information. This will let the "
|
||||
help='Enable sending aprs registry information. This will let the '
|
||||
"APRS registry know about your service and it's uptime. "
|
||||
"No personal information is sent, just the callsign, uptime and description. "
|
||||
"The service callsign is the callsign set in [DEFAULT] section.",
|
||||
'No personal information is sent, just the callsign, uptime and description. '
|
||||
'The service callsign is the callsign set in [DEFAULT] section.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"description",
|
||||
'description',
|
||||
default=None,
|
||||
help="Description of the service to send to the APRS registry. "
|
||||
"This is what will show up in the APRS registry."
|
||||
"If not set, the description will be the same as the callsign.",
|
||||
help='Description of the service to send to the APRS registry. '
|
||||
'This is what will show up in the APRS registry.'
|
||||
'If not set, the description will be the same as the callsign.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"registry_url",
|
||||
default="https://aprs.hemna.com/api/v1/registry",
|
||||
help="The APRS registry domain name to send the information to.",
|
||||
'registry_url',
|
||||
default='https://aprs.hemna.com/api/v1/registry',
|
||||
help='The APRS registry domain name to send the information to.',
|
||||
),
|
||||
cfg.StrOpt(
|
||||
"service_website",
|
||||
'service_website',
|
||||
default=None,
|
||||
help="The website for your APRS service to send to the APRS registry.",
|
||||
help='The website for your APRS service to send to the APRS registry.',
|
||||
),
|
||||
cfg.IntOpt(
|
||||
"frequency_seconds",
|
||||
'frequency_seconds',
|
||||
default=3600,
|
||||
help="The frequency in seconds to send the APRS registry information.",
|
||||
help='The frequency in seconds to send the APRS registry information.',
|
||||
),
|
||||
]
|
||||
|
||||
@ -232,7 +231,7 @@ def register_opts(config):
|
||||
|
||||
def list_opts():
|
||||
return {
|
||||
"DEFAULT": (aprsd_opts + enabled_plugins_opts),
|
||||
'DEFAULT': (aprsd_opts + enabled_plugins_opts),
|
||||
watch_list_group.name: watch_list_opts,
|
||||
registry_group.name: registry_opts,
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ from aprsd.packets import core
|
||||
from aprsd.utils import objectstore
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger("APRSD")
|
||||
LOG = logging.getLogger('APRSD')
|
||||
|
||||
|
||||
class PacketList(objectstore.ObjectStoreMixin):
|
||||
@ -27,8 +27,8 @@ class PacketList(objectstore.ObjectStoreMixin):
|
||||
|
||||
def _init_data(self):
|
||||
self.data = {
|
||||
"types": {},
|
||||
"packets": OrderedDict(),
|
||||
'types': {},
|
||||
'packets': OrderedDict(),
|
||||
}
|
||||
|
||||
def rx(self, packet: type[core.Packet]):
|
||||
@ -37,11 +37,11 @@ class PacketList(objectstore.ObjectStoreMixin):
|
||||
self._total_rx += 1
|
||||
self._add(packet)
|
||||
ptype = packet.__class__.__name__
|
||||
type_stats = self.data["types"].setdefault(
|
||||
type_stats = self.data['types'].setdefault(
|
||||
ptype,
|
||||
{"tx": 0, "rx": 0},
|
||||
{'tx': 0, 'rx': 0},
|
||||
)
|
||||
type_stats["rx"] += 1
|
||||
type_stats['rx'] += 1
|
||||
|
||||
def tx(self, packet: type[core.Packet]):
|
||||
"""Add a packet that was received."""
|
||||
@ -49,32 +49,32 @@ class PacketList(objectstore.ObjectStoreMixin):
|
||||
self._total_tx += 1
|
||||
self._add(packet)
|
||||
ptype = packet.__class__.__name__
|
||||
type_stats = self.data["types"].setdefault(
|
||||
type_stats = self.data['types'].setdefault(
|
||||
ptype,
|
||||
{"tx": 0, "rx": 0},
|
||||
{'tx': 0, 'rx': 0},
|
||||
)
|
||||
type_stats["tx"] += 1
|
||||
type_stats['tx'] += 1
|
||||
|
||||
def add(self, packet):
|
||||
with self.lock:
|
||||
self._add(packet)
|
||||
|
||||
def _add(self, packet):
|
||||
if not self.data.get("packets"):
|
||||
if not self.data.get('packets'):
|
||||
self._init_data()
|
||||
if packet.key in self.data["packets"]:
|
||||
self.data["packets"].move_to_end(packet.key)
|
||||
elif len(self.data["packets"]) == self.maxlen:
|
||||
self.data["packets"].popitem(last=False)
|
||||
self.data["packets"][packet.key] = packet
|
||||
if packet.key in self.data['packets']:
|
||||
self.data['packets'].move_to_end(packet.key)
|
||||
elif len(self.data['packets']) == self.maxlen:
|
||||
self.data['packets'].popitem(last=False)
|
||||
self.data['packets'][packet.key] = packet
|
||||
|
||||
def find(self, packet):
|
||||
with self.lock:
|
||||
return self.data["packets"][packet.key]
|
||||
return self.data['packets'][packet.key]
|
||||
|
||||
def __len__(self):
|
||||
with self.lock:
|
||||
return len(self.data["packets"])
|
||||
return len(self.data['packets'])
|
||||
|
||||
def total_rx(self):
|
||||
with self.lock:
|
||||
@ -87,17 +87,23 @@ class PacketList(objectstore.ObjectStoreMixin):
|
||||
def stats(self, serializable=False) -> dict:
|
||||
with self.lock:
|
||||
# Get last N packets directly using list slicing
|
||||
packets_list = list(self.data.get("packets", {}).values())
|
||||
pkts = packets_list[-CONF.packet_list_stats_maxlen :][::-1]
|
||||
|
||||
if CONF.packet_list_stats_maxlen >= 0:
|
||||
packets_list = list(self.data.get('packets', {}).values())
|
||||
pkts = packets_list[-CONF.packet_list_stats_maxlen :][::-1]
|
||||
else:
|
||||
# We have to copy here, because this get() results in a pointer
|
||||
# to the packets internally here, which can change after this
|
||||
# function returns, which would cause a problem trying to save
|
||||
# the stats to disk.
|
||||
pkts = self.data.get('packets', {}).copy()
|
||||
stats = {
|
||||
"total_tracked": self._total_rx
|
||||
'total_tracked': self._total_rx
|
||||
+ self._total_tx, # Fixed typo: was rx + rx
|
||||
"rx": self._total_rx,
|
||||
"tx": self._total_tx,
|
||||
"types": self.data.get("types", {}), # Changed default from [] to {}
|
||||
"packet_count": len(self.data.get("packets", [])),
|
||||
"maxlen": self.maxlen,
|
||||
"packets": pkts,
|
||||
'rx': self._total_rx,
|
||||
'tx': self._total_tx,
|
||||
'types': self.data.get('types', {}), # Changed default from [] to {}
|
||||
'packet_count': len(self.data.get('packets', [])),
|
||||
'maxlen': self.maxlen,
|
||||
'packets': pkts,
|
||||
}
|
||||
return stats
|
||||
|
Loading…
x
Reference in New Issue
Block a user