Get current Wi-Fi manager status with real-time SSID check. NOTE: This method is intentionally read-only with respect to the network storage layer. It must NEVER call ``_set_current_ssid()`` because that triggers ``set_active_network()`` which, on a transient Wi-Fi
(self)
| 2869 | self.ap_logger.info(f"Configuring interface {self.ap_interface} for AP mode") |
| 2870 | |
| 2871 | # Stop NetworkManager from managing the interface |
| 2872 | self.ap_logger.debug("Setting NetworkManager to not manage interface") |
| 2873 | result = subprocess.run(['sudo', 'nmcli', 'dev', 'set', self.ap_interface, 'managed', 'no'], |
| 2874 | capture_output=True, text=True, timeout=10) |
| 2875 | if result.returncode != 0: |
| 2876 | self.ap_logger.warning(f"NetworkManager command failed: {result.stderr}") |
| 2877 | |
| 2878 | # Configure IP address |
| 2879 | self.ap_logger.debug("Flushing existing IP addresses") |
| 2880 | result = subprocess.run(['sudo', 'ip', 'addr', 'flush', 'dev', self.ap_interface], |
| 2881 | capture_output=True, text=True, timeout=10) |
| 2882 | if result.returncode != 0: |
| 2883 | self.ap_logger.warning(f"IP flush failed: {result.stderr}") |
| 2884 | |
| 2885 | self.ap_logger.debug(f"Adding IP address {self.ap_ip}/24") |
| 2886 | result = subprocess.run(['sudo', 'ip', 'addr', 'add', f'{self.ap_ip}/24', 'dev', self.ap_interface], |
| 2887 | capture_output=True, text=True, timeout=10) |
| 2888 | if result.returncode != 0: |
| 2889 | self.ap_logger.error(f"Failed to add IP address: {result.stderr}") |
| 2890 | return False |
| 2891 | |
| 2892 | self.ap_logger.debug("Bringing interface up") |
| 2893 | result = subprocess.run(['sudo', 'ip', 'link', 'set', 'dev', self.ap_interface, 'up'], |
| 2894 | capture_output=True, text=True, timeout=10) |
| 2895 | if result.returncode != 0: |
| 2896 | self.ap_logger.error(f"Failed to bring interface up: {result.stderr}") |
| 2897 | return False |
| 2898 | |
| 2899 | # Wait for interface to be fully ready |
| 2900 | time.sleep(2) |
| 2901 | |
| 2902 | # Verify interface configuration |
| 2903 | self.ap_logger.debug("Verifying interface configuration...") |
| 2904 | result = subprocess.run(['ip', 'addr', 'show', self.ap_interface], |
| 2905 | capture_output=True, text=True, timeout=5) |
| 2906 | if result.returncode == 0: |
| 2907 | self.ap_logger.debug(f"Interface status:\n{result.stdout}") |
| 2908 | if self.ap_ip not in result.stdout: |
| 2909 | self.ap_logger.error(f"Interface {self.ap_interface} does not have expected IP {self.ap_ip}") |
| 2910 | return False |
| 2911 | |
| 2912 | self.logger.info("Configured AP interface") |
| 2913 | self.ap_logger.info(f"Interface {self.ap_interface} configured successfully with IP {self.ap_ip}") |
| 2914 | return True |
| 2915 | |
| 2916 | except Exception as e: |
| 2917 | self.logger.error(f"Error configuring AP interface: {e}") |
| 2918 | self.ap_logger.error(f"Exception configuring AP interface: {e}") |
| 2919 | return False |
| 2920 | |
| 2921 | def _start_ap_services(self): |
| 2922 | """Start hostapd and dnsmasq services""" |
| 2923 | try: |
| 2924 | # Kill any existing conflicting services first |
| 2925 | self.ap_logger.info("Cleaning up any conflicting services...") |
| 2926 | |
| 2927 | # Stop any system dnsmasq that might conflict |
| 2928 | try: |
nothing calls this directly
no test coverage detected