You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
12 KiB

"""
设备管理API
提供统一的设备管理接口,包括设备操作控制、ADB管理等功能
注意:设备注册、更新、注销等操作是自动化的,不对外提供API
"""
from fastapi import APIRouter, HTTPException, status
from typing import List, Optional, Dict, Any
from app.services.device_service import device_service
from app.schemas.adb import (
ClickRequest, InputRequest, ScreenshotResponse,
InstallRequest, InstallResponse, LogcatRequest, LogcatResponse
)
from app.utils.structured_log import get_structured_logger, LogLevel
logger = get_structured_logger(__name__, LogLevel.INFO)
router = APIRouter()
@router.get("/devices", summary="获取所有设备")
async def get_all_devices():
"""获取所有设备(包括注册和自动发现的)"""
try:
devices = await device_service.get_all_devices()
return {
"success": True,
"message": f"获取到 {len(devices)} 个设备",
"data": {
"devices": devices,
"total": len(devices)
}
}
except Exception as e:
logger.error(f"获取所有设备失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取设备列表失败: {str(e)}"
)
@router.get("/devices/{device_id}", summary="获取设备信息")
async def get_device_info(device_id: str):
"""获取指定设备的详细信息"""
try:
device_info = await device_service.get_device_info(device_id)
if not device_info:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"设备 {device_id} 不存在"
)
return {
"success": True,
"message": "获取设备信息成功",
"data": device_info
}
except HTTPException:
raise
except Exception as e:
logger.error(f"获取设备信息失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取设备信息失败: {str(e)}"
)
@router.post("/devices/{device_id}/click", summary="执行点击操作")
async def click_device(device_id: str, click_request: ClickRequest):
"""在指定设备上执行点击操作"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="click",
x=click_request.x,
y=click_request.y,
duration=click_request.duration
)
return {
"success": True,
"message": "点击操作执行成功",
"data": result
}
except ValueError as e:
logger.warning(f"点击操作参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"点击操作失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"点击操作失败: {str(e)}"
)
@router.post("/devices/{device_id}/input", summary="输入文本")
async def input_text(device_id: str, input_request: InputRequest):
"""在指定设备上输入文本"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="input_text",
text=input_request.text,
clear_first=input_request.clear_first
)
return {
"success": True,
"message": "文本输入成功",
"data": result
}
except ValueError as e:
logger.warning(f"文本输入参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"文本输入失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"文本输入失败: {str(e)}"
)
@router.get("/devices/{device_id}/screenshot", response_model=ScreenshotResponse, summary="获取屏幕截图")
async def get_screenshot(device_id: str):
"""获取指定设备的屏幕截图"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="screenshot"
)
return result
except ValueError as e:
logger.warning(f"截图操作参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"截图操作失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"截图操作失败: {str(e)}"
)
@router.post("/devices/{device_id}/install", response_model=InstallResponse, summary="安装APK")
async def install_apk(device_id: str, install_request: InstallRequest):
"""在指定设备上安装APK"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="install_apk",
apk_path=install_request.apk_path,
package_name=install_request.package_name
)
return result
except ValueError as e:
logger.warning(f"安装APK参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"安装APK失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"安装APK失败: {str(e)}"
)
@router.get("/devices/{device_id}/logcat", response_model=LogcatResponse, summary="获取日志")
async def get_logcat(
device_id: str,
package_name: Optional[str] = None,
level: str = "V",
max_lines: int = 100
):
"""获取指定设备的日志"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="get_logcat",
package_name=package_name,
level=level,
max_lines=max_lines
)
return result
except ValueError as e:
logger.warning(f"获取日志参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"获取日志失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取日志失败: {str(e)}"
)
@router.post("/devices/{device_id}/shell", summary="执行Shell命令")
async def execute_shell_command(device_id: str, command: str, timeout: int = 30):
"""在指定设备上执行Shell命令"""
try:
result = await device_service.execute_operation(
device_id=device_id,
operation="execute_shell_command",
command=command,
timeout=timeout
)
return {
"success": True,
"message": "Shell命令执行成功",
"data": result
}
except ValueError as e:
logger.warning(f"Shell命令参数错误: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"Shell命令执行失败: {device_id}, 错误: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Shell命令执行失败: {str(e)}"
)
@router.post("/devices/cache/clear", summary="清除设备缓存")
async def clear_device_cache():
"""清除设备来源缓存"""
try:
device_service.clear_cache()
return {
"success": True,
"message": "设备缓存清除成功"
}
except Exception as e:
logger.error(f"清除设备缓存失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"清除设备缓存失败: {str(e)}"
)
# ==================== ADB管理功能 ====================
@router.get("/adb/server/info", summary="获取ADB服务器信息")
async def get_adb_server_info():
"""获取ADB服务器信息"""
try:
result = await device_service.auto_discovery_adb_service.get_server_info()
return {
"success": True,
"message": "获取ADB服务器信息成功",
"data": result
}
except Exception as e:
logger.error(f"获取ADB服务器信息失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取ADB服务器信息失败: {str(e)}"
)
@router.get("/adb/devices", summary="获取ADB设备列表")
async def get_adb_devices(status: Optional[str] = None):
"""获取ADB设备列表"""
try:
status_filter = [status] if status else None
result = await device_service.auto_discovery_adb_service.list_devices(status_filter)
return {
"success": True,
"message": f"获取到 {len(result)} 个ADB设备",
"data": result
}
except Exception as e:
logger.error(f"获取ADB设备列表失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取ADB设备列表失败: {str(e)}"
)
@router.post("/adb/monitor/start", summary="启动ADB设备监控")
async def start_adb_monitoring():
"""启动ADB设备监控"""
try:
await device_service.auto_discovery_adb_service.start_monitoring()
return {
"success": True,
"message": "ADB设备监控启动成功"
}
except Exception as e:
logger.error(f"启动ADB设备监控失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"启动ADB设备监控失败: {str(e)}"
)
@router.post("/adb/monitor/stop", summary="停止ADB设备监控")
async def stop_adb_monitoring():
"""停止ADB设备监控"""
try:
await device_service.auto_discovery_adb_service.stop_monitoring()
return {
"success": True,
"message": "ADB设备监控停止成功"
}
except Exception as e:
logger.error(f"停止ADB设备监控失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"停止ADB设备监控失败: {str(e)}"
)
@router.get("/adb/monitor/status", summary="获取ADB监控状态")
async def get_adb_monitoring_status():
"""获取ADB监控状态"""
try:
monitoring_started = device_service.auto_discovery_adb_service._monitoring_started
task_done = device_service.auto_discovery_adb_service._device_monitor_task.done() if device_service.auto_discovery_adb_service._device_monitor_task else True
return {
"success": True,
"message": "获取ADB监控状态成功",
"data": {
"monitoring_started": monitoring_started,
"task_done": task_done,
"status": "running" if monitoring_started and not task_done else "stopped"
}
}
except Exception as e:
logger.error(f"获取ADB监控状态失败: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取ADB监控状态失败: {str(e)}"
)