feat: process buffered events from delta WebSocket updates

Events (zone entries/exits, portal crossings, presence transitions)
were already broadcast immediately via BroadcastEvent, but the
buffered copies included in the 10 Hz delta tick were silently
dropped by handleIncrementalUpdate. Now delta events are processed
through the same handleEventMessage path, with dedup to avoid
double-processing when both immediate and delta copies arrive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-04-07 11:03:52 -04:00
parent c77bf42178
commit 97f1eafc6f

View file

@ -58,7 +58,11 @@
bleDevices: new Map(), // MAC -> { mac, name, rssi, last_seen, label, blob_id }
// Alert tracking
alerts: new Map(), // id -> { id, ts, severity, description, acknowledged }
unacknowledgedCount: 0
unacknowledgedCount: 0,
// Event dedup: set of recently processed event IDs to avoid double-processing
// from immediate broadcast + delta buffering
recentEventIDs: new Set(),
recentEventIDsPruneAt: 0
};
// ============================================
@ -431,6 +435,19 @@
if (!msg.event) return;
const event = msg.event;
// Dedup: skip if we already processed this event (from immediate broadcast or prior delta)
const eid = String(event.id);
if (state.recentEventIDs.has(eid)) return;
state.recentEventIDs.add(eid);
// Prune old IDs every 30 seconds to prevent unbounded growth
const now = Date.now();
if (now > state.recentEventIDsPruneAt) {
state.recentEventIDs.clear();
state.recentEventIDsPruneAt = now + 30000;
}
console.log('[Spaxel] Event:', event.kind, 'in', event.zone, 'by', event.person_name || 'blob #' + event.blob_id);
// Log to timeline
@ -900,6 +917,13 @@
Viz3D.handleZoneUpdate(msg.zones);
}
}
// Events buffered since last tick (presence transitions, zone entries/exits, portal crossings)
if (msg.events && Array.isArray(msg.events)) {
msg.events.forEach(function (evt) {
handleEventMessage({ type: 'event', event: evt });
});
}
}
// applyMotionState updates a link's motion fields; returns true if it changed.