Fix ARRIVED spam — mark departing instead of popping from known_devices
When on_departure popped the device from known_devices, rapid RTM_NEWNEIGH events during ARP cache rebuild each triggered on_arrival as if the device was brand new, flooding the Matrix room with 5-10+ duplicate ARRIVED alerts. Fix: keep device in known_devices with departing=True flag. on_arrival silently cancels pending departure timers and returns without alerting when it sees this flag. Timer callback checks flag before sending the alert and only pops the device when departure is confirmed after 15 minutes.
This commit is contained in:
@@ -421,6 +421,19 @@ def on_arrival(mac: str, ip: str, hostname: str = "") -> None:
|
||||
hostname = hostname or ip
|
||||
now = time.time()
|
||||
|
||||
# Silent re-arrival if device marked departing (rapid flap recovery)
|
||||
with departure_lock:
|
||||
if mac in known_devices and known_devices[mac].get('departing'):
|
||||
# Device returned during departure window — cancel timer, clear flag, no alert
|
||||
if mac in departure_timers:
|
||||
departure_timers[mac].cancel()
|
||||
del departure_timers[mac]
|
||||
with known_lock:
|
||||
known_devices[mac]['departing'] = False
|
||||
last_departed_time.pop(mac, None)
|
||||
logging.debug(f"Device {mac} re-arrived during departure window — suppressed alert")
|
||||
return
|
||||
|
||||
# Check re-arrival suppression BEFORE acquiring lock (avoid nested locks)
|
||||
with departure_lock:
|
||||
# ALWAYS cancel any pending departure timer when device re-arrives
|
||||
@@ -493,7 +506,8 @@ def on_departure(mac: str) -> None:
|
||||
return
|
||||
|
||||
dev_copy = dev.copy()
|
||||
known_devices.pop(mac)
|
||||
# Mark departing instead of popping — allows re-arrival to detect and cancel timer
|
||||
known_devices[mac]['departing'] = True
|
||||
|
||||
# Start 15-minute debounce timer
|
||||
with departure_lock:
|
||||
@@ -503,6 +517,13 @@ def on_departure(mac: str) -> None:
|
||||
|
||||
def send_departure_alert():
|
||||
"""Callback to send alert after debounce expires."""
|
||||
# Check if device re-arrived (departing flag cleared by on_arrival)
|
||||
with known_lock:
|
||||
if not known_devices.get(mac, {}).get('departing'):
|
||||
return # device re-arrived, departure was cancelled
|
||||
# Device still departed — send alert and remove from tracking
|
||||
known_devices.pop(mac, None)
|
||||
|
||||
duration = fmt_duration(time.time() - dev_copy['first_seen'])
|
||||
msg = format_departure(dev_copy['hostname'], dev_copy['ip'], dev_copy['vendor'] or "unknown", mac, duration)
|
||||
logging.info(msg)
|
||||
|
||||
Reference in New Issue
Block a user