Refactor SSID metrics handling by removing Cisco client tracking and updating related functions for improved clarity and performance

This commit is contained in:
Yaro Kasear 2025-05-02 13:24:47 -05:00
parent 7d5fe1fbf5
commit 0fd16d47f3
5 changed files with 10 additions and 60 deletions

View file

@ -12,8 +12,6 @@ class IndexedCapture:
self.ssid_hidden_status = {} # SSID → hidden True/False
self.ssid_encryption_status = {} # SSID → open/encrypted
self.ssid_signals = defaultdict(list) # SSID → list of dBm values
self.cisco_ssid_clients = defaultdict(list) # SSID → list of (timestamp, client_count)
self.cisco_reported_clients = [] # list of all reported counts
self.ssid_packet_counts = defaultdict(int) # SSID → number of packets
self.ssid_clients = defaultdict(set) # SSID → MAC addresses
self.channel_to_aps = defaultdict(set) # Channel → BSSID
@ -84,7 +82,7 @@ class IndexedCapture:
privacy_bit = mgt._all_fields.get('wlan_mgt.fixed.capabilities.privacy')
is_open = (str(privacy_bit) != '1')
# First: extract SSID and Cisco client info independently
# First: extract SSID client info independently
for tag in tags:
tag_number = tag.get('wlan.tag.number')
@ -100,12 +98,6 @@ class IndexedCapture:
except Exception:
ssid = None
if tag_number == '133':
try:
num_clients = int(tag.get('wlan.cisco.ccx1.clients'))
except (TypeError, ValueError):
num_clients = None
# Now that we have them parsed, update structures
if ssid:
self.ssid_hidden_status[ssid] = hidden_ssid
@ -114,8 +106,6 @@ class IndexedCapture:
if num_clients is not None:
timestamp = float(packet.frame_info.time_epoch)
self.cisco_ssid_clients[ssid].append((timestamp, num_clients))
self.cisco_reported_clients.append(num_clients)
bssid = getattr(wlan, 'bssid', '').lower()
if not bssid or bssid == 'ff:ff:ff:ff:ff:ff':
@ -208,14 +198,14 @@ class IndexedCapture:
clients_on_channel = len(window_clients.get(ap_channel, []))
aps_on_channel = len(window_aps.get(ap_channel, []))
avg_ap_signal = mean(window_signals[ap_channel]) if window_signals.get(ap_channel) else 0
avg_ap_signal = safe_mean(window_signals[ap_channel])
max_ap_signal = max(window_signals[ap_channel]) if window_signals.get(ap_channel) else 0
unlinked_devices = self._count_unlinked_devices(packets, ap_channel)
our_ssid = self.bssid_to_ssid.get(ap_bssid)
num_bssids = len(window_ssid_to_bssids.get(our_ssid, [])) if our_ssid else 0
avg_ssid_signal = mean(window_ssid_signals.get(our_ssid, [])) if our_ssid else 0
avg_ssid_signal = safe_mean(window_ssid_signals.get(our_ssid, []))
max_ssid_signal = max(window_ssid_signals.get(our_ssid, [])) if our_ssid else 0
num_channels_ssid = len({self._channel_of_bssid(b) for b in window_ssid_to_bssids.get(our_ssid, [])}) if our_ssid else 0
packet_count = len(packets)
@ -223,8 +213,6 @@ class IndexedCapture:
return (
clients_on_ap, clients_on_channel, aps_on_channel,
avg_ap_signal, max_ap_signal, unlinked_devices,
self._cisco_avg_clients(our_ssid, start_ts, end_ts),
self._cisco_max_clients(our_ssid, start_ts, end_ts),
num_bssids, avg_ssid_signal, max_ssid_signal,
num_channels_ssid, packet_count
)
@ -293,26 +281,12 @@ class IndexedCapture:
continue
return len(ghost_candidates)
def _cisco_avg_clients(self, ssid, start_ts, end_ts):
if ssid not in self.cisco_ssid_clients:
return 0
hits = []
for ts, count in self.cisco_ssid_clients[ssid]:
if start_ts <= ts <= end_ts:
hits.append(count)
return round(mean(hits), 2) if hits else 0
def _cisco_max_clients(self, ssid, start_ts, end_ts):
if ssid not in self.cisco_ssid_clients:
return 0
windowed = [count for ts, count in self.cisco_ssid_clients[ssid] if start_ts <= ts <= end_ts]
return max(windowed) if windowed else 0
def _channel_of_bssid(self, bssid):
for channel, bssids in self.channel_to_aps.items():
if bssid in bssids:
return channel
return None
def safe_mean(data):
return mean(data) if data else 0