55 lines
2.0 KiB
Python
55 lines
2.0 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 = 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):
|
||
|
|
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
|
||
|
|
|