Refactor stations discovery and add hostapd discovery

This commit is contained in:
nemunaire 2026-01-01 23:29:34 +07:00
commit 2922a03724
15 changed files with 1339 additions and 249 deletions

View file

@ -0,0 +1,99 @@
package backend
import (
"strings"
"time"
)
// StationBackend defines the interface for station/device discovery backends.
// Implementations include ARP-based, DHCP-based, and Hostapd DBus-based discovery.
type StationBackend interface {
// Initialize initializes the backend with the given configuration
Initialize(config BackendConfig) error
// Close cleans up backend resources
Close() error
// GetStations returns all currently connected stations
GetStations() ([]Station, error)
// StartEventMonitoring starts monitoring for station events
// Backends that don't support real-time events will poll and simulate events
StartEventMonitoring(callbacks EventCallbacks) error
// StopEventMonitoring stops event monitoring
StopEventMonitoring()
// SupportsRealTimeEvents returns true if backend supports real-time events (e.g., DBus)
// Returns false for polling-based backends (ARP, DHCP)
SupportsRealTimeEvents() bool
}
// Station represents a connected device in a backend-agnostic format
type Station struct {
MAC string // Hardware MAC address (required, primary identifier)
IP string // IP address (may be empty for some backends initially)
Hostname string // Device hostname (may be empty)
Type string // Device type: "mobile", "laptop", "tablet", "unknown"
Signal int32 // Signal strength in dBm (0 if not available)
RxBytes uint64 // Received bytes (0 if not available)
TxBytes uint64 // Transmitted bytes (0 if not available)
ConnectedAt time.Time // When station connected (best effort)
}
// EventCallbacks defines callback functions for station events.
// Backends call these when stations connect, disconnect, or update.
type EventCallbacks struct {
// OnStationConnected is called when a new station connects
OnStationConnected func(station Station)
// OnStationDisconnected is called when a station disconnects
OnStationDisconnected func(mac string)
// OnStationUpdated is called when station information changes
// (e.g., IP discovered, signal strength changed)
OnStationUpdated func(station Station)
}
// BackendConfig provides configuration for backend initialization
type BackendConfig struct {
// Common
InterfaceName string // Network interface (e.g., "wlan1")
// ARP-specific
ARPTablePath string // Path to /proc/net/arp (default: "/proc/net/arp")
// DHCP-specific
DHCPLeasesPath string // Path to DHCP leases file
// Hostapd-specific
HostapdInterface string // Hostapd interface name for DBus
}
// GuessDeviceType attempts to guess device type from hostname and MAC address
func GuessDeviceType(hostname, mac string) string {
hostname = strings.ToLower(hostname)
if strings.Contains(hostname, "iphone") || strings.Contains(hostname, "android") {
return "mobile"
} else if strings.Contains(hostname, "ipad") || strings.Contains(hostname, "tablet") {
return "tablet"
} else if strings.Contains(hostname, "macbook") || strings.Contains(hostname, "laptop") {
return "laptop"
}
// Guess by MAC prefix (OUI)
if len(mac) >= 8 {
macPrefix := strings.ToUpper(mac[:8])
switch macPrefix {
case "00:50:56", "00:0C:29", "00:05:69": // VMware
return "laptop"
case "08:00:27": // VirtualBox
return "laptop"
default:
return "mobile"
}
}
return "unknown"
}