Files
Hadi 59b31e5ca3 init
Signed-off-by: Hadi <[email protected]>
2026-08-13 00:58:37 +02:00

119 lines
2.9 KiB
Go

package network
import (
"errors"
"strconv"
)
var ErrNoWifiDevice = errors.New("no Wi-Fi device found")
// WifiDevice returns the first Wi-Fi radio device, if any.
func WifiDevice() (Device, error) {
devices, err := ListDevices()
if err != nil {
return Device{}, err
}
for _, d := range devices {
if d.Type == "wifi" {
return d, nil
}
}
return Device{}, ErrNoWifiDevice
}
// WifiNetwork is one access point seen by `nmcli device wifi list`.
type WifiNetwork struct {
Active bool // this is the AP we're currently associated with
SSID string
BSSID string
Signal int // 0-100
Security string
}
func (w WifiNetwork) Secured() bool {
return w.Security != "" && w.Security != "--"
}
// ListWifi returns visible access points, deduplicated by SSID (keeping the
// strongest signal seen for each network), sorted strongest-first.
func ListWifi() ([]WifiNetwork, error) {
rows, err := runTerse("IN-USE,SSID,BSSID,SIGNAL,SECURITY", "device", "wifi", "list")
if err != nil {
return nil, err
}
bySSID := make(map[string]WifiNetwork)
order := make([]string, 0, len(rows))
for _, row := range rows {
ssid := field(row, 1)
if ssid == "" {
continue // hidden network with no broadcast SSID
}
signal, _ := strconv.Atoi(field(row, 3))
net := WifiNetwork{
Active: field(row, 0) == "*",
SSID: ssid,
BSSID: field(row, 2),
Signal: signal,
Security: field(row, 4),
}
existing, ok := bySSID[ssid]
if !ok || net.Active || net.Signal > existing.Signal {
bySSID[ssid] = net
}
if !ok {
order = append(order, ssid)
}
}
networks := make([]WifiNetwork, 0, len(order))
for _, ssid := range order {
networks = append(networks, bySSID[ssid])
}
return networks, nil
}
// Rescan asks NetworkManager to trigger a fresh Wi-Fi scan. It returns once
// the scan is requested, not once it completes; call ListWifi shortly after.
func Rescan() error {
_, err := run("device", "wifi", "rescan")
return err
}
// ConnectWifi joins ssid, creating a new saved profile if none exists yet.
// Pass an empty password for open networks or when a saved profile already
// has one.
func ConnectWifi(ssid, password string) error {
args := []string{"device", "wifi", "connect", ssid}
if password != "" {
args = append(args, "password", password)
}
_, err := run(args...)
return err
}
// DisconnectWifi disconnects the given Wi-Fi device without forgetting it.
func DisconnectWifi(device string) error {
_, err := run("device", "disconnect", device)
return err
}
// SetWifiRadio turns the Wi-Fi radio on or off entirely.
func SetWifiRadio(on bool) error {
state := "off"
if on {
state = "on"
}
_, err := run("radio", "wifi", state)
return err
}
// RadioEnabled reports whether the Wi-Fi radio is currently switched on.
func RadioEnabled() (bool, error) {
out, err := getField("WIFI", "general")
if err != nil {
return false, err
}
return out == "enabled", nil
}