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 }