repeater/internal/hotspot/hotspot.go

111 lines
2.3 KiB
Go

package hotspot
import (
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"github.com/nemunaire/repeater/internal/models"
)
const (
AP_INTERFACE = "wlan1"
HOSTAPD_CONF = "/etc/hostapd/hostapd.conf"
)
// Configure updates the hotspot configuration
func Configure(config models.HotspotConfig) error {
hostapdConfig := fmt.Sprintf(`interface=%s
driver=nl80211
ssid=%s
hw_mode=g
channel=%d
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=%s
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
`, AP_INTERFACE, config.SSID, config.Channel, config.Password)
return os.WriteFile(HOSTAPD_CONF, []byte(hostapdConfig), 0644)
}
// Start starts the hotspot
func Start() error {
cmd := exec.Command("/etc/init.d/hostapd", "start")
return cmd.Run()
}
// Stop stops the hotspot
func Stop() error {
cmd := exec.Command("/etc/init.d/hostapd", "stop")
return cmd.Run()
}
// Status checks if the hotspot is running.
// Returns nil if the service is running, or an error if it's stopped or crashed.
func Status() error {
cmd := exec.Command("/etc/init.d/hostapd", "status")
return cmd.Run()
}
// GetDetailedStatus retrieves detailed status information from hostapd_cli.
// Returns nil if hostapd is not running or if there's an error.
func GetDetailedStatus() *models.HotspotStatus {
cmd := exec.Command("hostapd_cli", "status")
output, err := cmd.Output()
if err != nil {
return nil
}
status := &models.HotspotStatus{}
lines := strings.Split(string(output), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "Selected interface") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "state":
status.State = value
case "channel":
if ch, err := strconv.Atoi(value); err == nil {
status.Channel = ch
}
case "freq":
if freq, err := strconv.Atoi(value); err == nil {
status.Frequency = freq
}
case "ssid[0]":
status.SSID = value
case "bssid[0]":
status.BSSID = value
case "num_sta[0]":
if num, err := strconv.Atoi(value); err == nil {
status.NumStations = num
}
case "hw_mode":
status.HWMode = value
case "country_code":
status.CountryCode = value
}
}
return status
}