180 lines
6.0 KiB
Python
180 lines
6.0 KiB
Python
from fastapi import FastAPI, HTTPException
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
from datetime import datetime
|
||
from typing import Optional
|
||
import json
|
||
from concurrent.futures import ThreadPoolExecutor
|
||
from .config import create_redis_connections
|
||
from .models import (
|
||
get_camera_data_by_date,
|
||
background_generate_report
|
||
)
|
||
|
||
app = FastAPI()
|
||
|
||
# 配置CORS
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=["*"],
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
# 创建线程池执行器
|
||
executor = ThreadPoolExecutor(max_workers=3)
|
||
|
||
# 用于跟踪报告生成任务的状态
|
||
report_tasks = {}
|
||
|
||
# 创建Redis连接池
|
||
redis_connections = create_redis_connections()
|
||
|
||
@app.get("/web/face/{camera_id}/data")
|
||
async def get_camera_data(camera_id: str, date: Optional[str] = None):
|
||
"""获取摄像头人脸数据"""
|
||
if date is None:
|
||
date = datetime.now().strftime("%Y%m%d")
|
||
return await get_camera_data_by_date(camera_id, date, redis_connections[camera_id], is_face=True)
|
||
|
||
@app.get("/web/{camera_id}/data")
|
||
async def get_camera_data(camera_id: str, date: Optional[str] = None):
|
||
"""获取摄像头行为数据"""
|
||
if date is None:
|
||
date = datetime.now().strftime("%Y%m%d")
|
||
return await get_camera_data_by_date(camera_id, date, redis_connections[camera_id])
|
||
|
||
@app.get("/web/report/{date}")
|
||
async def get_report_by_date(date: str):
|
||
"""获取指定日期的分析报告"""
|
||
try:
|
||
print(f"\n=== 开始处理日期: {date} ===")
|
||
try:
|
||
parsed_date = datetime.strptime(date, "%Y-%m-%d")
|
||
date_no_hyphen = parsed_date.strftime("%Y%m%d")
|
||
print(f"转换后的日期格式: {date_no_hyphen}")
|
||
except ValueError:
|
||
raise HTTPException(
|
||
status_code=400,
|
||
detail="Invalid date format. Please use YYYY-MM-DD"
|
||
)
|
||
|
||
report_redis = redis_connections["report"]
|
||
report_key = f"report_{date_no_hyphen}"
|
||
task_key = f"task_status_{date_no_hyphen}"
|
||
print(f"缓存键: {report_key}")
|
||
|
||
cached_report = report_redis.get(report_key)
|
||
print(f"是否有缓存: {'是' if cached_report else '否'}")
|
||
|
||
if cached_report:
|
||
print("返回缓存数据")
|
||
return {
|
||
"message": "success",
|
||
"data": json.loads(cached_report),
|
||
"source": "cache"
|
||
}
|
||
|
||
task_status_json = report_redis.get(task_key)
|
||
if task_status_json:
|
||
task_status = json.loads(task_status_json)
|
||
if task_status["status"] == "running":
|
||
return {
|
||
"message": "processing",
|
||
"detail": "报告正在生成中,请稍后再试"
|
||
}
|
||
elif task_status["status"] == "completed":
|
||
report_data = report_redis.get(report_key)
|
||
if report_data:
|
||
return {
|
||
"message": "success",
|
||
"data": json.loads(report_data),
|
||
"source": "new_generation"
|
||
}
|
||
else:
|
||
return {
|
||
"message": "no_data",
|
||
"detail": "暂无数据"
|
||
}
|
||
elif task_status["status"] == "failed":
|
||
return {
|
||
"message": "error",
|
||
"detail": f"报告生成失败: {task_status.get('error', '未知错误')}"
|
||
}
|
||
|
||
print("启动后台任务生成报告...")
|
||
executor.submit(background_generate_report, date_no_hyphen, redis_connections)
|
||
|
||
return {
|
||
"message": "processing",
|
||
"detail": "报告正在生成中,请稍后再试"
|
||
}
|
||
|
||
except Exception as e:
|
||
print(f"Error processing report request: {str(e)}")
|
||
import traceback
|
||
print(f"详细错误信息: {traceback.format_exc()}")
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"处理报告时发生错误: {str(e)}\n错误类型: {type(e)}"
|
||
)
|
||
|
||
@app.get("/web/report/download/{date}")
|
||
async def download_report(date: str):
|
||
"""下载指定日期的分析报告"""
|
||
try:
|
||
try:
|
||
parsed_date = datetime.strptime(date, "%Y-%m-%d")
|
||
date_no_hyphen = parsed_date.strftime("%Y%m%d")
|
||
except ValueError:
|
||
error_msg = "日期格式必须为YYYY-MM-DD(例如:2024-12-31)"
|
||
print(f"日期格式错误: {error_msg}")
|
||
raise HTTPException(
|
||
status_code=400,
|
||
detail=error_msg
|
||
)
|
||
|
||
report_key = f"report_{date_no_hyphen}"
|
||
report_redis = redis_connections["report"]
|
||
|
||
report_data = report_redis.get(report_key)
|
||
if not report_data:
|
||
error_msg = f"未找到 {date} 的报告数据,请先生成报告"
|
||
print(error_msg)
|
||
raise HTTPException(
|
||
status_code=404,
|
||
detail=error_msg
|
||
)
|
||
|
||
try:
|
||
data = json.loads(report_data)
|
||
if "hourly_distribution" in data:
|
||
del data["hourly_distribution"]
|
||
|
||
print("成功获取报告数据")
|
||
return {
|
||
"message": "success",
|
||
"data": data
|
||
}
|
||
except json.JSONDecodeError as je:
|
||
error_msg = f"报告数据格式错误: {str(je)}"
|
||
print(error_msg)
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=error_msg
|
||
)
|
||
|
||
except HTTPException as he:
|
||
raise he
|
||
except Exception as e:
|
||
error_msg = f"处理请求时发生错误: {str(e)}"
|
||
print(error_msg)
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=error_msg
|
||
)
|
||
|
||
if __name__ == "__main__":
|
||
import uvicorn
|
||
uvicorn.run(app, host="0.0.0.0", port=6005)
|