repeater/internal/wifi/iwd/station.go

142 lines
3.3 KiB
Go

package iwd
import (
"fmt"
"github.com/godbus/dbus/v5"
)
// Station represents an iwd Station interface
type Station struct {
path dbus.ObjectPath
conn *dbus.Conn
obj dbus.BusObject
}
// NewStation creates a new Station instance
func NewStation(conn *dbus.Conn, path dbus.ObjectPath) *Station {
return &Station{
path: path,
conn: conn,
obj: conn.Object(Service, path),
}
}
// Scan triggers a network scan
func (s *Station) Scan() error {
err := s.obj.Call(StationInterface+".Scan", 0).Err
if err != nil {
return fmt.Errorf("scan failed: %v", err)
}
return nil
}
// IsScanning checks if a scan is currently in progress
func (s *Station) IsScanning() (bool, error) {
prop, err := s.obj.GetProperty(StationInterface + ".Scanning")
if err != nil {
return false, fmt.Errorf("failed to get Scanning property: %v", err)
}
scanning, ok := prop.Value().(bool)
if !ok {
return false, fmt.Errorf("Scanning property is not a boolean")
}
return scanning, nil
}
// GetOrderedNetworks returns networks sorted by signal strength
func (s *Station) GetOrderedNetworks() ([]NetworkInfo, error) {
var result []struct {
Path dbus.ObjectPath
Signal int16
}
err := s.obj.Call(StationInterface+".GetOrderedNetworks", 0).Store(&result)
if err != nil {
return nil, fmt.Errorf("failed to get ordered networks: %v", err)
}
networks := make([]NetworkInfo, len(result))
for i, r := range result {
networks[i] = NetworkInfo{
Path: r.Path,
Signal: r.Signal,
}
}
return networks, nil
}
// GetState returns the current connection state
func (s *Station) GetState() (StationState, error) {
prop, err := s.obj.GetProperty(StationInterface + ".State")
if err != nil {
return "", fmt.Errorf("failed to get State property: %v", err)
}
state, ok := prop.Value().(string)
if !ok {
return "", fmt.Errorf("State property is not a string")
}
return StationState(state), nil
}
// Disconnect disconnects from the current network
func (s *Station) Disconnect() error {
err := s.obj.Call(StationInterface+".Disconnect", 0).Err
if err != nil {
return fmt.Errorf("disconnect failed: %v", err)
}
return nil
}
// GetNetwork finds and returns a Network object by SSID
func (s *Station) GetNetwork(ssid string) (*Network, error) {
networks, err := s.GetOrderedNetworks()
if err != nil {
return nil, err
}
// Find the network with matching SSID
for _, netInfo := range networks {
network := NewNetwork(s.conn, netInfo.Path)
props, err := network.GetProperties()
if err != nil {
continue
}
if props.Name == ssid {
return network, nil
}
}
return nil, fmt.Errorf("network '%s' not found", ssid)
}
// GetConnectedNetwork returns the currently connected network
func (s *Station) GetConnectedNetwork() (*Network, error) {
prop, err := s.obj.GetProperty(StationInterface + ".ConnectedNetwork")
if err != nil {
return nil, fmt.Errorf("failed to get ConnectedNetwork property: %v", err)
}
path, ok := prop.Value().(dbus.ObjectPath)
if !ok {
return nil, fmt.Errorf("ConnectedNetwork property is not an ObjectPath")
}
// Check if path is empty (not connected)
if path == "/" || path == "" {
return nil, fmt.Errorf("not connected to any network")
}
return NewNetwork(s.conn, path), nil
}
// GetPath returns the D-Bus object path for this station
func (s *Station) GetPath() dbus.ObjectPath {
return s.path
}