diff --git a/enrichment/indexed_capture.py b/enrichment/indexed_capture.py index ccb7bdc..6564895 100644 --- a/enrichment/indexed_capture.py +++ b/enrichment/indexed_capture.py @@ -12,7 +12,7 @@ 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 → client counts + 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 @@ -98,9 +98,11 @@ class IndexedCapture: if tag.get('wlan.tag.number') == '133': try: num_clients = int(tag.get('wlan.cisco.ccx1.clients')) + timestamp = float(packet.frame_info.time_epoch) if ssid: - self.cisco_ssid_clients[ssid].append(num_clients) + self.cisco_ssid_clients[ssid].append((timestamp, num_clients)) self.cisco_reported_clients.append(num_clients) + print(f"[DEBUG] Indexed {len(self.cisco_reported_clients)} Cisco client reports.") except (TypeError, ValueError): pass @@ -188,9 +190,6 @@ class IndexedCapture: if signal: window_ssid_signals[ssid].append(int(signal)) - if channel == ap_channel: - print(f"[DEBUG] [AP] Adding bssid={bssid} to window_aps[{channel}]") - # Track signals signal = getattr(radio, 'dbm_antsignal', None) if signal: @@ -218,12 +217,12 @@ 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), self._cisco_max_clients(our_ssid), + 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 ) - def _count_clients_on_ap(self, packets, ap_bssid): clients = defaultdict(int) ap_bssid = ap_bssid.lower() @@ -289,20 +288,20 @@ class IndexedCapture: return len(ghost_candidates) + def _cisco_avg_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 round(mean(windowed), 2) if windowed else 0 - def _cisco_avg_clients(self, ssid): - if ssid in self.cisco_ssid_clients: - return round(mean(self.cisco_ssid_clients[ssid]), 2) - return 0 - - def _cisco_max_clients(self, ssid): - if ssid in self.cisco_ssid_clients: - return max(self.cisco_ssid_clients[ssid]) - return 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 - \ No newline at end of file