Add websocket wifi updates
This commit is contained in:
parent
c443fce24f
commit
1477d909b0
11 changed files with 755 additions and 10 deletions
223
internal/wifi/iwd/signals.go
Normal file
223
internal/wifi/iwd/signals.go
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
package iwd
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
// SignalMonitor monitors D-Bus signals from iwd
|
||||
type SignalMonitor struct {
|
||||
conn *dbus.Conn
|
||||
station *Station
|
||||
|
||||
// Signal channel
|
||||
signalChan chan *dbus.Signal
|
||||
|
||||
// Callbacks
|
||||
onStateChange func(state StationState, ssid string)
|
||||
onScanComplete func()
|
||||
|
||||
// Control
|
||||
stopChan chan struct{}
|
||||
mu sync.RWMutex
|
||||
running bool
|
||||
|
||||
// State tracking
|
||||
lastScanning bool
|
||||
}
|
||||
|
||||
// NewSignalMonitor creates a new signal monitor
|
||||
func NewSignalMonitor(conn *dbus.Conn, station *Station) *SignalMonitor {
|
||||
return &SignalMonitor{
|
||||
conn: conn,
|
||||
station: station,
|
||||
signalChan: make(chan *dbus.Signal, 100),
|
||||
stopChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// OnStateChange registers a callback for state changes
|
||||
func (sm *SignalMonitor) OnStateChange(callback func(state StationState, ssid string)) {
|
||||
sm.mu.Lock()
|
||||
defer sm.mu.Unlock()
|
||||
sm.onStateChange = callback
|
||||
}
|
||||
|
||||
// OnScanComplete registers a callback for scan completion
|
||||
func (sm *SignalMonitor) OnScanComplete(callback func()) {
|
||||
sm.mu.Lock()
|
||||
defer sm.mu.Unlock()
|
||||
sm.onScanComplete = callback
|
||||
}
|
||||
|
||||
// Start begins monitoring D-Bus signals
|
||||
func (sm *SignalMonitor) Start() error {
|
||||
sm.mu.Lock()
|
||||
if sm.running {
|
||||
sm.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
sm.running = true
|
||||
sm.mu.Unlock()
|
||||
|
||||
// Subscribe to PropertiesChanged signals for Station interface
|
||||
stationPath := sm.station.GetPath()
|
||||
|
||||
// Add signal match for PropertiesChanged on Station interface
|
||||
matchOptions := []dbus.MatchOption{
|
||||
dbus.WithMatchObjectPath(stationPath),
|
||||
dbus.WithMatchInterface("org.freedesktop.DBus.Properties"),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
}
|
||||
|
||||
if err := sm.conn.AddMatchSignal(matchOptions...); err != nil {
|
||||
sm.mu.Lock()
|
||||
sm.running = false
|
||||
sm.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Register signal channel
|
||||
sm.conn.Signal(sm.signalChan)
|
||||
|
||||
// Get initial scanning state
|
||||
scanning, err := sm.station.IsScanning()
|
||||
if err == nil {
|
||||
sm.lastScanning = scanning
|
||||
}
|
||||
|
||||
// Start monitoring goroutine
|
||||
go sm.monitor()
|
||||
|
||||
log.Printf("D-Bus signal monitoring started for station %s", stationPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops monitoring D-Bus signals
|
||||
func (sm *SignalMonitor) Stop() {
|
||||
sm.mu.Lock()
|
||||
if !sm.running {
|
||||
sm.mu.Unlock()
|
||||
return
|
||||
}
|
||||
sm.running = false
|
||||
sm.mu.Unlock()
|
||||
|
||||
// Signal stop
|
||||
close(sm.stopChan)
|
||||
|
||||
// Remove signal channel
|
||||
sm.conn.RemoveSignal(sm.signalChan)
|
||||
|
||||
log.Printf("D-Bus signal monitoring stopped")
|
||||
}
|
||||
|
||||
// monitor is the main signal processing loop
|
||||
func (sm *SignalMonitor) monitor() {
|
||||
for {
|
||||
select {
|
||||
case sig := <-sm.signalChan:
|
||||
sm.handleSignal(sig)
|
||||
case <-sm.stopChan:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleSignal processes a D-Bus signal
|
||||
func (sm *SignalMonitor) handleSignal(sig *dbus.Signal) {
|
||||
// Only process PropertiesChanged signals
|
||||
if sig.Name != "org.freedesktop.DBus.Properties.PropertiesChanged" {
|
||||
return
|
||||
}
|
||||
|
||||
// Verify signal is from Station interface
|
||||
if len(sig.Body) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
interfaceName, ok := sig.Body[0].(string)
|
||||
if !ok || interfaceName != StationInterface {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse changed properties
|
||||
changedProps, ok := sig.Body[1].(map[string]dbus.Variant)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for State property change
|
||||
if stateVariant, ok := changedProps["State"]; ok {
|
||||
if state, ok := stateVariant.Value().(string); ok {
|
||||
sm.handleStateChange(StationState(state))
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Scanning property change
|
||||
if scanningVariant, ok := changedProps["Scanning"]; ok {
|
||||
if scanning, ok := scanningVariant.Value().(bool); ok {
|
||||
sm.handleScanningChange(scanning)
|
||||
}
|
||||
}
|
||||
|
||||
// Check for ConnectedNetwork property change
|
||||
if _, ok := changedProps["ConnectedNetwork"]; ok {
|
||||
// Network connection changed, trigger state update
|
||||
sm.handleConnectionChange()
|
||||
}
|
||||
}
|
||||
|
||||
// handleStateChange processes a state change
|
||||
func (sm *SignalMonitor) handleStateChange(state StationState) {
|
||||
sm.mu.RLock()
|
||||
callback := sm.onStateChange
|
||||
sm.mu.RUnlock()
|
||||
|
||||
if callback == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get connected SSID if connected
|
||||
ssid := ""
|
||||
if state == StateConnected {
|
||||
network, err := sm.station.GetConnectedNetwork()
|
||||
if err == nil {
|
||||
props, err := network.GetProperties()
|
||||
if err == nil {
|
||||
ssid = props.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback(state, ssid)
|
||||
}
|
||||
|
||||
// handleScanningChange processes scanning state changes
|
||||
func (sm *SignalMonitor) handleScanningChange(scanning bool) {
|
||||
// Detect scan completion (transition from true to false)
|
||||
if sm.lastScanning && !scanning {
|
||||
sm.mu.RLock()
|
||||
callback := sm.onScanComplete
|
||||
sm.mu.RUnlock()
|
||||
|
||||
if callback != nil {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
sm.lastScanning = scanning
|
||||
}
|
||||
|
||||
// handleConnectionChange processes connection changes
|
||||
func (sm *SignalMonitor) handleConnectionChange() {
|
||||
// Get current state and trigger state change callback
|
||||
state, err := sm.station.GetState()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sm.handleStateChange(state)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue