from fastapi import APIRouter, HTTPException, Depends, Path, Body from pydantic import BaseModel, Field from typing import Optional from api.auth import api_auth from services.connection_manager import connection_manager from services.device_volume_manager import device_volume_manager from utils.logger import session_logger router = APIRouter(prefix="/api/device", tags=["Device Control"]) class VolumeRequest(BaseModel): volume: int = Field(..., ge=0, le=100, description="音量值(0-100)") class DeviceResponse(BaseModel): status: str message: str device_id: str class VolumeResponse(BaseModel): volume: int device_id: str @router.post("/volume/{device_id}", response_model=DeviceResponse) async def set_device_volume( device_id: str = Path(..., description="设备ID"), volume_request: VolumeRequest = Body(...), authenticated_device_id: str = Depends(api_auth) ): """设置设备音量""" try: await device_volume_manager.set_volume(device_id, volume_request.volume) session_logger.info(device_id, "volume", f"设备音量设置为 {volume_request.volume}") websocket = await connection_manager.get_connection(device_id) if websocket: try: await websocket.send_text(f"VOLUME:{volume_request.volume}") session_logger.info(device_id, "volume", f"已发送实时音量设置到设备") except Exception as e: session_logger.warning(device_id, "volume", f"发送音量通知失败,但数据库已更新: {str(e)}") else: session_logger.info(device_id, "volume", "设备当前不在线,仅保存设置到数据库") return { "status": "success", "message": f"Volume set to {volume_request.volume}", "device_id": device_id } except Exception as e: session_logger.error(device_id, "volume", f"设置音量失败: {str(e)}") raise HTTPException(status_code=500, detail=f"设置音量失败: {str(e)}") @router.get("/volume/{device_id}", response_model=VolumeResponse) async def get_device_volume( device_id: str = Path(..., description="设备ID"), authenticated_device_id: str = Depends(api_auth) ): """获取设备当前音量设置""" try: volume = await device_volume_manager.get_volume(device_id) return { "volume": volume, "device_id": device_id } except Exception as e: session_logger.error(device_id, "volume", f"获取音量失败: {str(e)}") raise HTTPException(status_code=500, detail=f"获取音量失败: {str(e)}") class NetworkResetResponse(BaseModel): status: str message: str device_id: str @router.post("/reset-network/{device_id}", response_model=NetworkResetResponse) async def reset_device_network( device_id: str = Path(..., description="设备ID"), authenticated_device_id: str = Depends(api_auth) ): """重置设备网络配置""" websocket = await connection_manager.get_connection(device_id) if not websocket: raise HTTPException(status_code=404, detail=f"设备 {device_id} 未在线或未找到") try: await websocket.send_text("RESET_NETWORK") session_logger.info(device_id, "network", "已发送网络重置命令") return { "status": "success", "message": "Network reset initiated", "device_id": device_id } except Exception as e: session_logger.error(device_id, "network", f"网络重置命令发送失败: {str(e)}") raise HTTPException(status_code=500, detail=f"网络重置命令发送失败: {str(e)}")