72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
"""基础业务路由(仿真/设备/文件下载等)。
|
||
|
||
该文件保留项目早期的示例接口与基础能力:
|
||
- 健康检查
|
||
- 设备连接状态(示例)
|
||
- 启停仿真
|
||
- 文件下载(带目录穿越保护)
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from pathlib import Path
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException
|
||
from fastapi.responses import FileResponse
|
||
|
||
from backend.api.schemas import HealthResponse, SimulationStartRequest, SimulationStartResponse, SimulationStopResponse
|
||
from backend.services.simulation_manager import SimulationManager
|
||
from backend.utils import safe_join
|
||
|
||
|
||
def get_router(simulation_manager: SimulationManager, file_root: Path) -> APIRouter:
|
||
"""构造基础业务路由。
|
||
|
||
说明:此项目采用“router 工厂函数”风格,通过参数注入 service/配置,而不是全局依赖容器。
|
||
"""
|
||
router = APIRouter()
|
||
|
||
@router.get("/health", response_model=HealthResponse)
|
||
async def health() -> HealthResponse:
|
||
"""健康检查(用于容器编排/负载均衡探活)。"""
|
||
return HealthResponse()
|
||
|
||
@router.get("/api/devices")
|
||
async def devices():
|
||
"""返回设备列表(当前为示例数据,反映仿真运行时状态)。"""
|
||
runtime = simulation_manager.current()
|
||
return {
|
||
"data": [
|
||
{
|
||
"device_id": "controlbox_01",
|
||
"device_type": "mock_vehicle",
|
||
"connected": bool(runtime and runtime.status == "running"),
|
||
}
|
||
]
|
||
}
|
||
|
||
@router.post("/api/simulation/start", response_model=SimulationStartResponse)
|
||
async def start_simulation(body: SimulationStartRequest) -> SimulationStartResponse:
|
||
"""启动仿真。"""
|
||
simulation_id = await simulation_manager.start(body.model_dump())
|
||
return SimulationStartResponse(simulation_id=simulation_id)
|
||
|
||
@router.post("/api/simulation/{simulation_id}/stop", response_model=SimulationStopResponse)
|
||
async def stop_simulation(simulation_id: str) -> SimulationStopResponse:
|
||
"""停止仿真。"""
|
||
await simulation_manager.stop(simulation_id)
|
||
return SimulationStopResponse(simulation_id=simulation_id, status="stopped")
|
||
|
||
@router.get("/files/{file_path:path}")
|
||
async def files(file_path: str):
|
||
"""下载文件(相对 file_root),并校验路径合法性。"""
|
||
try:
|
||
resolved = safe_join(file_root, file_path)
|
||
except ValueError:
|
||
raise HTTPException(status_code=400, detail="invalid path")
|
||
if not resolved.exists() or not resolved.is_file():
|
||
raise HTTPException(status_code=404, detail="not found")
|
||
return FileResponse(str(resolved))
|
||
|
||
return router
|