diff --git a/subsystems/provisioning/definitions.go b/subsystems/provisioning/definitions.go index 8792345..67bafb4 100644 --- a/subsystems/provisioning/definitions.go +++ b/subsystems/provisioning/definitions.go @@ -29,6 +29,10 @@ const ( ConnCheckFilepath = "/etc/NetworkManager/conf.d/80-viam.conf" ConnCheckContents = "[connectivity]\nuri=http://packages.viam.com/check_network_status.txt\ninterval=300\n" + wifiPowerSaveFilepath = "/etc/NetworkManager/conf.d/81-viam-wifi-powersave.conf" + wifiPowerSaveContentsDefault = "# This file intentionally left blank.\n" + wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2\n" + wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3\n" NetworkTypeWifi = "wifi" NetworkTypeWired = "wired" NetworkTypeHotspot = "hotspot" @@ -366,8 +370,8 @@ type Config struct { // Computed from HotspotPrefix and Manufacturer hotspotSSID string - // When true, it will disable power save for all wifi connections managed by NetworkManager. - DisableWifiPowerSave *bool `json:"disable_wifi_power_save"` + // If set, will explicitly enable or disable power save for all wifi connections managed by NetworkManager. + WifiPowerSave *bool `json:"wifi_power_save"` } // Timeout allows parsing golang-style durations (1h20m30s) OR seconds-as-float from/to json. diff --git a/subsystems/provisioning/grpc.go b/subsystems/provisioning/grpc.go index d408cb1..5aee5ef 100644 --- a/subsystems/provisioning/grpc.go +++ b/subsystems/provisioning/grpc.go @@ -16,7 +16,7 @@ func (w *Provisioning) startGRPC() error { bind := PortalBindAddr + ":4772" lis, err := net.Listen("tcp", bind) if err != nil { - return errw.Wrapf(err, "error listening on: %s", bind) + return errw.Wrapf(err, "listening on: %s", bind) } w.grpcServer = grpc.NewServer(grpc.WaitForHandlers(true)) diff --git a/subsystems/provisioning/networkmanager.go b/subsystems/provisioning/networkmanager.go index 82f95f8..81683b8 100644 --- a/subsystems/provisioning/networkmanager.go +++ b/subsystems/provisioning/networkmanager.go @@ -175,13 +175,13 @@ func (w *Provisioning) StartProvisioning(ctx context.Context, inputChan chan<- u return err } if err := w.activateConnection(ctx, w.Config().HotspotInterface, w.Config().hotspotSSID); err != nil { - return errw.Wrap(err, "error starting provisioning mode hotspot") + return errw.Wrap(err, "starting provisioning mode hotspot") } // start portal with ssid list and known connections if err := w.startPortal(inputChan); err != nil { err = errors.Join(err, w.deactivateConnection(w.Config().HotspotInterface, w.Config().hotspotSSID)) - return errw.Wrap(err, "could not start web/grpc portal") + return errw.Wrap(err, "starting web/grpc portal") } w.connState.setProvisioning(true) diff --git a/subsystems/provisioning/portal.go b/subsystems/provisioning/portal.go index 996b552..086a944 100644 --- a/subsystems/provisioning/portal.go +++ b/subsystems/provisioning/portal.go @@ -35,11 +35,11 @@ func (w *Provisioning) startPortal(inputChan chan<- userInput) error { w.portalData = &portalData{input: &userInput{}, inputChan: inputChan} if err := w.startGRPC(); err != nil { - return errw.Wrap(err, "error starting GRPC service") + return errw.Wrap(err, "starting GRPC service") } if err := w.startWeb(); err != nil { - return errw.Wrap(err, "error starting web portal service") + return errw.Wrap(err, "starting web portal service") } return nil @@ -56,7 +56,7 @@ func (w *Provisioning) startWeb() error { bind := PortalBindAddr + ":80" lis, err := net.Listen("tcp", bind) if err != nil { - return errw.Wrapf(err, "error listening on: %s", bind) + return errw.Wrapf(err, "listening on: %s", bind) } w.portalData.workers.Add(1) diff --git a/subsystems/provisioning/provisioning.go b/subsystems/provisioning/provisioning.go index 029257a..0e21218 100644 --- a/subsystems/provisioning/provisioning.go +++ b/subsystems/provisioning/provisioning.go @@ -21,14 +21,6 @@ import ( "google.golang.org/grpc" ) -const ( - wifiPowerSaveFilepath = "/etc/NetworkManager/conf.d/wifi-powersave.conf" - - wifiPowerSaveContentsDefault = "[connection]\n# Do not modify existing setting\nwifi.powersave = 1" - wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2" - wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3" -) - func init() { registry.Register(SubsysName, NewProvisioning) } @@ -172,7 +164,7 @@ func (w *Provisioning) init(ctx context.Context) error { w.updateHotspotSSID(w.cfg) if err := w.writeDNSMasq(); err != nil { - return errw.Wrap(err, "error writing dnsmasq configuration") + return errw.Wrap(err, "writing dnsmasq configuration") } if err := w.testConnCheck(); err != nil { @@ -238,8 +230,8 @@ func (w *Provisioning) Start(ctx context.Context) error { } } - if err := w.writeWifiPowerSave(); err != nil { - w.logger.Error(errw.Wrap(err, "error applying wifi power save configuration")) + if err := w.writeWifiPowerSave(ctx); err != nil { + w.logger.Error(errw.Wrap(err, "applying wifi power save configuration")) } w.processAdditionalnetworks(ctx) @@ -369,7 +361,7 @@ func (w *Provisioning) processAdditionalnetworks(ctx context.Context) { for _, network := range w.cfg.Networks { _, err := w.addOrUpdateConnection(network) if err != nil { - w.logger.Error(errw.Wrapf(err, "error adding network %s", network.SSID)) + w.logger.Error(errw.Wrapf(err, "adding network %s", network.SSID)) continue } if network.Interface != "" { @@ -388,27 +380,34 @@ func (w *Provisioning) updateHotspotSSID(cfg *Config) { } } -func (w *Provisioning) writeWifiPowerSave() error { +// must be run inside dataMu lock. +func (w *Provisioning) writeWifiPowerSave(ctx context.Context) error { contents := wifiPowerSaveContentsDefault - - if w.cfg.DisableWifiPowerSave != nil && *w.cfg.DisableWifiPowerSave { - contents = wifiPowerSaveContentsDisable - } - - if w.cfg.DisableWifiPowerSave != nil && !*w.cfg.DisableWifiPowerSave { - contents = wifiPowerSaveContentsEnable + if w.cfg.WifiPowerSave != nil { + if *w.cfg.WifiPowerSave { + contents = wifiPowerSaveContentsEnable + } else { + contents = wifiPowerSaveContentsDisable + } } isNew, err := agent.WriteFileIfNew(wifiPowerSaveFilepath, []byte(contents)) if err != nil { - return errw.Wrap(err, "error writing wifi-powersave.conf") + return errw.Wrap(err, "writing wifi-powersave.conf") } if isNew { w.logger.Infof("Updated %s to: %q", wifiPowerSaveFilepath, contents) // Reload NetworkManager to apply changes if err := w.nm.Reload(0); err != nil { - return errw.Wrap(err, "error reloading NetworkManager after wifi-powersave.conf update") + return errw.Wrap(err, "reloading NetworkManager after wifi-powersave.conf update") + } + + ssid := w.netState.ActiveSSID(w.cfg.HotspotInterface) + if w.connState.getConnected() && ssid != "" { + if err := w.activateConnection(ctx, w.cfg.HotspotInterface, ssid); err != nil { + return errw.Wrapf(err, "reactivating %s to enforce powersave setting", ssid) + } } } diff --git a/subsystems/provisioning/scanning.go b/subsystems/provisioning/scanning.go index 9122615..c3eaa8a 100644 --- a/subsystems/provisioning/scanning.go +++ b/subsystems/provisioning/scanning.go @@ -19,7 +19,7 @@ func (w *Provisioning) networkScan(ctx context.Context) error { prevScan, err := wifiDev.GetPropertyLastScan() if err != nil { - return errw.Wrap(err, "error scanning wifi") + return errw.Wrap(err, "scanning wifi") } err = wifiDev.RequestScan() diff --git a/subsystems/provisioning/setup.go b/subsystems/provisioning/setup.go index dda0785..4fef08a 100644 --- a/subsystems/provisioning/setup.go +++ b/subsystems/provisioning/setup.go @@ -35,35 +35,35 @@ func (w *Provisioning) writeDNSMasq() error { func (w *Provisioning) testConnCheck() error { connCheckEnabled, err := w.nm.GetPropertyConnectivityCheckEnabled() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check state") + return errw.Wrap(err, "getting NetworkManager connectivity check state") } if !connCheckEnabled { hasConnCheck, err := w.nm.GetPropertyConnectivityCheckAvailable() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check configuration") + return errw.Wrap(err, "getting NetworkManager connectivity check configuration") } if !hasConnCheck { if err := w.writeConnCheck(); err != nil { - return (errw.Wrap(err, "error writing NetworkManager connectivity check configuration")) + return (errw.Wrap(err, "writing NetworkManager connectivity check configuration")) } if err := w.nm.Reload(0); err != nil { - return (errw.Wrap(err, "error reloading NetworkManager")) + return (errw.Wrap(err, "reloading NetworkManager")) } hasConnCheck, err = w.nm.GetPropertyConnectivityCheckAvailable() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check configuration") + return errw.Wrap(err, "getting NetworkManager connectivity check configuration") } if !hasConnCheck { - return errors.New("error configuring NetworkManager connectivity check") + return errors.New("configuring NetworkManager connectivity check") } } connCheckEnabled, err = w.nm.GetPropertyConnectivityCheckEnabled() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check state") + return errw.Wrap(err, "getting NetworkManager connectivity check state") } if !connCheckEnabled {