import datetime import logging import os import time from functools import reduce import cv2 import numpy as np from flask import (Blueprint, Flask, Response, current_app, jsonify, make_response, request) from peewee import SqliteDatabase, operator, fn from playhouse.shortcuts import model_to_dict from frigate.models import Event bp = Blueprint('frigate', __name__) def create_app(frigate_config, database: SqliteDatabase, camera_metrics, detectors, detected_frames_processor): app = Flask(__name__) log = logging.getLogger('werkzeug') log.setLevel(logging.INFO) @app.before_request def _db_connect(): database.connect() @app.teardown_request def _db_close(exc): if not database.is_closed(): database.close() app.frigate_config = frigate_config app.camera_metrics = camera_metrics app.detectors = detectors app.detected_frames_processor = detected_frames_processor app.register_blueprint(bp) return app @bp.route('/') def is_healthy(): return "Frigate is running. Alive and healthy!" @bp.route('/events/summary') def events_summary(): groups = ( Event .select( Event.camera, Event.label, fn.strftime('%Y-%m-%d', fn.datetime(Event.start_time, 'unixepoch', 'localtime')).alias('day'), Event.zones, fn.COUNT(Event.id).alias('count') ) .group_by( Event.camera, Event.label, fn.strftime('%Y-%m-%d', fn.datetime(Event.start_time, 'unixepoch', 'localtime')), Event.zones ) ) return jsonify([e for e in groups.dicts()]) @bp.route('/events/') def event(id): return model_to_dict(Event.get(Event.id == id)) @bp.route('/events') def events(): limit = request.args.get('limit', 100) camera = request.args.get('camera') label = request.args.get('label') zone = request.args.get('zone') after = request.args.get('after', type=int) before = request.args.get('before', type=int) clauses = [] if camera: clauses.append((Event.camera == camera)) if label: clauses.append((Event.label == label)) if zone: clauses.append((Event.zones.cast('text') % f"*\"{zone}\"*")) if after: clauses.append((Event.start_time >= after)) if before: clauses.append((Event.start_time <= before)) if len(clauses) == 0: clauses.append((1 == 1)) events = (Event.select() .where(reduce(operator.and_, clauses)) .order_by(Event.start_time.desc()) .limit(limit)) return jsonify([model_to_dict(e) for e in events]) @bp.route('/config') def config(): return jsonify(current_app.frigate_config.to_dict()) @bp.route('/stats') def stats(): camera_metrics = current_app.camera_metrics stats = {} total_detection_fps = 0 for name, camera_stats in camera_metrics.items(): total_detection_fps += camera_stats['detection_fps'].value stats[name] = { 'camera_fps': round(camera_stats['camera_fps'].value, 2), 'process_fps': round(camera_stats['process_fps'].value, 2), 'skipped_fps': round(camera_stats['skipped_fps'].value, 2), 'detection_fps': round(camera_stats['detection_fps'].value, 2), 'pid': camera_stats['process'].pid, 'capture_pid': camera_stats['capture_process'].pid } stats['detectors'] = {} for name, detector in current_app.detectors.items(): stats['detectors'][name] = { 'inference_speed': round(detector.avg_inference_speed.value*1000, 2), 'detection_start': detector.detection_start.value, 'pid': detector.detect_process.pid } stats['detection_fps'] = round(total_detection_fps, 2) return jsonify(stats) @bp.route('//