"""ZED 分段录制 HTTP 控制(响应格式对齐 biomass:code/msg/data;不校验 ingest API Key)。""" from __future__ import annotations from typing import Any, Dict, Optional from fastapi import APIRouter, Body, Depends from pydantic import BaseModel, Field from starlette.responses import JSONResponse from app.services.zed_recording_control import ( start_zed_recording, stop_zed_recording, zed_recording_is_running, ) from app.settings import Settings, get_settings from app.state import app_state router = APIRouter(prefix="/api/v1/zed/recording", tags=["zed-recording"]) def _ok(data: Dict[str, Any], msg: str = "成功") -> JSONResponse: return JSONResponse( content={ "code": 200, "msg": msg, "data": data, } ) def _err( http_status: int, *, code: int, msg: str, data: Optional[Dict[str, Any]] = None, ) -> JSONResponse: body: Dict[str, Any] = {"code": code, "msg": msg} if data is not None: body["data"] = data return JSONResponse(status_code=http_status, content=body) class ZedRecordingStartRequest(BaseModel): """可选覆盖分段时长;``fish_id`` 由服务端每次启动在库中递增分配。""" segment_sec: Optional[float] = Field( None, ge=1.0, description="每段时长(秒);缺省使用 ZED_SVO_SEGMENT_SEC", ) @router.get("/status") async def zed_recording_status() -> JSONResponse: data: Dict[str, Any] = {"running": zed_recording_is_running()} if app_state.zed_recording_fish_id is not None: data["fish_id"] = app_state.zed_recording_fish_id return _ok(data) @router.post("/start") async def zed_recording_start( body: ZedRecordingStartRequest = Body(default_factory=ZedRecordingStartRequest), settings: Settings = Depends(get_settings), ) -> JSONResponse: ok, msg, fish_id, _ = start_zed_recording( settings, segment_sec=body.segment_sec, ) if not ok: if msg == "already_running": return _err( 409, code=409, msg="已在录制中", data={"ok": False, "message": "已在录制中"}, ) if msg.startswith("session_db_error:"): return _err( 500, code=500, msg="写入录制会话失败", data={"ok": False, "message": msg}, ) return _err( 500, code=500, msg="启动录制失败", data={"ok": False, "message": msg}, ) return _ok( { "ok": True, "message": "录制开始", "fish_id": fish_id, } ) @router.post("/stop") async def zed_recording_stop(settings: Settings = Depends(get_settings)) -> JSONResponse: ok, msg, fish_id = stop_zed_recording(settings) if not ok: if msg == "not_running": return _ok({"ok": False, "message": "未在录制"}, msg="未在录制") if msg == "stop_timeout": return _err( 504, code=504, msg="停止超时", data={"ok": False, "message": "停止超时"}, ) return _err( 500, code=500, msg="停止录制失败", data={"ok": False, "message": msg}, ) out: Dict[str, Any] = {"ok": True, "message": "录制停止"} if fish_id is not None: out["fish_id"] = fish_id return _ok(out)