api.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """FastAPI 服务入口。
  2. 该模块负责:
  3. 1. 从环境变量加载配置;
  4. 2. 初始化测高服务;
  5. 3. 注册生命周期事件与 HTTP 路由;
  6. 4. 启动 Uvicorn 服务。
  7. """
  8. import os
  9. import uvicorn
  10. from fastapi import FastAPI, HTTPException
  11. from fastapi.staticfiles import StaticFiles
  12. from api_config import ApiConfig
  13. from cargo_service import CargoHeightService
  14. from request_logging import setup_request_logging
  15. # 读取配置并创建核心服务实例。
  16. config = ApiConfig.from_env()
  17. service = CargoHeightService(config)
  18. # 创建 Web 应用对象。
  19. app = FastAPI(title="Cargo Height API")
  20. # 安装请求日志中间件,用于记录每次 API 调用的响应与耗时。
  21. setup_request_logging(
  22. app,
  23. max_response_len=config.request_log_max_len,
  24. max_bytes=config.request_log_max_bytes,
  25. backup_count=config.request_log_backup_count,
  26. )
  27. # 暴露本地样例图片目录,便于通过 HTTP 直接访问保存的测量图像。
  28. sample_images_dir = os.path.join(os.getcwd(), "sample_images")
  29. os.makedirs(sample_images_dir, exist_ok=True)
  30. app.mount("/sample_images", StaticFiles(directory=sample_images_dir), name="sample_images")
  31. @app.on_event("startup")
  32. def on_startup() -> None:
  33. """应用启动时初始化相机管线与滤波器等资源。"""
  34. service.startup()
  35. @app.on_event("shutdown")
  36. def on_shutdown() -> None:
  37. """应用关闭时释放相机资源,避免设备占用。"""
  38. service.shutdown()
  39. @app.get("/height")
  40. def get_height():
  41. """执行一次测高流程并返回结果。
  42. 返回值中包含:
  43. - `height_mm`: 估计高度(毫米);
  44. - `samples`: 本次采样的原始距离列表;
  45. - `image_paths`: 相关彩色图与深度标注图路径。
  46. """
  47. result = service.measure_height()
  48. if result is None:
  49. # 采样不足时返回 503,表示服务暂时无法给出有效结果。
  50. raise HTTPException(status_code=503, detail="Insufficient valid samples from depth camera")
  51. return result
  52. @app.get("/health")
  53. def health():
  54. """健康检查接口,用于探活。"""
  55. return {"status": "ok"}
  56. def main() -> None:
  57. """启动 Uvicorn 服务器。"""
  58. uvicorn.run("api:app", host=config.api_host, port=config.api_port, log_level="info")
  59. if __name__ == "__main__":
  60. main()