net_alerter: Add Strategy 0 MAC deduplication and fix Strategy 3 overwrite bug
Strategy 0 now checks if a MAC already exists in any identity's wifi_macs/ble_macs sets before creating a new record. Prevents duplicate identity creation on repeated mDNS/ARP signals. Strategy 3 now conditionally updates existing records instead of unconditionally overwriting them. Preserves signal_count and signal_types accumulation needed for auto-enrollment (2+ signal types). Fixes issue where devices seen only via mDNS/ARP never reached enrollment threshold.
This commit is contained in:
+50
-15
@@ -186,6 +186,7 @@ def _correlate_or_create_identity(mac: str, signal_type: str, dhcp_fp: str = "",
|
||||
signal_type: "ble", "dhcp", "arp", or "mdns"
|
||||
|
||||
Lookup strategy:
|
||||
0. Check if MAC already exists in any identity's MAC sets
|
||||
1. If handoff_seq provided, look for matching BLE handoff seq anchor
|
||||
2. If dhcp_fp provided, look for matching DHCP fingerprint
|
||||
3. If neither, create new provisional identity
|
||||
@@ -196,6 +197,18 @@ def _correlate_or_create_identity(mac: str, signal_type: str, dhcp_fp: str = "",
|
||||
# Determine signal category: 'ble' or 'wifi' (for dhcp/arp/mdns)
|
||||
signal_category = 'ble' if signal_type == 'ble' else 'wifi'
|
||||
|
||||
# Strategy 0: Check if MAC already exists in any identity
|
||||
for iid, dev in device_store.items():
|
||||
if mac in dev['wifi_macs'] or mac in dev['ble_macs']:
|
||||
# Found existing identity for this MAC — update instead of creating new
|
||||
dev['last_seen'][mac] = time.time()
|
||||
dev['signal_types'].add(signal_category)
|
||||
logging.debug(f"MAC {mac} already linked to identity {iid}, updated {signal_category} signal")
|
||||
# Check if meets enrollment criteria (2+ signal types)
|
||||
if len(dev['signal_types']) >= 2 and not dev['enrolled']:
|
||||
_fire_enrollment_callback(iid)
|
||||
return iid
|
||||
|
||||
# Strategy 1: Match by BLE Handoff sequence (most stable)
|
||||
if handoff_seq is not None:
|
||||
for iid, dev in device_store.items():
|
||||
@@ -232,23 +245,45 @@ def _correlate_or_create_identity(mac: str, signal_type: str, dhcp_fp: str = "",
|
||||
# Provisional identity based on first MAC seen
|
||||
identity_id = f"prov:{mac}"
|
||||
|
||||
dev = _create_identity_record(identity_id)
|
||||
|
||||
# Add initial signal
|
||||
if signal_type == "ble":
|
||||
dev['ble_macs'].add(mac)
|
||||
if handoff_seq is not None:
|
||||
dev['handoff_seq'] = handoff_seq
|
||||
dev['signal_types'].add('ble')
|
||||
# Check if this identity already exists (e.g., multiple mDNS/ARP signals for same MAC)
|
||||
if identity_id in device_store:
|
||||
dev = device_store[identity_id]
|
||||
# Update existing record instead of overwriting
|
||||
if signal_type == "ble":
|
||||
dev['ble_macs'].add(mac)
|
||||
if handoff_seq is not None:
|
||||
dev['handoff_seq'] = handoff_seq
|
||||
dev['signal_types'].add('ble')
|
||||
else:
|
||||
dev['wifi_macs'].add(mac)
|
||||
if dhcp_fp:
|
||||
dev['dhcp_fingerprint'] = dhcp_fp
|
||||
dev['signal_types'].add('wifi')
|
||||
dev['last_seen'][mac] = time.time()
|
||||
# Check if meets enrollment criteria (2+ signal types)
|
||||
if len(dev['signal_types']) >= 2 and not dev['enrolled']:
|
||||
_fire_enrollment_callback(identity_id)
|
||||
logging.debug(f"Updated device identity {identity_id} with {signal_type} signal (MAC: {mac})")
|
||||
else:
|
||||
dev['wifi_macs'].add(mac)
|
||||
if dhcp_fp:
|
||||
dev['dhcp_fingerprint'] = dhcp_fp
|
||||
dev['signal_types'].add('wifi')
|
||||
# Create new identity
|
||||
dev = _create_identity_record(identity_id)
|
||||
|
||||
# Add initial signal
|
||||
if signal_type == "ble":
|
||||
dev['ble_macs'].add(mac)
|
||||
if handoff_seq is not None:
|
||||
dev['handoff_seq'] = handoff_seq
|
||||
dev['signal_types'].add('ble')
|
||||
else:
|
||||
dev['wifi_macs'].add(mac)
|
||||
if dhcp_fp:
|
||||
dev['dhcp_fingerprint'] = dhcp_fp
|
||||
dev['signal_types'].add('wifi')
|
||||
|
||||
dev['last_seen'][mac] = time.time()
|
||||
device_store[identity_id] = dev
|
||||
logging.debug(f"Created new device identity {identity_id} from {signal_type} signal")
|
||||
|
||||
dev['last_seen'][mac] = time.time()
|
||||
device_store[identity_id] = dev
|
||||
logging.debug(f"Created new device identity {identity_id} from {signal_type} signal")
|
||||
return identity_id
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user