main.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import logging
  2. from contextlib import asynccontextmanager
  3. from fastapi import FastAPI
  4. from app.api import api_router
  5. from app.services import CameraUnavailableError, get_camera_service
  6. from app.core.config import settings
  7. logging.basicConfig(level=logging.INFO)
  8. logger = logging.getLogger(__name__)
  9. @asynccontextmanager
  10. async def lifespan(_: FastAPI):
  11. """
  12. FastAPI 生命周期管理。
  13. 启动阶段会尝试预热相机,这样第一次请求拍照时更快。
  14. 但这里不会因为相机异常而阻止整个服务启动,
  15. 因为有时你可能还需要先看接口文档、做健康检查或排查环境。
  16. """
  17. camera_service = get_camera_service()
  18. try:
  19. camera_service.initialize()
  20. logger.info("树莓派相机预热完成。")
  21. except CameraUnavailableError as exc:
  22. logger.warning("相机预热失败,拍照接口暂时不可用:%s", exc)
  23. try:
  24. yield
  25. finally:
  26. camera_service.close()
  27. logger.info("相机资源已关闭。")
  28. app = FastAPI(
  29. title=settings.app.title,
  30. version=settings.app.version,
  31. description=settings.app.description,
  32. lifespan=lifespan,
  33. )
  34. app.include_router(api_router, prefix="/api")
  35. @app.get("/", summary="服务入口")
  36. def read_root() -> dict[str, str]:
  37. """
  38. 服务入口说明。
  39. 这里返回最基础的服务信息,方便你确认服务已启动,
  40. 也方便后续再逐步加入更多模块说明。
  41. """
  42. return {
  43. "message": "Raspberry Pi Camera API is running.",
  44. "docs": "/docs",
  45. }
  46. @app.get("/health", summary="健康检查")
  47. def health_check() -> dict[str, object]:
  48. """
  49. 健康检查接口。
  50. 这个接口不强依赖相机真实可用,只返回服务当前状态和相机是否已初始化。
  51. 在部署脚本、容器探针或反向代理检查中都比较实用。
  52. """
  53. camera_service = get_camera_service()
  54. return {
  55. "status": "ok",
  56. "camera_initialized": camera_service.is_initialized,
  57. "app_name": settings.app.title,
  58. "app_version": settings.app.version,
  59. }