"""WiFi management API endpoints.""" from fastapi import APIRouter, HTTPException from pydantic import BaseModel from typing import List, Optional from ..managers.wifi_manager import ( wifi_manager, WiFiMode, WiFiStatus, WiFiNetwork, WiFiInterface, ) router = APIRouter() class WiFiStatusResponse(BaseModel): """WiFi status response.""" mode: str interfaces: List[dict] current_ssid: Optional[str] current_ip: Optional[str] ap_ssid: Optional[str] ap_ip: Optional[str] supports_dual: bool class WiFiNetworkResponse(BaseModel): """WiFi network response.""" ssid: str bssid: str signal_strength: int frequency: int encrypted: bool in_use: bool class SetModeRequest(BaseModel): """Request to set WiFi mode.""" mode: WiFiMode class ConnectRequest(BaseModel): """Request to connect to network.""" ssid: str password: Optional[str] = None interface: Optional[str] = None hidden: bool = False @router.get("/status", response_model=WiFiStatusResponse) async def get_wifi_status(): """Get current WiFi status and available interfaces. Returns WiFi mode, interface information, and connection status. """ try: status: WiFiStatus = await wifi_manager.get_status() return WiFiStatusResponse( mode=status.mode.value, interfaces=[ { "name": iface.name, "mac": iface.mac, "is_usb": iface.is_usb, "is_up": iface.is_up, "connected": iface.connected, "ssid": iface.ssid, "ip_address": iface.ip_address, } for iface in status.interfaces ], current_ssid=status.current_ssid, current_ip=status.current_ip, ap_ssid=status.ap_ssid, ap_ip=status.ap_ip, supports_dual=status.supports_dual, ) except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to get WiFi status: {e}") @router.get("/scan", response_model=List[WiFiNetworkResponse]) async def scan_networks(interface: Optional[str] = None): """Scan for available WiFi networks. Args: interface: Optional interface to scan with Returns: List of available networks """ try: networks = await wifi_manager.scan_networks(interface) return [ WiFiNetworkResponse( ssid=net.ssid, bssid=net.bssid, signal_strength=net.signal_strength, frequency=net.frequency, encrypted=net.encrypted, in_use=net.in_use, ) for net in networks ] except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to scan networks: {e}") @router.post("/mode") async def set_wifi_mode(request: SetModeRequest): """Set WiFi operation mode. Args: request: Mode to set (ap, client, dual, auto, off) Returns: Success status """ try: success = await wifi_manager.set_mode(request.mode) if not success: raise HTTPException(status_code=500, detail="Failed to set WiFi mode") return { "success": True, "message": f"WiFi mode set to {request.mode.value}", "mode": request.mode.value, } except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to set WiFi mode: {e}") @router.post("/connect") async def connect_to_network(request: ConnectRequest): """Connect to a WiFi network. Args: request: Connection details (SSID, password, interface, hidden) Returns: Success status """ try: success = await wifi_manager.connect_to_network( ssid=request.ssid, password=request.password, interface=request.interface, hidden=request.hidden, ) if not success: raise HTTPException(status_code=500, detail="Failed to connect to network") return { "success": True, "message": f"Connected to {request.ssid}", "ssid": request.ssid, } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to connect to network: {e}") @router.get("/interfaces") async def get_interfaces(): """Get available WiFi interfaces. Returns: List of WiFi interfaces with their status """ try: interfaces = await wifi_manager.detect_interfaces() return { "interfaces": [ { "name": iface.name, "mac": iface.mac, "is_usb": iface.is_usb, "is_up": iface.is_up, "connected": iface.connected, "ssid": iface.ssid, "ip_address": iface.ip_address, } for iface in interfaces ], "supports_dual": len(interfaces) >= 2, } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to get interfaces: {e}") @router.post("/disconnect") async def disconnect_from_network(interface: Optional[str] = None): """Disconnect from current network. Args: interface: Interface to disconnect (optional) Returns: Success status """ try: success = await wifi_manager.disconnect_from_network(interface) if not success: raise HTTPException(status_code=500, detail="Failed to disconnect") return { "success": True, "message": "Disconnected from network", } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to disconnect: {e}") @router.get("/saved") async def get_saved_networks(): """Get list of saved networks. Returns: List of saved networks """ try: networks = await wifi_manager.get_saved_networks() return {"networks": networks} except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to get saved networks: {e}") @router.delete("/saved/{ssid}") async def forget_network(ssid: str): """Forget a saved network. Args: ssid: SSID of network to forget Returns: Success status """ try: success = await wifi_manager.forget_network(ssid) if not success: raise HTTPException(status_code=404, detail=f"Network {ssid} not found") return { "success": True, "message": f"Forgot network {ssid}", } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to forget network: {e}") @router.post("/static-ip") async def set_static_ip( interface: str, ip_address: str, netmask: str = "255.255.255.0", gateway: Optional[str] = None, dns: Optional[List[str]] = None, ): """Set static IP for interface. Args: interface: Interface name ip_address: Static IP address netmask: Network mask (default: 255.255.255.0) gateway: Gateway IP (optional) dns: DNS servers (optional) Returns: Success status """ try: success = await wifi_manager.set_static_ip( interface, ip_address, netmask, gateway, dns ) if not success: raise HTTPException(status_code=500, detail="Failed to set static IP") return { "success": True, "message": f"Static IP {ip_address} set for {interface}", } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to set static IP: {e}") @router.post("/dhcp") async def enable_dhcp(interface: str): """Enable DHCP for interface. Args: interface: Interface name Returns: Success status """ try: success = await wifi_manager.enable_dhcp(interface) if not success: raise HTTPException(status_code=500, detail="Failed to enable DHCP") return { "success": True, "message": f"DHCP enabled for {interface}", } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to enable DHCP: {e}")