feat(fish_api): SQLite 快照投递、日志与 watch 空闲告警
- 新增 SQLite:measure/health 快照、delivery_cursor 单消费者 pop;clear/start_fresh 可清空库 - biomass GET 仅返回约定 data 字段,X-Fish-Biomass-New 表示是否有新快照;poller 读响应头 - loguru 桥接 uvicorn,子进程 stdout 流式输出;format_json_pretty 与算法摘要日志 - measure/action watch 无新任务时限流 WARNING;watch_idle 共用逻辑 - 依赖 loguru;新增 db、logging_config、subprocess_run、watch_idle、启动脚本 FishMeasure: 更新 fish_video_weight_evaluation 与 predict_weigth_from_svo2;移除未用 refbox/segmentation 脚本 Made-with: Cursor
This commit is contained in:
@@ -1,55 +1,101 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import APIRouter, Depends
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
from app.state import app_state
|
||||
from app.db import pop_next_health, pop_next_measure
|
||||
from app.settings import Settings, get_settings
|
||||
|
||||
router = APIRouter(prefix="/api/v1/biomass", tags=["biomass"])
|
||||
|
||||
# 是否有新快照被本次 GET 消费(1/0);body 保持与客户端约定字段一致,不写入 has_new。
|
||||
HEADER_BIOMASS_NEW = "X-Fish-Biomass-New"
|
||||
|
||||
|
||||
def _new_headers(has_new: bool) -> dict[str, str]:
|
||||
return {HEADER_BIOMASS_NEW: "1" if has_new else "0"}
|
||||
|
||||
|
||||
@router.get("/real/camera/")
|
||||
async def get_real_camera():
|
||||
"""双目实时结果(轮询最新一次 FishMeasure 完成快照)。"""
|
||||
m = app_state.last_measure
|
||||
if m.error:
|
||||
return {
|
||||
"code": 500,
|
||||
"msg": m.error,
|
||||
"data": {
|
||||
"result": [],
|
||||
"video_left": "",
|
||||
"video_right": "",
|
||||
async def get_real_camera(settings: Settings = Depends(get_settings)):
|
||||
"""双目实时结果:每次 GET 投递下一条未消费的 FishMeasure 快照(SQLite 游标)。"""
|
||||
m, has_new, _ = pop_next_measure(settings)
|
||||
if not has_new:
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"result": [],
|
||||
"video_left": "",
|
||||
"video_right": "",
|
||||
},
|
||||
},
|
||||
headers=_new_headers(False),
|
||||
)
|
||||
if m.error:
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 500,
|
||||
"msg": m.error,
|
||||
"data": {
|
||||
"result": [],
|
||||
"video_left": "",
|
||||
"video_right": "",
|
||||
},
|
||||
},
|
||||
headers=_new_headers(True),
|
||||
)
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"result": m.result,
|
||||
"video_left": m.video_left,
|
||||
"video_right": m.video_right,
|
||||
},
|
||||
}
|
||||
return {
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"result": m.result,
|
||||
"video_left": m.video_left,
|
||||
"video_right": m.video_right,
|
||||
},
|
||||
}
|
||||
headers=_new_headers(True),
|
||||
)
|
||||
|
||||
|
||||
@router.get("/health/result/")
|
||||
async def get_health_result():
|
||||
"""行为 / 健康结果(轮询最新一次 FishAction 完成快照)。"""
|
||||
h = app_state.last_health
|
||||
if h.error:
|
||||
return {
|
||||
"code": 500,
|
||||
"msg": h.error,
|
||||
"data": {
|
||||
"behavior_result": "",
|
||||
"health_result": "",
|
||||
async def get_health_result(settings: Settings = Depends(get_settings)):
|
||||
"""行为 / 健康结果:每次 GET 投递下一条未消费的 FishAction 快照(SQLite 游标)。"""
|
||||
h, has_new, _ = pop_next_health(settings)
|
||||
if not has_new:
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"behavior_result": "",
|
||||
"health_result": "",
|
||||
},
|
||||
},
|
||||
headers=_new_headers(False),
|
||||
)
|
||||
if h.error:
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 500,
|
||||
"msg": h.error,
|
||||
"data": {
|
||||
"behavior_result": "",
|
||||
"health_result": "",
|
||||
},
|
||||
},
|
||||
headers=_new_headers(True),
|
||||
)
|
||||
return JSONResponse(
|
||||
content={
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"behavior_result": h.behavior_result,
|
||||
"health_result": h.health_result,
|
||||
},
|
||||
}
|
||||
return {
|
||||
"code": 200,
|
||||
"msg": "成功",
|
||||
"data": {
|
||||
"behavior_result": h.behavior_result,
|
||||
"health_result": h.health_result,
|
||||
},
|
||||
}
|
||||
headers=_new_headers(True),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user