242 lines
6 KiB
Go
242 lines
6 KiB
Go
package wifi
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gorilla/websocket"
|
|
"github.com/nemunaire/repeater/internal/models"
|
|
"github.com/nemunaire/repeater/internal/wifi/backend"
|
|
)
|
|
|
|
var (
|
|
wifiBackend backend.WiFiBackend
|
|
wifiBroadcaster *WifiBroadcaster
|
|
)
|
|
|
|
// Initialize initializes the WiFi service with the specified backend
|
|
func Initialize(interfaceName string, backendName string) error {
|
|
// Create the appropriate backend using the factory
|
|
var err error
|
|
wifiBackend, err = createBackend(backendName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Initialize the backend
|
|
return wifiBackend.Initialize(interfaceName)
|
|
}
|
|
|
|
// Close closes the backend connection
|
|
func Close() {
|
|
if wifiBackend != nil {
|
|
wifiBackend.Close()
|
|
}
|
|
}
|
|
|
|
// GetCachedNetworks returns previously discovered networks without triggering a scan
|
|
func GetCachedNetworks() ([]models.WiFiNetwork, error) {
|
|
// Get ordered networks from backend
|
|
backendNetworks, err := wifiBackend.GetOrderedNetworks()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("erreur lors de la récupération des réseaux: %v", err)
|
|
}
|
|
|
|
// Convert backend networks to models
|
|
networks := make([]models.WiFiNetwork, 0, len(backendNetworks))
|
|
for _, backendNet := range backendNetworks {
|
|
wifiNet := models.WiFiNetwork{
|
|
SSID: backendNet.SSID,
|
|
Signal: signalToStrength(int(backendNet.SignalDBm)),
|
|
Security: mapSecurityType(backendNet.SecurityType),
|
|
BSSID: backendNet.BSSID,
|
|
Channel: 0, // Not yet exposed by backends
|
|
}
|
|
networks = append(networks, wifiNet)
|
|
}
|
|
|
|
// Sort by signal strength (descending)
|
|
sort.Slice(networks, func(i, j int) bool {
|
|
return networks[i].Signal > networks[j].Signal
|
|
})
|
|
|
|
return networks, nil
|
|
}
|
|
|
|
// ScanNetworks scans for available WiFi networks
|
|
func ScanNetworks() ([]models.WiFiNetwork, error) {
|
|
// Check if already scanning
|
|
scanning, err := wifiBackend.IsScanning()
|
|
if err == nil && scanning {
|
|
time.Sleep(3 * time.Second)
|
|
} else {
|
|
// Trigger scan
|
|
err := wifiBackend.ScanNetworks()
|
|
if err != nil && !strings.Contains(err.Error(), "rejected") {
|
|
return nil, fmt.Errorf("erreur lors du scan: %v", err)
|
|
}
|
|
time.Sleep(2 * time.Second)
|
|
}
|
|
|
|
// Get ordered networks from backend
|
|
backendNetworks, err := wifiBackend.GetOrderedNetworks()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("erreur lors de la récupération des réseaux: %v", err)
|
|
}
|
|
|
|
// Convert backend networks to models
|
|
networks := make([]models.WiFiNetwork, 0, len(backendNetworks))
|
|
for _, backendNet := range backendNetworks {
|
|
wifiNet := models.WiFiNetwork{
|
|
SSID: backendNet.SSID,
|
|
Signal: signalToStrength(int(backendNet.SignalDBm)),
|
|
Security: mapSecurityType(backendNet.SecurityType),
|
|
BSSID: backendNet.BSSID,
|
|
Channel: 0, // Not yet exposed by backends
|
|
}
|
|
networks = append(networks, wifiNet)
|
|
}
|
|
|
|
// Sort by signal strength (descending)
|
|
sort.Slice(networks, func(i, j int) bool {
|
|
return networks[i].Signal > networks[j].Signal
|
|
})
|
|
|
|
// Broadcast to WebSocket clients if available
|
|
if wifiBroadcaster != nil {
|
|
wifiBroadcaster.BroadcastScanUpdate(networks)
|
|
}
|
|
|
|
return networks, nil
|
|
}
|
|
|
|
// Connect connects to a WiFi network
|
|
func Connect(ssid, password string) error {
|
|
// Use backend to connect
|
|
if err := wifiBackend.Connect(ssid, password); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Poll for connection
|
|
for i := 0; i < 20; i++ {
|
|
time.Sleep(500 * time.Millisecond)
|
|
if IsConnected() {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("timeout lors de la connexion")
|
|
}
|
|
|
|
// Disconnect disconnects from the current WiFi network
|
|
func Disconnect() error {
|
|
return wifiBackend.Disconnect()
|
|
}
|
|
|
|
// IsConnected checks if WiFi is connected
|
|
func IsConnected() bool {
|
|
state, err := wifiBackend.GetConnectionState()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return state == backend.StateConnected
|
|
}
|
|
|
|
// GetConnectedSSID returns the SSID of the currently connected network
|
|
func GetConnectedSSID() string {
|
|
return wifiBackend.GetConnectedSSID()
|
|
}
|
|
|
|
// GetConnectionState returns the current WiFi connection state
|
|
func GetConnectionState() string {
|
|
state, err := wifiBackend.GetConnectionState()
|
|
if err != nil {
|
|
return string(backend.StateDisconnected)
|
|
}
|
|
return string(state)
|
|
}
|
|
|
|
// StartEventMonitoring initializes signal monitoring and WebSocket broadcasting
|
|
func StartEventMonitoring() error {
|
|
// Initialize broadcaster
|
|
wifiBroadcaster = NewWifiBroadcaster()
|
|
|
|
// Set up callbacks
|
|
callbacks := backend.EventCallbacks{
|
|
OnStateChange: handleStateChange,
|
|
OnScanComplete: handleScanComplete,
|
|
}
|
|
|
|
// Start backend monitoring
|
|
return wifiBackend.StartEventMonitoring(callbacks)
|
|
}
|
|
|
|
// StopEventMonitoring stops signal monitoring
|
|
func StopEventMonitoring() {
|
|
if wifiBackend != nil {
|
|
wifiBackend.StopEventMonitoring()
|
|
}
|
|
}
|
|
|
|
// RegisterWebSocketClient registers a new WebSocket client for WiFi events
|
|
func RegisterWebSocketClient(conn *websocket.Conn) {
|
|
if wifiBroadcaster != nil {
|
|
wifiBroadcaster.RegisterClient(conn)
|
|
}
|
|
}
|
|
|
|
// UnregisterWebSocketClient removes a WebSocket client
|
|
func UnregisterWebSocketClient(conn *websocket.Conn) {
|
|
if wifiBroadcaster != nil {
|
|
wifiBroadcaster.UnregisterClient(conn)
|
|
}
|
|
}
|
|
|
|
// handleStateChange is called when WiFi connection state changes
|
|
func handleStateChange(newState backend.ConnectionState, connectedSSID string) {
|
|
if wifiBroadcaster != nil {
|
|
wifiBroadcaster.BroadcastStateChange(string(newState), connectedSSID)
|
|
}
|
|
}
|
|
|
|
// handleScanComplete is called when a WiFi scan completes
|
|
func handleScanComplete() {
|
|
// Get updated network list
|
|
networks, err := GetCachedNetworks()
|
|
if err == nil && wifiBroadcaster != nil {
|
|
wifiBroadcaster.BroadcastScanUpdate(networks)
|
|
}
|
|
}
|
|
|
|
// mapSecurityType maps backend security types to display format
|
|
func mapSecurityType(securityType string) string {
|
|
switch securityType {
|
|
case "open":
|
|
return "Open"
|
|
case "wep":
|
|
return "WEP"
|
|
case "psk":
|
|
return "WPA2"
|
|
case "8021x":
|
|
return "WPA2"
|
|
default:
|
|
return "WPA2"
|
|
}
|
|
}
|
|
|
|
// signalToStrength converts signal level (dBm) to strength (1-5)
|
|
func signalToStrength(level int) int {
|
|
if level >= -30 {
|
|
return 5
|
|
} else if level >= -50 {
|
|
return 4
|
|
} else if level >= -60 {
|
|
return 3
|
|
} else if level >= -70 {
|
|
return 2
|
|
} else {
|
|
return 1
|
|
}
|
|
}
|