148 lines
3.8 KiB
Python
148 lines
3.8 KiB
Python
"""
|
||
项目管理路由
|
||
管理设备与项目的绑定关系
|
||
"""
|
||
|
||
from fastapi import APIRouter
|
||
from pydantic import BaseModel
|
||
from typing import Optional, Dict, Any
|
||
from services.ws_hub import ws_hub
|
||
import uuid
|
||
from datetime import datetime
|
||
|
||
router = APIRouter(prefix="/projects", tags=["项目管理"])
|
||
|
||
|
||
class ExecuteCommand(BaseModel):
|
||
"""执行命令请求"""
|
||
action: str
|
||
params: Optional[Dict[str, Any]] = {}
|
||
|
||
|
||
# ========== 项目列表 ==========
|
||
|
||
@router.get("")
|
||
async def list_projects():
|
||
"""获取所有项目列表"""
|
||
projects = ws_hub.get_all_projects()
|
||
return {
|
||
"success": True,
|
||
"projects": list(projects.values()),
|
||
"total": len(projects)
|
||
}
|
||
|
||
|
||
@router.get("/{project_id}")
|
||
async def get_project(project_id: str):
|
||
"""获取项目详情"""
|
||
devices = ws_hub.get_project_devices(project_id)
|
||
return {
|
||
"success": True,
|
||
"project_id": project_id,
|
||
"devices": devices,
|
||
"online_count": len(devices)
|
||
}
|
||
|
||
|
||
@router.get("/{project_id}/devices")
|
||
async def get_project_devices(project_id: str):
|
||
"""获取项目下所有在线设备"""
|
||
devices = ws_hub.get_project_devices(project_id)
|
||
return {
|
||
"success": True,
|
||
"project_id": project_id,
|
||
"devices": devices,
|
||
"total": len(devices)
|
||
}
|
||
|
||
|
||
# ========== 批量执行命令 ==========
|
||
|
||
@router.post("/{project_id}/broadcast")
|
||
async def broadcast_command(project_id: str, command: ExecuteCommand):
|
||
"""
|
||
向项目下所有设备广播命令(不等待响应)
|
||
|
||
适用于:打开APP、发送通知等不需要等待结果的操作
|
||
"""
|
||
msg = {
|
||
"type": "execute",
|
||
"command_id": f"cmd_{uuid.uuid4().hex[:8]}",
|
||
"action": command.action,
|
||
"params": command.params,
|
||
"timestamp": int(datetime.now().timestamp())
|
||
}
|
||
|
||
results = await ws_hub.broadcast_to_project(project_id, msg)
|
||
|
||
return {
|
||
"success": True,
|
||
"project_id": project_id,
|
||
"command": command.action,
|
||
"sent": results["success"],
|
||
"failed": results["failed"],
|
||
"details": results["devices"]
|
||
}
|
||
|
||
|
||
@router.post("/{project_id}/execute")
|
||
async def execute_command(project_id: str, command: ExecuteCommand, timeout: int = 30):
|
||
"""
|
||
在项目下所有设备执行命令(等待响应)
|
||
|
||
适用于:需要获取执行结果的操作
|
||
"""
|
||
msg = {
|
||
"type": "execute",
|
||
"action": command.action,
|
||
"params": command.params
|
||
}
|
||
|
||
results = await ws_hub.execute_on_project(project_id, msg, timeout)
|
||
|
||
success_count = sum(1 for r in results if r.get("result", {}).get("code", 500) == 200)
|
||
|
||
return {
|
||
"success": True,
|
||
"project_id": project_id,
|
||
"command": command.action,
|
||
"total_devices": len(results),
|
||
"success_count": success_count,
|
||
"results": results
|
||
}
|
||
|
||
|
||
# ========== 单设备操作 ==========
|
||
|
||
@router.post("/{project_id}/devices/{device_id}/execute")
|
||
async def execute_on_device(
|
||
project_id: str,
|
||
device_id: str,
|
||
command: ExecuteCommand,
|
||
timeout: int = 30
|
||
):
|
||
"""在指定设备上执行命令"""
|
||
|
||
# 检查设备是否属于该项目
|
||
device_info = ws_hub.get_device_info(device_id)
|
||
if not device_info:
|
||
return {"success": False, "message": "设备不存在或离线"}
|
||
|
||
if device_info.get("project_id") != project_id:
|
||
return {"success": False, "message": "设备不属于该项目"}
|
||
|
||
# 发送命令
|
||
msg = {
|
||
"type": "execute",
|
||
"action": command.action,
|
||
"params": command.params
|
||
}
|
||
|
||
result = await ws_hub.send_command(device_id, msg, timeout)
|
||
|
||
return {
|
||
"success": result.get("code", 500) == 200,
|
||
"device_id": device_id,
|
||
"result": result
|
||
}
|