feat(db): add missing columns for cloud sync and alarm region data
This commit is contained in:
90
api/roi.py
90
api/roi.py
@@ -1,7 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException, Body
|
||||||
|
from pydantic import BaseModel
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from db.crud import (
|
from db.crud import (
|
||||||
@@ -20,6 +21,32 @@ from inference.roi.roi_filter import ROIFilter
|
|||||||
router = APIRouter(prefix="/api/camera", tags=["ROI管理"])
|
router = APIRouter(prefix="/api/camera", tags=["ROI管理"])
|
||||||
|
|
||||||
|
|
||||||
|
class CreateROIRequest(BaseModel):
|
||||||
|
roi_id: str
|
||||||
|
name: str
|
||||||
|
roi_type: str
|
||||||
|
points: List[List[float]]
|
||||||
|
rule_type: str
|
||||||
|
direction: Optional[str] = None
|
||||||
|
stay_time: Optional[int] = None
|
||||||
|
threshold_sec: int = 360
|
||||||
|
confirm_sec: int = 30
|
||||||
|
return_sec: int = 5
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateROIRequest(BaseModel):
|
||||||
|
name: Optional[str] = None
|
||||||
|
roi_type: Optional[str] = None
|
||||||
|
points: Optional[List[List[float]]] = None
|
||||||
|
rule_type: Optional[str] = None
|
||||||
|
direction: Optional[str] = None
|
||||||
|
stay_time: Optional[int] = None
|
||||||
|
enabled: Optional[bool] = None
|
||||||
|
threshold_sec: Optional[int] = None
|
||||||
|
confirm_sec: Optional[int] = None
|
||||||
|
return_sec: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
def _invalidate_roi_cache(camera_id: int):
|
def _invalidate_roi_cache(camera_id: int):
|
||||||
pipeline = get_pipeline()
|
pipeline = get_pipeline()
|
||||||
pipeline.roi_filter.clear_cache(camera_id)
|
pipeline.roi_filter.clear_cache(camera_id)
|
||||||
@@ -72,31 +99,22 @@ def get_roi(camera_id: int, roi_id: int, db: Session = Depends(get_db)):
|
|||||||
@router.post("/{camera_id}/roi", response_model=dict)
|
@router.post("/{camera_id}/roi", response_model=dict)
|
||||||
def add_roi(
|
def add_roi(
|
||||||
camera_id: int,
|
camera_id: int,
|
||||||
roi_id: str,
|
request: CreateROIRequest,
|
||||||
name: str,
|
|
||||||
roi_type: str,
|
|
||||||
points: List[List[float]],
|
|
||||||
rule_type: str,
|
|
||||||
direction: Optional[str] = None,
|
|
||||||
stay_time: Optional[int] = None,
|
|
||||||
threshold_sec: int = 360,
|
|
||||||
confirm_sec: int = 30,
|
|
||||||
return_sec: int = 5,
|
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
roi = create_roi(
|
roi = create_roi(
|
||||||
db,
|
db,
|
||||||
camera_id=camera_id,
|
camera_id=camera_id,
|
||||||
roi_id=roi_id,
|
roi_id=request.roi_id,
|
||||||
name=name,
|
name=request.name,
|
||||||
roi_type=roi_type,
|
roi_type=request.roi_type,
|
||||||
points=points,
|
points=request.points,
|
||||||
rule_type=rule_type,
|
rule_type=request.rule_type,
|
||||||
direction=direction,
|
direction=request.direction,
|
||||||
stay_time=stay_time,
|
stay_time=request.stay_time,
|
||||||
threshold_sec=threshold_sec,
|
threshold_sec=request.threshold_sec,
|
||||||
confirm_sec=confirm_sec,
|
confirm_sec=request.confirm_sec,
|
||||||
return_sec=return_sec,
|
return_sec=request.return_sec,
|
||||||
)
|
)
|
||||||
|
|
||||||
_invalidate_roi_cache(camera_id)
|
_invalidate_roi_cache(camera_id)
|
||||||
@@ -106,7 +124,7 @@ def add_roi(
|
|||||||
"roi_id": roi.roi_id,
|
"roi_id": roi.roi_id,
|
||||||
"name": roi.name,
|
"name": roi.name,
|
||||||
"type": roi.roi_type,
|
"type": roi.roi_type,
|
||||||
"points": points,
|
"points": request.points,
|
||||||
"rule": roi.rule_type,
|
"rule": roi.rule_type,
|
||||||
"enabled": roi.enabled,
|
"enabled": roi.enabled,
|
||||||
}
|
}
|
||||||
@@ -116,29 +134,21 @@ def add_roi(
|
|||||||
def modify_roi(
|
def modify_roi(
|
||||||
camera_id: int,
|
camera_id: int,
|
||||||
roi_id: int,
|
roi_id: int,
|
||||||
name: Optional[str] = None,
|
request: UpdateROIRequest,
|
||||||
points: Optional[List[List[float]]] = None,
|
|
||||||
rule_type: Optional[str] = None,
|
|
||||||
direction: Optional[str] = None,
|
|
||||||
stay_time: Optional[int] = None,
|
|
||||||
enabled: Optional[bool] = None,
|
|
||||||
threshold_sec: Optional[int] = None,
|
|
||||||
confirm_sec: Optional[int] = None,
|
|
||||||
return_sec: Optional[int] = None,
|
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
roi = update_roi(
|
roi = update_roi(
|
||||||
db,
|
db,
|
||||||
roi_id=roi_id,
|
roi_id=roi_id,
|
||||||
name=name,
|
name=request.name,
|
||||||
points=points,
|
points=request.points,
|
||||||
rule_type=rule_type,
|
rule_type=request.rule_type,
|
||||||
direction=direction,
|
direction=request.direction,
|
||||||
stay_time=stay_time,
|
stay_time=request.stay_time,
|
||||||
enabled=enabled,
|
enabled=request.enabled,
|
||||||
threshold_sec=threshold_sec,
|
threshold_sec=request.threshold_sec,
|
||||||
confirm_sec=confirm_sec,
|
confirm_sec=request.confirm_sec,
|
||||||
return_sec=return_sec,
|
return_sec=request.return_sec,
|
||||||
)
|
)
|
||||||
if not roi:
|
if not roi:
|
||||||
raise HTTPException(status_code=404, detail="ROI不存在")
|
raise HTTPException(status_code=404, detail="ROI不存在")
|
||||||
|
|||||||
71
migrate_db.py
Normal file
71
migrate_db.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
db_path = 'security_monitor.db'
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
def add_column(table_name, col_name, col_type, default_value=None):
|
||||||
|
try:
|
||||||
|
if default_value:
|
||||||
|
cursor.execute(f'ALTER TABLE {table_name} ADD COLUMN {col_name} {col_type} DEFAULT {default_value}')
|
||||||
|
else:
|
||||||
|
cursor.execute(f'ALTER TABLE {table_name} ADD COLUMN {col_name} {col_type}')
|
||||||
|
print(f'添加列 {table_name}.{col_name} 成功')
|
||||||
|
return True
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
if 'duplicate column name' in str(e):
|
||||||
|
print(f'列 {table_name}.{col_name} 已存在')
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f'添加列 {table_name}.{col_name} 失败: {e}')
|
||||||
|
return False
|
||||||
|
|
||||||
|
print('=== 数据库迁移脚本 ===')
|
||||||
|
print()
|
||||||
|
|
||||||
|
# cameras 表
|
||||||
|
print('更新 cameras 表:')
|
||||||
|
add_column('cameras', 'cloud_id', 'INTEGER')
|
||||||
|
add_column('cameras', 'pending_sync', 'BOOLEAN', '0')
|
||||||
|
add_column('cameras', 'sync_failed_at', 'TIMESTAMP')
|
||||||
|
add_column('cameras', 'sync_retry_count', 'INTEGER', '0')
|
||||||
|
print()
|
||||||
|
|
||||||
|
# rois 表
|
||||||
|
print('更新 rois 表:')
|
||||||
|
add_column('rois', 'cloud_id', 'INTEGER')
|
||||||
|
add_column('rois', 'pending_sync', 'BOOLEAN', '0')
|
||||||
|
add_column('rois', 'sync_failed_at', 'TIMESTAMP')
|
||||||
|
add_column('rois', 'sync_retry_count', 'INTEGER', '0')
|
||||||
|
add_column('rois', 'sync_version', 'INTEGER', '0')
|
||||||
|
print()
|
||||||
|
|
||||||
|
# alarms 表
|
||||||
|
print('更新 alarms 表:')
|
||||||
|
add_column('alarms', 'cloud_id', 'INTEGER')
|
||||||
|
add_column('alarms', 'upload_status', "TEXT", "'pending_upload'")
|
||||||
|
add_column('alarms', 'upload_retry_count', 'INTEGER', '0')
|
||||||
|
add_column('alarms', 'error_message', 'TEXT')
|
||||||
|
add_column('alarms', 'region_data', 'TEXT')
|
||||||
|
add_column('alarms', 'llm_checked', 'BOOLEAN', '0')
|
||||||
|
add_column('alarms', 'llm_result', 'TEXT')
|
||||||
|
add_column('alarms', 'processed', 'BOOLEAN', '0')
|
||||||
|
print()
|
||||||
|
|
||||||
|
# camera_status 表
|
||||||
|
print('更新 camera_status 表:')
|
||||||
|
add_column('camera_status', 'last_frame_time', 'TIMESTAMP')
|
||||||
|
print()
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# 验证表结构
|
||||||
|
print('=== 验证表结构 ===')
|
||||||
|
for table in ['cameras', 'rois', 'alarms', 'camera_status']:
|
||||||
|
cursor.execute(f'PRAGMA table_info({table})')
|
||||||
|
cols = [col[1] for col in cursor.fetchall()]
|
||||||
|
print(f'{table}: {len(cols)} 列')
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
print()
|
||||||
|
print('数据库迁移完成!')
|
||||||
Binary file not shown.
Reference in New Issue
Block a user