from datetime import datetime from typing import List, Optional from sqlalchemy.orm import Session from db.models import Camera, CameraStatus, ROI, Alarm def get_all_cameras(db: Session, enabled_only: bool = True) -> List[Camera]: query = db.query(Camera) if enabled_only: query = query.filter(Camera.enabled == True) return query.all() def get_camera_by_id(db: Session, camera_id: int) -> Optional[Camera]: return db.query(Camera).filter(Camera.id == camera_id).first() def create_camera( db: Session, name: str, rtsp_url: str, fps_limit: int = 30, process_every_n_frames: int = 3, ) -> Camera: camera = Camera( name=name, rtsp_url=rtsp_url, fps_limit=fps_limit, process_every_n_frames=process_every_n_frames, ) db.add(camera) db.commit() db.refresh(camera) return camera def update_camera( db: Session, camera_id: int, name: Optional[str] = None, rtsp_url: Optional[str] = None, fps_limit: Optional[int] = None, process_every_n_frames: Optional[int] = None, enabled: Optional[bool] = None, ) -> Optional[Camera]: camera = get_camera_by_id(db, camera_id) if not camera: return None if name is not None: camera.name = name if rtsp_url is not None: camera.rtsp_url = rtsp_url if fps_limit is not None: camera.fps_limit = fps_limit if process_every_n_frames is not None: camera.process_every_n_frames = process_every_n_frames if enabled is not None: camera.enabled = enabled db.commit() db.refresh(camera) return camera def delete_camera(db: Session, camera_id: int) -> bool: camera = get_camera_by_id(db, camera_id) if not camera: return False db.delete(camera) db.commit() return True def get_camera_status(db: Session, camera_id: int) -> Optional[CameraStatus]: return ( db.query(CameraStatus).filter(CameraStatus.camera_id == camera_id).first() ) def update_camera_status( db: Session, camera_id: int, is_running: Optional[bool] = None, fps: Optional[float] = None, error_message: Optional[str] = None, ) -> Optional[CameraStatus]: status = get_camera_status(db, camera_id) if not status: status = CameraStatus(camera_id=camera_id) db.add(status) if is_running is not None: status.is_running = is_running if fps is not None: status.fps = fps if error_message is not None: status.error_message = error_message status.last_check_time = datetime.utcnow() db.commit() db.refresh(status) return status def get_all_rois(db: Session, camera_id: Optional[int] = None) -> List[ROI]: query = db.query(ROI) if camera_id is not None: query = query.filter(ROI.camera_id == camera_id) return query.filter(ROI.enabled == True).all() def get_roi_by_id(db: Session, roi_id: int) -> Optional[ROI]: return db.query(ROI).filter(ROI.id == roi_id).first() def get_roi_by_roi_id(db: Session, camera_id: int, roi_id: str) -> Optional[ROI]: return ( db.query(ROI) .filter(ROI.camera_id == camera_id, ROI.roi_id == roi_id) .first() ) def create_roi( db: Session, camera_id: int, 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, ) -> ROI: import json roi = ROI( camera_id=camera_id, roi_id=roi_id, name=name, roi_type=roi_type, points=json.dumps(points), rule_type=rule_type, direction=direction, stay_time=stay_time, threshold_sec=threshold_sec, confirm_sec=confirm_sec, return_sec=return_sec, ) db.add(roi) db.commit() db.refresh(roi) return roi def update_roi( db: Session, roi_id: int, name: 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, ) -> Optional[ROI]: import json roi = get_roi_by_id(db, roi_id) if not roi: return None if name is not None: roi.name = name if points is not None: roi.points = json.dumps(points) if rule_type is not None: roi.rule_type = rule_type if direction is not None: roi.direction = direction if stay_time is not None: roi.stay_time = stay_time if enabled is not None: roi.enabled = enabled if threshold_sec is not None: roi.threshold_sec = threshold_sec if confirm_sec is not None: roi.confirm_sec = confirm_sec if return_sec is not None: roi.return_sec = return_sec db.commit() db.refresh(roi) return roi def delete_roi(db: Session, roi_id: int) -> bool: roi = get_roi_by_id(db, roi_id) if not roi: return False db.delete(roi) db.commit() return True def get_roi_points(db: Session, camera_id: int) -> List[dict]: import json rois = get_all_rois(db, camera_id) return [ { "id": roi.id, "roi_id": roi.roi_id, "name": roi.name, "type": roi.roi_type, "points": json.loads(roi.points), "rule": roi.rule_type, "direction": roi.direction, "stay_time": roi.stay_time, "enabled": roi.enabled, "threshold_sec": roi.threshold_sec, "confirm_sec": roi.confirm_sec, "return_sec": roi.return_sec, } for roi in rois ] def create_alarm( db: Session, camera_id: int, event_type: str, confidence: float = 0.0, snapshot_path: Optional[str] = None, roi_id: Optional[str] = None, llm_checked: bool = False, llm_result: Optional[str] = None, ) -> Alarm: alarm = Alarm( camera_id=camera_id, roi_id=roi_id, event_type=event_type, confidence=confidence, snapshot_path=snapshot_path, llm_checked=llm_checked, llm_result=llm_result, ) db.add(alarm) db.commit() db.refresh(alarm) return alarm def get_alarms( db: Session, camera_id: Optional[int] = None, event_type: Optional[str] = None, limit: int = 100, offset: int = 0, ) -> List[Alarm]: query = db.query(Alarm) if camera_id is not None: query = query.filter(Alarm.camera_id == camera_id) if event_type is not None: query = query.filter(Alarm.event_type == event_type) return query.order_by(Alarm.created_at.desc()).offset(offset).limit(limit).all() def update_alarm( db: Session, alarm_id: int, llm_checked: Optional[bool] = None, llm_result: Optional[str] = None, processed: Optional[bool] = None, ) -> Optional[Alarm]: alarm = db.query(Alarm).filter(Alarm.id == alarm_id).first() if not alarm: return None if llm_checked is not None: alarm.llm_checked = llm_checked if llm_result is not None: alarm.llm_result = llm_result if processed is not None: alarm.processed = processed db.commit() db.refresh(alarm) return alarm def get_alarm_stats(db: Session) -> dict: total = db.query(Alarm).count() unprocessed = db.query(Alarm).filter(Alarm.processed == False).count() llm_pending = db.query(Alarm).filter( Alarm.llm_checked == False, Alarm.processed == False ).count() return { "total": total, "unprocessed": unprocessed, "llm_pending": llm_pending, }