From 32c92f20276381ea9a8cc5b65522d45463ea7dfe Mon Sep 17 00:00:00 2001 From: jedarden Date: Tue, 7 Apr 2026 07:23:30 -0400 Subject: [PATCH] feat: broadcast ble_scan messages to dashboard every 5s Add a 5-second ticker in the dashboard hub that broadcasts BLE device list updates as typed 'ble_scan' messages when devices are present. The BroadcastBLEScan method and frontend handler already existed but were never wired up to a periodic timer. Co-Authored-By: Claude Opus 4.6 --- mothership/internal/dashboard/hub.go | 30 +++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/mothership/internal/dashboard/hub.go b/mothership/internal/dashboard/hub.go index 0e32851..6f4cb5e 100644 --- a/mothership/internal/dashboard/hub.go +++ b/mothership/internal/dashboard/hub.go @@ -156,9 +156,9 @@ func (h *Hub) SetZoneState(state ZoneStateProvider) { } // Run starts the hub's main loop. -// The 10 Hz delta tick replaces the old 5 s state / 500 ms presence / -// 5 s BLE periodic broadcasts. System health (60 s) is kept as a -// separate low-frequency broadcast. +// The 10 Hz delta tick replaces the old 5 s state / 500 ms presence broadcasts. +// BLE scan results are broadcast every 5 s as a separate typed message. +// System health (60 s) is kept as a separate low-frequency broadcast. func (h *Hub) Run() { // 10 Hz snapshot/delta tick deltaTicker := time.NewTicker(100 * time.Millisecond) @@ -168,6 +168,10 @@ func (h *Hub) Run() { healthTicker := time.NewTicker(60 * time.Second) defer healthTicker.Stop() + // BLE scan broadcast ticker (5 seconds) + bleScanTicker := time.NewTicker(5 * time.Second) + defer bleScanTicker.Stop() + for { select { case client := <-h.register: @@ -216,6 +220,9 @@ func (h *Hub) Run() { case <-healthTicker.C: h.broadcastSystemHealth() + + case <-bleScanTicker.C: + h.broadcastBLEScan() } } } @@ -690,6 +697,23 @@ func (h *Hub) broadcastSystemHealth() { ) } +// broadcastBLEScan broadcasts the current BLE device list to all dashboard clients. +// Called every 5 seconds when devices are present. +func (h *Hub) broadcastBLEScan() { + h.mu.RLock() + ble := h.bleState + clientCount := len(h.clients) + h.mu.RUnlock() + + if ble == nil || clientCount == 0 { + return + } + + if devices := ble.GetCurrentDevices(); len(devices) > 0 { + h.BroadcastBLEScan(devices) + } +} + // BroadcastFleetChange broadcasts a fleet change event to all dashboard clients. // This implements the fleet.FleetChangeBroadcaster interface. func (h *Hub) BroadcastFleetChange(event fleet.FleetChangeEvent) {