Add websocket wifi updates
This commit is contained in:
parent
c443fce24f
commit
1477d909b0
11 changed files with 755 additions and 10 deletions
140
internal/wifi/broadcaster.go
Normal file
140
internal/wifi/broadcaster.go
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
package wifi
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/nemunaire/repeater/internal/models"
|
||||
)
|
||||
|
||||
// WifiBroadcaster manages WebSocket clients and broadcasts WiFi events
|
||||
type WifiBroadcaster struct {
|
||||
clients map[*websocket.Conn]bool
|
||||
clientsMu sync.RWMutex
|
||||
|
||||
// State deduplication
|
||||
lastState string
|
||||
lastSSID string
|
||||
lastNetworks []models.WiFiNetwork
|
||||
stateMu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewWifiBroadcaster creates a new WiFi broadcaster
|
||||
func NewWifiBroadcaster() *WifiBroadcaster {
|
||||
return &WifiBroadcaster{
|
||||
clients: make(map[*websocket.Conn]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterClient registers a new WebSocket client
|
||||
func (wb *WifiBroadcaster) RegisterClient(conn *websocket.Conn) {
|
||||
wb.clientsMu.Lock()
|
||||
wb.clients[conn] = true
|
||||
wb.clientsMu.Unlock()
|
||||
|
||||
// Send initial state to the new client
|
||||
wb.sendInitialState(conn)
|
||||
}
|
||||
|
||||
// UnregisterClient removes a WebSocket client
|
||||
func (wb *WifiBroadcaster) UnregisterClient(conn *websocket.Conn) {
|
||||
wb.clientsMu.Lock()
|
||||
delete(wb.clients, conn)
|
||||
wb.clientsMu.Unlock()
|
||||
}
|
||||
|
||||
// sendInitialState sends the current WiFi state to a newly connected client
|
||||
func (wb *WifiBroadcaster) sendInitialState(conn *websocket.Conn) {
|
||||
wb.stateMu.RLock()
|
||||
lastState := wb.lastState
|
||||
lastSSID := wb.lastSSID
|
||||
lastNetworks := make([]models.WiFiNetwork, len(wb.lastNetworks))
|
||||
copy(lastNetworks, wb.lastNetworks)
|
||||
wb.stateMu.RUnlock()
|
||||
|
||||
// Send last known state if available
|
||||
if lastState != "" {
|
||||
event := NewStateChangeEvent(lastState, lastSSID, "")
|
||||
conn.WriteJSON(event)
|
||||
}
|
||||
|
||||
// Send last known network list if available
|
||||
if len(lastNetworks) > 0 {
|
||||
event := NewScanUpdateEvent(lastNetworks)
|
||||
conn.WriteJSON(event)
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastScanUpdate broadcasts a scan update event to all clients
|
||||
func (wb *WifiBroadcaster) BroadcastScanUpdate(networks []models.WiFiNetwork) {
|
||||
// Check for changes to avoid duplicate broadcasts
|
||||
wb.stateMu.Lock()
|
||||
if networksEqual(wb.lastNetworks, networks) {
|
||||
wb.stateMu.Unlock()
|
||||
return
|
||||
}
|
||||
wb.lastNetworks = make([]models.WiFiNetwork, len(networks))
|
||||
copy(wb.lastNetworks, networks)
|
||||
wb.stateMu.Unlock()
|
||||
|
||||
event := NewScanUpdateEvent(networks)
|
||||
wb.broadcast(event)
|
||||
}
|
||||
|
||||
// BroadcastStateChange broadcasts a state change event to all clients
|
||||
func (wb *WifiBroadcaster) BroadcastStateChange(state, ssid string) {
|
||||
// Check for changes to avoid duplicate broadcasts
|
||||
wb.stateMu.Lock()
|
||||
if wb.lastState == state && wb.lastSSID == ssid {
|
||||
wb.stateMu.Unlock()
|
||||
return
|
||||
}
|
||||
previousState := wb.lastState
|
||||
wb.lastState = state
|
||||
wb.lastSSID = ssid
|
||||
wb.stateMu.Unlock()
|
||||
|
||||
event := NewStateChangeEvent(state, ssid, previousState)
|
||||
wb.broadcast(event)
|
||||
}
|
||||
|
||||
// BroadcastSignalUpdate broadcasts a signal update event to all clients
|
||||
func (wb *WifiBroadcaster) BroadcastSignalUpdate(ssid string, signal, dbm int) {
|
||||
event := NewSignalUpdateEvent(ssid, signal, dbm)
|
||||
wb.broadcast(event)
|
||||
}
|
||||
|
||||
// broadcast sends an event to all connected clients
|
||||
func (wb *WifiBroadcaster) broadcast(event WifiEvent) {
|
||||
// Get list of clients with read lock
|
||||
wb.clientsMu.RLock()
|
||||
clients := make([]*websocket.Conn, 0, len(wb.clients))
|
||||
for client := range wb.clients {
|
||||
clients = append(clients, client)
|
||||
}
|
||||
wb.clientsMu.RUnlock()
|
||||
|
||||
// Broadcast to all clients
|
||||
for _, client := range clients {
|
||||
err := client.WriteJSON(event)
|
||||
if err != nil {
|
||||
log.Printf("Erreur lors de l'envoi WebSocket WiFi: %v", err)
|
||||
client.Close()
|
||||
wb.UnregisterClient(client)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// networksEqual compares two network slices for equality
|
||||
func networksEqual(a, b []models.WiFiNetwork) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i].SSID != b[i].SSID || a[i].Signal != b[i].Signal {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue