diff --git a/aprsd/cmds/listen.py b/aprsd/cmds/listen.py
index 1dedd76..4a276fd 100644
--- a/aprsd/cmds/listen.py
+++ b/aprsd/cmds/listen.py
@@ -22,6 +22,7 @@ from aprsd.main import cli
from aprsd.packets import collector as packet_collector
from aprsd.packets import core, seen_list
from aprsd.packets import log as packet_log
+from aprsd.packets import packet_list
from aprsd.packets.filter import PacketFilter
from aprsd.packets.filters import dupe_filter, packet_type
from aprsd.stats import collector
@@ -68,7 +69,7 @@ class APRSDListenProcessThread(rx.APRSDFilterThread):
def print_packet(self, packet):
if self.log_packets:
- packet_log.log(packet)
+ packet_log.log(packet, force_log=True)
def process_packet(self, packet: type[core.Packet]):
if self.plugin_manager:
@@ -83,7 +84,7 @@ class ListenStatsThread(APRSDThread):
def __init__(self):
super().__init__('PacketStatsLog')
self._last_total_rx = 0
- self.period = 31
+ self.period = 10
self.start_time = time.time()
def loop(self):
@@ -96,18 +97,14 @@ class ListenStatsThread(APRSDThread):
rx_delta = total_rx - self._last_total_rx
rate = rx_delta / self.period
- # Get unique callsigns count from packets' from_call field
- unique_callsigns = set()
- if 'packets' in stats and stats['packets']:
- for packet in stats['packets']:
- # Handle both Packet objects and dicts (if serializable)
- if hasattr(packet, 'from_call'):
- if packet.from_call:
- unique_callsigns.add(packet.from_call)
- elif isinstance(packet, dict) and 'from_call' in packet:
- if packet['from_call']:
- unique_callsigns.add(packet['from_call'])
- unique_callsigns_count = len(unique_callsigns)
+ # Get unique callsigns count from SeenList stats
+ seen_list_instance = seen_list.SeenList()
+ seen_list_stats = seen_list_instance.stats()
+ seen_list_instance.save()
+ # we have to copy the seen_list_stats to avoid the lock being held too long
+ with seen_list_instance.lock:
+ seen_list_stats = seen_list_stats.copy()
+ unique_callsigns_count = len(seen_list_stats)
# Calculate uptime
elapsed = time.time() - self.start_time
@@ -119,7 +116,6 @@ class ListenStatsThread(APRSDThread):
f'RX Rate: {rate:.2f} pps '
f'Total RX: {total_rx} '
f'RX Last {self.period} secs: {rx_delta} '
- f'Packets in PacketListStats: {packet_count}',
)
LOGU.opt(colors=True).info(
f'Uptime: {elapsed:.0f}s ({elapsed_minutes:.1f}m / {elapsed_hours:.2f}h) '
@@ -150,6 +146,38 @@ class ListenStatsThread(APRSDThread):
f'({percentage_str})',
)
+ # Extract callsign counts from seen_list stats
+ callsign_counts = {}
+ for callsign, data in seen_list_stats.items():
+ if isinstance(data, dict) and 'count' in data:
+ callsign_counts[callsign] = data['count']
+
+ # Sort callsigns by packet count (descending) and get top 10
+ sorted_callsigns = sorted(
+ callsign_counts.items(), key=lambda x: x[1], reverse=True
+ )[:10]
+
+ # Log top 10 callsigns
+ if sorted_callsigns:
+ LOGU.opt(colors=True).info(
+ 'Top 10 Callsigns by Packet Count:'
+ )
+ total_ranks = len(sorted_callsigns)
+ for rank, (callsign, count) in enumerate(sorted_callsigns, 1):
+ # Use different colors based on rank: most packets (rank 1) = red,
+ # least packets (last rank) = green, middle = yellow
+ if rank == 1:
+ count_color_tag = 'red'
+ elif rank == total_ranks:
+ count_color_tag = 'green'
+ else:
+ count_color_tag = 'yellow'
+ LOGU.opt(colors=True).info(
+ f' {rank:2d}. '
+ f'{callsign:<12}: '
+ f'<{count_color_tag}>{count:6d} packets{count_color_tag}>',
+ )
+
time.sleep(1)
return True
@@ -292,10 +320,6 @@ def listen(
keepalive_thread = keepalive.KeepAliveThread()
- if not CONF.enable_seen_list:
- # just deregister the class from the packet collector
- packet_collector.PacketCollector().unregister(seen_list.SeenList)
-
# we don't want the dupe filter to run here.
PacketFilter().unregister(dupe_filter.DupePacketFilter)
if packet_filter:
@@ -326,6 +350,11 @@ def listen(
for p in pm.get_plugins():
LOG.info('Loaded plugin %s', p.__class__.__name__)
+ if log_packets:
+ LOG.info('Packet Logging is enabled')
+ else:
+ LOG.info('Packet Logging is disabled')
+
stats = stats_thread.APRSDStatsStoreThread()
stats.start()
diff --git a/aprsd/packets/log.py b/aprsd/packets/log.py
index bbee973..a48720d 100644
--- a/aprsd/packets/log.py
+++ b/aprsd/packets/log.py
@@ -90,8 +90,9 @@ def log(
tx: Optional[bool] = False,
header: Optional[bool] = True,
packet_count: Optional[int] = None,
+ force_log: Optional[bool] = False,
) -> None:
- if not CONF.enable_packet_logging:
+ if not CONF.enable_packet_logging and not force_log:
return
if CONF.log_packet_format == 'multiline':
log_multiline(packet, tx, header)