""" Device management API endpoints. """ from typing import List from fastapi import APIRouter, Depends, HTTPException from dashboard.dependencies import get_device_manager, get_ws_manager from dashboard.models.device import DeviceSchema, DeviceStatus from dashboard.services.device_manager import DeviceManager from dashboard.services.websocket_manager import WebSocketManager router = APIRouter(prefix="/devices", tags=["devices"]) @router.get("", response_model=List[DeviceSchema]) async def list_devices( device_manager: DeviceManager = Depends(get_device_manager), ): """List all connected devices. Returns: List of device schemas """ devices = await device_manager.refresh_devices() return [ DeviceSchema( device_id=d.device_id, status=d.status, device_type=d.device_type, model=d.model, android_version=d.android_version, current_app=d.current_app, last_seen=d.last_seen, is_connected=d.is_connected, ) for d in devices ] @router.get("/refresh") async def refresh_devices( device_manager: DeviceManager = Depends(get_device_manager), ws_manager: WebSocketManager = Depends(get_ws_manager), ): """Rescan for connected devices. Returns: Refresh confirmation """ devices = await device_manager.refresh_devices() # Broadcast device update for device in devices: await ws_manager.broadcast_device_update( device.device_id, { "status": device.status, "is_connected": device.is_connected, "model": device.model, "current_app": device.current_app, "last_seen": device.last_seen.isoformat(), }, ) return {"message": "Devices refreshed", "count": len(devices)} @router.get("/{device_id}", response_model=DeviceSchema) async def get_device( device_id: str, device_manager: DeviceManager = Depends(get_device_manager), ): """Get device details. Args: device_id: Device identifier Returns: Device schema Raises: HTTPException: If device not found """ device = await device_manager.get_device(device_id) if device is None: raise HTTPException(status_code=404, detail=f"Device {device_id} not found") return DeviceSchema( device_id=device.device_id, status=device.status, device_type=device.device_type, model=device.model, android_version=device.android_version, current_app=device.current_app, last_seen=device.last_seen, is_connected=device.is_connected, ) @router.post("/{device_id}/connect") async def connect_device( device_id: str, address: str | None = None, device_manager: DeviceManager = Depends(get_device_manager), ): """Connect to device via WiFi. Args: device_id: Device identifier (for route matching) address: Device address (IP:PORT) Returns: Connection result """ if not address: raise HTTPException(status_code=400, detail="Address is required") success = await device_manager.connect_device(address) if success: return {"message": f"Connected to {address}"} else: raise HTTPException(status_code=500, detail=f"Failed to connect to {address}") @router.post("/{device_id}/disconnect") async def disconnect_device( device_id: str, address: str | None = None, device_manager: DeviceManager = Depends(get_device_manager), ): """Disconnect from device. Args: device_id: Device identifier (for route matching) address: Device address (IP:PORT) Returns: Disconnection result """ if not address: raise HTTPException(status_code=400, detail="Address is required") success = await device_manager.disconnect_device(address) if success: return {"message": f"Disconnected from {address}"} else: raise HTTPException( status_code=500, detail=f"Failed to disconnect from {address}" ) @router.get("/{device_id}/screenshot") async def get_device_screenshot( device_id: str, device_manager: DeviceManager = Depends(get_device_manager), ): """Get current device screenshot. Args: device_id: Device identifier Returns: Screenshot data (base64 encoded) """ screenshot = await device_manager.get_screenshot(device_id) if screenshot is None: raise HTTPException(status_code=500, detail="Failed to capture screenshot") return {"device_id": device_id, "screenshot": screenshot} @router.get("/{device_id}/current-app") async def get_current_app( device_id: str, device_manager: DeviceManager = Depends(get_device_manager), ): """Get current app for device. Args: device_id: Device identifier Returns: Current app package name """ app = await device_manager.get_current_app(device_id) return {"device_id": device_id, "current_app": app}