treewide: fix issues detected by ruff

This commit is contained in:
Martin Weinelt 2023-05-23 02:38:21 +02:00
parent b339f53bb4
commit 2807a229a2
No known key found for this signature in database
GPG Key ID: 87C1E9888F856759
39 changed files with 124 additions and 153 deletions

View File

@ -53,7 +53,7 @@ def start(id, num_detections, detection_queue, event):
frame_times = [] frame_times = []
for x in range(0, num_detections): for x in range(0, num_detections):
start_frame = datetime.datetime.now().timestamp() start_frame = datetime.datetime.now().timestamp()
detections = object_detector.detect(my_frame) object_detector.detect(my_frame)
frame_times.append(datetime.datetime.now().timestamp() - start_frame) frame_times.append(datetime.datetime.now().timestamp() - start_frame)
duration = datetime.datetime.now().timestamp() - start duration = datetime.datetime.now().timestamp() - start

View File

@ -1,13 +1,15 @@
import faulthandler import faulthandler
from flask import cli
faulthandler.enable()
import threading import threading
threading.current_thread().name = "frigate" from flask import cli
from frigate.app import FrigateApp from frigate.app import FrigateApp
faulthandler.enable()
threading.current_thread().name = "frigate"
cli.show_server_banner = lambda *x: None cli.show_server_banner = lambda *x: None
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -133,10 +133,10 @@ class FrigateApp:
for log, level in self.config.logger.logs.items(): for log, level in self.config.logger.logs.items():
logging.getLogger(log).setLevel(level.value.upper()) logging.getLogger(log).setLevel(level.value.upper())
if not "werkzeug" in self.config.logger.logs: if "werkzeug" not in self.config.logger.logs:
logging.getLogger("werkzeug").setLevel("ERROR") logging.getLogger("werkzeug").setLevel("ERROR")
if not "ws4py" in self.config.logger.logs: if "ws4py" not in self.config.logger.logs:
logging.getLogger("ws4py").setLevel("ERROR") logging.getLogger("ws4py").setLevel("ERROR")
def init_queues(self) -> None: def init_queues(self) -> None:
@ -294,7 +294,7 @@ class FrigateApp:
def start_video_output_processor(self) -> None: def start_video_output_processor(self) -> None:
output_processor = mp.Process( output_processor = mp.Process(
target=output_frames, target=output_frames,
name=f"output_processor", name="output_processor",
args=( args=(
self.config, self.config,
self.video_output_queue, self.video_output_queue,
@ -467,7 +467,7 @@ class FrigateApp:
self.stop() self.stop()
def stop(self) -> None: def stop(self) -> None:
logger.info(f"Stopping...") logger.info("Stopping...")
self.stop_event.set() self.stop_event.set()
for detector in self.detectors.values(): for detector in self.detectors.values():

View File

@ -72,7 +72,7 @@ class Dispatcher:
camera_name = topic.split("/")[-3] camera_name = topic.split("/")[-3]
command = topic.split("/")[-2] command = topic.split("/")[-2]
self._camera_settings_handlers[command](camera_name, payload) self._camera_settings_handlers[command](camera_name, payload)
except IndexError as e: except IndexError:
logger.error(f"Received invalid set command: {topic}") logger.error(f"Received invalid set command: {topic}")
return return
elif topic.endswith("ptz"): elif topic.endswith("ptz"):
@ -80,7 +80,7 @@ class Dispatcher:
# example /cam_name/ptz payload=MOVE_UP|MOVE_DOWN|STOP... # example /cam_name/ptz payload=MOVE_UP|MOVE_DOWN|STOP...
camera_name = topic.split("/")[-2] camera_name = topic.split("/")[-2]
self._on_ptz_command(camera_name, payload) self._on_ptz_command(camera_name, payload)
except IndexError as e: except IndexError:
logger.error(f"Received invalid ptz command: {topic}") logger.error(f"Received invalid ptz command: {topic}")
return return
elif topic == "restart": elif topic == "restart":
@ -128,7 +128,7 @@ class Dispatcher:
elif payload == "OFF": elif payload == "OFF":
if self.camera_metrics[camera_name]["detection_enabled"].value: if self.camera_metrics[camera_name]["detection_enabled"].value:
logger.error( logger.error(
f"Turning off motion is not allowed when detection is enabled." "Turning off motion is not allowed when detection is enabled."
) )
return return
@ -196,7 +196,7 @@ class Dispatcher:
if payload == "ON": if payload == "ON":
if not self.config.cameras[camera_name].record.enabled_in_config: if not self.config.cameras[camera_name].record.enabled_in_config:
logger.error( logger.error(
f"Recordings must be enabled in the config to be turned on via MQTT." "Recordings must be enabled in the config to be turned on via MQTT."
) )
return return

View File

@ -177,10 +177,10 @@ class MqttClient(Communicator): # type: ignore[misc]
f"{self.mqtt_config.topic_prefix}/restart", self.on_mqtt_command f"{self.mqtt_config.topic_prefix}/restart", self.on_mqtt_command
) )
if not self.mqtt_config.tls_ca_certs is None: if self.mqtt_config.tls_ca_certs is not None:
if ( if (
not self.mqtt_config.tls_client_cert is None self.mqtt_config.tls_client_cert is not None
and not self.mqtt_config.tls_client_key is None and self.mqtt_config.tls_client_key is not None
): ):
self.client.tls_set( self.client.tls_set(
self.mqtt_config.tls_ca_certs, self.mqtt_config.tls_ca_certs,
@ -189,9 +189,9 @@ class MqttClient(Communicator): # type: ignore[misc]
) )
else: else:
self.client.tls_set(self.mqtt_config.tls_ca_certs) self.client.tls_set(self.mqtt_config.tls_ca_certs)
if not self.mqtt_config.tls_insecure is None: if self.mqtt_config.tls_insecure is not None:
self.client.tls_insecure_set(self.mqtt_config.tls_insecure) self.client.tls_insecure_set(self.mqtt_config.tls_insecure)
if not self.mqtt_config.user is None: if self.mqtt_config.user is not None:
self.client.username_pw_set( self.client.username_pw_set(
self.mqtt_config.user, password=self.mqtt_config.password self.mqtt_config.user, password=self.mqtt_config.password
) )

View File

@ -45,7 +45,7 @@ class WebSocketClient(Communicator): # type: ignore[misc]
"topic": json_message.get("topic"), "topic": json_message.get("topic"),
"payload": json_message.get("payload"), "payload": json_message.get("payload"),
} }
except Exception as e: except Exception:
logger.warning( logger.warning(
f"Unable to parse websocket message as valid json: {message.data.decode('utf-8')}" f"Unable to parse websocket message as valid json: {message.data.decode('utf-8')}"
) )
@ -82,7 +82,7 @@ class WebSocketClient(Communicator): # type: ignore[misc]
"payload": payload, "payload": payload,
} }
) )
except Exception as e: except Exception:
# if the payload can't be decoded don't relay to clients # if the payload can't be decoded don't relay to clients
logger.debug(f"payload for {topic} wasn't text. Skipping...") logger.debug(f"payload for {topic} wasn't text. Skipping...")
return return

View File

@ -8,7 +8,6 @@ from typing import Dict, List, Optional, Tuple, Union
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import yaml
from pydantic import BaseModel, Extra, Field, validator, parse_obj_as from pydantic import BaseModel, Extra, Field, validator, parse_obj_as
from pydantic.fields import PrivateAttr from pydantic.fields import PrivateAttr
@ -26,7 +25,6 @@ from frigate.util import (
get_ffmpeg_arg_list, get_ffmpeg_arg_list,
escape_special_characters, escape_special_characters,
load_config_with_no_duplicates, load_config_with_no_duplicates,
load_labels,
) )
from frigate.ffmpeg_presets import ( from frigate.ffmpeg_presets import (
parse_preset_hardware_acceleration_decode, parse_preset_hardware_acceleration_decode,
@ -36,12 +34,9 @@ from frigate.ffmpeg_presets import (
parse_preset_output_rtmp, parse_preset_output_rtmp,
) )
from frigate.detectors import ( from frigate.detectors import (
PixelFormatEnum,
InputTensorEnum,
ModelConfig, ModelConfig,
DetectorConfig, DetectorConfig,
) )
from frigate.version import VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -487,7 +482,7 @@ class CameraFfmpegConfig(FfmpegConfig):
if len(roles) > len(roles_set): if len(roles) > len(roles_set):
raise ValueError("Each input role may only be used once.") raise ValueError("Each input role may only be used once.")
if not "detect" in roles: if "detect" not in roles:
raise ValueError("The detect role is required.") raise ValueError("The detect role is required.")
return v return v
@ -776,12 +771,12 @@ def verify_config_roles(camera_config: CameraConfig) -> None:
set([r for i in camera_config.ffmpeg.inputs for r in i.roles]) set([r for i in camera_config.ffmpeg.inputs for r in i.roles])
) )
if camera_config.record.enabled and not "record" in assigned_roles: if camera_config.record.enabled and "record" not in assigned_roles:
raise ValueError( raise ValueError(
f"Camera {camera_config.name} has record enabled, but record is not assigned to an input." f"Camera {camera_config.name} has record enabled, but record is not assigned to an input."
) )
if camera_config.rtmp.enabled and not "rtmp" in assigned_roles: if camera_config.rtmp.enabled and "rtmp" not in assigned_roles:
raise ValueError( raise ValueError(
f"Camera {camera_config.name} has rtmp enabled, but rtmp is not assigned to an input." f"Camera {camera_config.name} has rtmp enabled, but rtmp is not assigned to an input."
) )
@ -1062,7 +1057,7 @@ class FrigateConfig(FrigateBaseModel):
config.model.dict(exclude_unset=True), config.model.dict(exclude_unset=True),
) )
if not "path" in merged_model: if "path" not in merged_model:
if detector_config.type == "cpu": if detector_config.type == "cpu":
merged_model["path"] = "/cpu_model.tflite" merged_model["path"] = "/cpu_model.tflite"
elif detector_config.type == "edgetpu": elif detector_config.type == "edgetpu":

View File

@ -1,11 +1,5 @@
import logging import logging
from .detection_api import DetectionApi
from .detector_config import (
PixelFormatEnum,
InputTensorEnum,
ModelConfig,
)
from .detector_types import DetectorTypeEnum, api_types, DetectorConfig from .detector_types import DetectorTypeEnum, api_types, DetectorConfig

View File

@ -3,12 +3,12 @@ import json
import logging import logging
from enum import Enum from enum import Enum
import os import os
from typing import Dict, List, Optional, Tuple, Union, Literal from typing import Dict, Optional, Tuple
import requests import requests
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from pydantic import BaseModel, Extra, Field, validator from pydantic import BaseModel, Extra, Field
from pydantic.fields import PrivateAttr from pydantic.fields import PrivateAttr
from frigate.plus import PlusApi from frigate.plus import PlusApi

View File

@ -3,8 +3,9 @@ import numpy as np
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig
from typing_extensions import Literal from typing_extensions import Literal
from pydantic import Extra, Field from pydantic import Field
try: try:
from tflite_runtime.interpreter import Interpreter from tflite_runtime.interpreter import Interpreter

View File

@ -6,7 +6,7 @@ import io
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig
from typing_extensions import Literal from typing_extensions import Literal
from pydantic import Extra, Field from pydantic import Field
from PIL import Image from PIL import Image
@ -64,11 +64,11 @@ class DeepStack(DetectionApi):
for i, detection in enumerate(response_json.get("predictions")): for i, detection in enumerate(response_json.get("predictions")):
logger.debug(f"Response: {detection}") logger.debug(f"Response: {detection}")
if detection["confidence"] < 0.4: if detection["confidence"] < 0.4:
logger.debug(f"Break due to confidence < 0.4") logger.debug("Break due to confidence < 0.4")
break break
label = self.get_label_index(detection["label"]) label = self.get_label_index(detection["label"])
if label < 0: if label < 0:
logger.debug(f"Break due to unknown label") logger.debug("Break due to unknown label")
break break
detections[i] = [ detections[i] = [
label, label,

View File

@ -4,7 +4,7 @@ import numpy as np
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig
from typing_extensions import Literal from typing_extensions import Literal
from pydantic import Extra, Field from pydantic import Field
try: try:
from tflite_runtime.interpreter import Interpreter, load_delegate from tflite_runtime.interpreter import Interpreter, load_delegate

View File

@ -5,7 +5,7 @@ import openvino.runtime as ov
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig, ModelTypeEnum from frigate.detectors.detector_config import BaseDetectorConfig, ModelTypeEnum
from typing_extensions import Literal from typing_extensions import Literal
from pydantic import Extra, Field from pydantic import Field
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -8,7 +8,7 @@ try:
from cuda import cuda from cuda import cuda
TRT_SUPPORT = True TRT_SUPPORT = True
except ModuleNotFoundError as e: except ModuleNotFoundError:
TRT_SUPPORT = False TRT_SUPPORT = False
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
@ -172,7 +172,7 @@ class TensorRtDetector(DetectionApi):
if not self.context.execute_async_v2( if not self.context.execute_async_v2(
bindings=self.bindings, stream_handle=self.stream bindings=self.bindings, stream_handle=self.stream
): ):
logger.warn(f"Execute returned false") logger.warn("Execute returned false")
# Transfer predictions back from the GPU. # Transfer predictions back from the GPU.
[ [

View File

@ -7,7 +7,6 @@ import threading
from pathlib import Path from pathlib import Path
from peewee import fn
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.const import CLIPS_DIR from frigate.const import CLIPS_DIR
@ -45,9 +44,9 @@ class EventCleanup(threading.Thread):
) )
# loop over object types in db # loop over object types in db
for l in distinct_labels: for event in distinct_labels:
# get expiration time for this label # get expiration time for this label
expire_days = retain_config.objects.get(l.label, retain_config.default) expire_days = retain_config.objects.get(event.label, retain_config.default)
expire_after = ( expire_after = (
datetime.datetime.now() - datetime.timedelta(days=expire_days) datetime.datetime.now() - datetime.timedelta(days=expire_days)
).timestamp() ).timestamp()
@ -55,8 +54,8 @@ class EventCleanup(threading.Thread):
expired_events = Event.select().where( expired_events = Event.select().where(
Event.camera.not_in(self.camera_keys), Event.camera.not_in(self.camera_keys),
Event.start_time < expire_after, Event.start_time < expire_after,
Event.label == l.label, Event.label == event.label,
Event.retain_indefinitely == False, Event.retain_indefinitely is False,
) )
# delete the media from disk # delete the media from disk
for event in expired_events: for event in expired_events:
@ -75,8 +74,8 @@ class EventCleanup(threading.Thread):
update_query = Event.update(update_params).where( update_query = Event.update(update_params).where(
Event.camera.not_in(self.camera_keys), Event.camera.not_in(self.camera_keys),
Event.start_time < expire_after, Event.start_time < expire_after,
Event.label == l.label, Event.label == event.label,
Event.retain_indefinitely == False, Event.retain_indefinitely is False,
) )
update_query.execute() update_query.execute()
@ -92,9 +91,9 @@ class EventCleanup(threading.Thread):
) )
# loop over object types in db # loop over object types in db
for l in distinct_labels: for event in distinct_labels:
# get expiration time for this label # get expiration time for this label
expire_days = retain_config.objects.get(l.label, retain_config.default) expire_days = retain_config.objects.get(event.label, retain_config.default)
expire_after = ( expire_after = (
datetime.datetime.now() - datetime.timedelta(days=expire_days) datetime.datetime.now() - datetime.timedelta(days=expire_days)
).timestamp() ).timestamp()
@ -102,8 +101,8 @@ class EventCleanup(threading.Thread):
expired_events = Event.select().where( expired_events = Event.select().where(
Event.camera == name, Event.camera == name,
Event.start_time < expire_after, Event.start_time < expire_after,
Event.label == l.label, Event.label == event.label,
Event.retain_indefinitely == False, Event.retain_indefinitely is False,
) )
# delete the grabbed clips from disk # delete the grabbed clips from disk
for event in expired_events: for event in expired_events:
@ -121,8 +120,8 @@ class EventCleanup(threading.Thread):
update_query = Event.update(update_params).where( update_query = Event.update(update_params).where(
Event.camera == name, Event.camera == name,
Event.start_time < expire_after, Event.start_time < expire_after,
Event.label == l.label, Event.label == event.label,
Event.retain_indefinitely == False, Event.retain_indefinitely is False,
) )
update_query.execute() update_query.execute()
@ -169,8 +168,8 @@ class EventCleanup(threading.Thread):
# drop events from db where has_clip and has_snapshot are false # drop events from db where has_clip and has_snapshot are false
delete_query = Event.delete().where( delete_query = Event.delete().where(
Event.has_clip == False, Event.has_snapshot == False Event.has_clip is False, Event.has_snapshot is False
) )
delete_query.execute() delete_query.execute()
logger.info(f"Exiting event cleanup...") logger.info("Exiting event cleanup...")

View File

@ -3,7 +3,6 @@
import base64 import base64
import cv2 import cv2
import datetime import datetime
import glob
import logging import logging
import os import os
import random import random

View File

@ -5,7 +5,6 @@ import threading
from enum import Enum from enum import Enum
from peewee import fn
from frigate.config import EventsConfig, FrigateConfig from frigate.config import EventsConfig, FrigateConfig
from frigate.models import Event from frigate.models import Event
@ -65,7 +64,7 @@ class EventProcessor(threading.Thread):
def run(self) -> None: def run(self) -> None:
# set an end_time on events without an end_time on startup # set an end_time on events without an end_time on startup
Event.update(end_time=Event.start_time + 30).where( Event.update(end_time=Event.start_time + 30).where(
Event.end_time == None Event.end_time is None
).execute() ).execute()
while not self.stop_event.is_set(): while not self.stop_event.is_set():
@ -99,9 +98,9 @@ class EventProcessor(threading.Thread):
# set an end_time on events without an end_time before exiting # set an end_time on events without an end_time before exiting
Event.update(end_time=datetime.datetime.now().timestamp()).where( Event.update(end_time=datetime.datetime.now().timestamp()).where(
Event.end_time == None Event.end_time is None
).execute() ).execute()
logger.info(f"Exiting event processor...") logger.info("Exiting event processor...")
def handle_object_detection( def handle_object_detection(
self, self,

View File

@ -105,10 +105,10 @@ def events_summary():
clauses = [] clauses = []
if not has_clip is None: if has_clip is not None:
clauses.append((Event.has_clip == has_clip)) clauses.append((Event.has_clip == has_clip))
if not has_snapshot is None: if has_snapshot is not None:
clauses.append((Event.has_snapshot == has_snapshot)) clauses.append((Event.has_snapshot == has_snapshot))
if len(clauses) == 0: if len(clauses) == 0:
@ -253,7 +253,7 @@ def send_to_plus(id):
event.plus_id = plus_id event.plus_id = plus_id
event.save() event.save()
if not include_annotation is None: if include_annotation is not None:
box = event.data["box"] box = event.data["box"]
try: try:
@ -296,12 +296,12 @@ def false_positive(id):
# events from before the conversion to relative dimensions cant include annotations # events from before the conversion to relative dimensions cant include annotations
if event.data.get("box") is None: if event.data.get("box") is None:
message = f"Events prior to 0.13 cannot be submitted as false positives" message = "Events prior to 0.13 cannot be submitted as false positives"
logger.error(message) logger.error(message)
return make_response(jsonify({"success": False, "message": message}), 400) return make_response(jsonify({"success": False, "message": message}), 400)
if event.false_positive: if event.false_positive:
message = f"False positive already submitted to Frigate+" message = "False positive already submitted to Frigate+"
logger.error(message) logger.error(message)
return make_response(jsonify({"success": False, "message": message}), 400) return make_response(jsonify({"success": False, "message": message}), 400)
@ -437,7 +437,7 @@ def get_sub_labels():
parts = label.split(",") parts = label.split(",")
for part in parts: for part in parts:
if not (part.strip()) in sub_labels: if part.strip() not in sub_labels:
sub_labels.append(part.strip()) sub_labels.append(part.strip())
sub_labels.sort() sub_labels.sort()
@ -476,7 +476,7 @@ def event_thumbnail(id, max_cache_age=2592000):
event_complete = False event_complete = False
try: try:
event = Event.get(Event.id == id) event = Event.get(Event.id == id)
if not event.end_time is None: if event.end_time is not None:
event_complete = True event_complete = True
thumbnail_bytes = base64.b64decode(event.thumbnail) thumbnail_bytes = base64.b64decode(event.thumbnail)
except DoesNotExist: except DoesNotExist:
@ -486,7 +486,7 @@ def event_thumbnail(id, max_cache_age=2592000):
for camera_state in camera_states: for camera_state in camera_states:
if id in camera_state.tracked_objects: if id in camera_state.tracked_objects:
tracked_obj = camera_state.tracked_objects.get(id) tracked_obj = camera_state.tracked_objects.get(id)
if not tracked_obj is None: if tracked_obj is not None:
thumbnail_bytes = tracked_obj.get_thumbnail() thumbnail_bytes = tracked_obj.get_thumbnail()
except: except:
return "Event not found", 404 return "Event not found", 404
@ -593,7 +593,7 @@ def event_snapshot(id):
event_complete = False event_complete = False
jpg_bytes = None jpg_bytes = None
try: try:
event = Event.get(Event.id == id, Event.end_time != None) event = Event.get(Event.id == id, Event.end_time is not None)
event_complete = True event_complete = True
if not event.has_snapshot: if not event.has_snapshot:
return "Snapshot not available", 404 return "Snapshot not available", 404
@ -609,7 +609,7 @@ def event_snapshot(id):
for camera_state in camera_states: for camera_state in camera_states:
if id in camera_state.tracked_objects: if id in camera_state.tracked_objects:
tracked_obj = camera_state.tracked_objects.get(id) tracked_obj = camera_state.tracked_objects.get(id)
if not tracked_obj is None: if tracked_obj is not None:
jpg_bytes = tracked_obj.get_jpg_bytes( jpg_bytes = tracked_obj.get_jpg_bytes(
timestamp=request.args.get("timestamp", type=int), timestamp=request.args.get("timestamp", type=int),
bounding_box=request.args.get("bbox", type=int), bounding_box=request.args.get("bbox", type=int),
@ -645,7 +645,7 @@ def label_snapshot(camera_name, label):
event_query = ( event_query = (
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
.where(Event.has_snapshot == True) .where(Event.has_snapshot is True)
.order_by(Event.start_time.desc()) .order_by(Event.start_time.desc())
) )
else: else:
@ -653,7 +653,7 @@ def label_snapshot(camera_name, label):
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
.where(Event.label == label) .where(Event.label == label)
.where(Event.has_snapshot == True) .where(Event.has_snapshot is True)
.order_by(Event.start_time.desc()) .order_by(Event.start_time.desc())
) )
@ -820,13 +820,13 @@ def events():
if before: if before:
clauses.append((Event.start_time < before)) clauses.append((Event.start_time < before))
if not has_clip is None: if has_clip is not None:
clauses.append((Event.has_clip == has_clip)) clauses.append((Event.has_clip == has_clip))
if not has_snapshot is None: if has_snapshot is not None:
clauses.append((Event.has_snapshot == has_snapshot)) clauses.append((Event.has_snapshot == has_snapshot))
if not in_progress is None: if in_progress is not None:
clauses.append((Event.end_time.is_null(in_progress))) clauses.append((Event.end_time.is_null(in_progress)))
if not include_thumbnails: if not include_thumbnails:
@ -899,7 +899,7 @@ def end_event(event_id):
{"success": False, "message": f"{event_id} must be set and valid."}, 404 {"success": False, "message": f"{event_id} must be set and valid."}, 404
) )
return jsonify({"success": True, "message": f"Event successfully ended."}, 200) return jsonify({"success": True, "message": "Event successfully ended."}, 200)
@bp.route("/config") @bp.route("/config")
@ -959,9 +959,8 @@ def config_save():
# Validate the config schema # Validate the config schema
try: try:
new_yaml = FrigateConfig.parse_raw(new_config) FrigateConfig.parse_raw(new_config)
check_runtime = new_yaml.runtime_config except Exception:
except Exception as e:
return make_response( return make_response(
jsonify( jsonify(
{ {
@ -985,12 +984,12 @@ def config_save():
with open(config_file, "w") as f: with open(config_file, "w") as f:
f.write(new_config) f.write(new_config)
f.close() f.close()
except Exception as e: except Exception:
return make_response( return make_response(
jsonify( jsonify(
{ {
"success": False, "success": False,
"message": f"Could not write config file, be sure that Frigate has write permission on the config file.", "message": "Could not write config file, be sure that Frigate has write permission on the config file.",
} }
), ),
400, 400,
@ -1531,7 +1530,7 @@ def ffprobe():
if not path_param: if not path_param:
return jsonify( return jsonify(
{"success": False, "message": f"Path needs to be provided."}, "404" {"success": False, "message": "Path needs to be provided."}, "404"
) )
if path_param.startswith("camera"): if path_param.startswith("camera"):

View File

@ -10,8 +10,7 @@ from logging import handlers
from typing import Optional from typing import Optional
from types import FrameType from types import FrameType
from setproctitle import setproctitle from setproctitle import setproctitle
from typing import Deque, Optional from typing import Deque
from types import FrameType
from collections import deque from collections import deque
from frigate.util import clean_camera_user_pass from frigate.util import clean_camera_user_pass
@ -44,7 +43,7 @@ def root_configurer(queue: Queue) -> None:
def log_process(log_queue: Queue) -> None: def log_process(log_queue: Queue) -> None:
threading.current_thread().name = f"logger" threading.current_thread().name = "logger"
setproctitle("frigate.logger") setproctitle("frigate.logger")
listener_configurer() listener_configurer()

View File

@ -1,4 +1,3 @@
from numpy import unique
from peewee import ( from peewee import (
Model, Model,
CharField, CharField,

View File

@ -161,7 +161,7 @@ class ObjectDetectProcess:
def start_or_restart(self): def start_or_restart(self):
self.detection_start.value = 0.0 self.detection_start.value = 0.0
if (not self.detect_process is None) and self.detect_process.is_alive(): if (self.detect_process is not None) and self.detect_process.is_alive():
self.stop() self.stop()
self.detect_process = mp.Process( self.detect_process = mp.Process(
target=run_detector, target=run_detector,

View File

@ -141,7 +141,7 @@ class TrackedObject:
# check each zone # check each zone
for name, zone in self.camera_config.zones.items(): for name, zone in self.camera_config.zones.items():
# if the zone is not for this object type, skip # if the zone is not for this object type, skip
if len(zone.objects) > 0 and not obj_data["label"] in zone.objects: if len(zone.objects) > 0 and obj_data["label"] not in zone.objects:
continue continue
contour = zone.contour contour = zone.contour
# check if the object is in the zone # check if the object is in the zone
@ -177,9 +177,9 @@ class TrackedObject:
return (thumb_update, significant_change) return (thumb_update, significant_change)
def to_dict(self, include_thumbnail: bool = False): def to_dict(self, include_thumbnail: bool = False):
snapshot_time = ( (
self.thumbnail_data["frame_time"] self.thumbnail_data["frame_time"]
if not self.thumbnail_data is None if self.thumbnail_data is not None
else 0.0 else 0.0
) )
event = { event = {
@ -526,7 +526,7 @@ class CameraState:
for id in removed_ids: for id in removed_ids:
# publish events to mqtt # publish events to mqtt
removed_obj = tracked_objects[id] removed_obj = tracked_objects[id]
if not "end_time" in removed_obj.obj_data: if "end_time" not in removed_obj.obj_data:
removed_obj.obj_data["end_time"] = frame_time removed_obj.obj_data["end_time"] = frame_time
for c in self.callbacks["end"]: for c in self.callbacks["end"]:
c(self.name, removed_obj, frame_time) c(self.name, removed_obj, frame_time)
@ -1028,4 +1028,4 @@ class TrackedObjectProcessor(threading.Thread):
event_id, camera = self.event_processed_queue.get() event_id, camera = self.event_processed_queue.get()
self.camera_states[camera].finished(event_id) self.camera_states[camera].finished(event_id)
logger.info(f"Exiting object processor...") logger.info("Exiting object processor...")

View File

@ -1,14 +1,7 @@
import copy
import datetime
import itertools
import multiprocessing as mp
import random import random
import string import string
import threading
import time
from collections import defaultdict from collections import defaultdict
import cv2
import numpy as np import numpy as np
from scipy.spatial import distance as dist from scipy.spatial import distance as dist
@ -160,7 +153,7 @@ class ObjectTracker:
# update any tracked objects with labels that are not # update any tracked objects with labels that are not
# seen in the current objects and deregister if needed # seen in the current objects and deregister if needed
for obj in list(self.tracked_objects.values()): for obj in list(self.tracked_objects.values()):
if not obj["label"] in new_object_groups: if obj["label"] not in new_object_groups:
if self.disappeared[obj["id"]] >= self.max_disappeared: if self.disappeared[obj["id"]] >= self.max_disappeared:
self.deregister(obj["id"]) self.deregister(obj["id"])
else: else:

View File

@ -4,7 +4,6 @@ import logging
import math import math
import multiprocessing as mp import multiprocessing as mp
import os import os
import operator
import queue import queue
import signal import signal
import subprocess as sp import subprocess as sp
@ -185,7 +184,7 @@ class BirdsEyeFrameManager:
if len(logo_files) > 0: if len(logo_files) > 0:
birdseye_logo = cv2.imread(logo_files[0], cv2.IMREAD_UNCHANGED) birdseye_logo = cv2.imread(logo_files[0], cv2.IMREAD_UNCHANGED)
if not birdseye_logo is None: if birdseye_logo is not None:
transparent_layer = birdseye_logo[:, :, 3] transparent_layer = birdseye_logo[:, :, 3]
y_offset = height // 2 - transparent_layer.shape[0] // 2 y_offset = height // 2 - transparent_layer.shape[0] // 2
x_offset = width // 2 - transparent_layer.shape[1] // 2 x_offset = width // 2 - transparent_layer.shape[1] // 2
@ -229,7 +228,7 @@ class BirdsEyeFrameManager:
self.last_output_time = 0.0 self.last_output_time = 0.0
def clear_frame(self): def clear_frame(self):
logger.debug(f"Clearing the birdseye frame") logger.debug("Clearing the birdseye frame")
self.frame[:] = self.blank_frame self.frame[:] = self.blank_frame
def copy_to_position(self, position, camera=None, frame_time=None): def copy_to_position(self, position, camera=None, frame_time=None):
@ -301,7 +300,7 @@ class BirdsEyeFrameManager:
# reset the layout if it needs to be different # reset the layout if it needs to be different
if layout_dim != self.layout_dim or reset_layout: if layout_dim != self.layout_dim or reset_layout:
if reset_layout: if reset_layout:
logger.debug(f"Added new cameras, resetting layout...") logger.debug("Added new cameras, resetting layout...")
logger.debug(f"Changing layout size from {self.layout_dim} to {layout_dim}") logger.debug(f"Changing layout size from {self.layout_dim} to {layout_dim}")
self.layout_dim = layout_dim self.layout_dim = layout_dim
@ -385,7 +384,7 @@ class BirdsEyeFrameManager:
] ]
# if not an empty spot and the camera has a newer frame, copy it # if not an empty spot and the camera has a newer frame, copy it
elif ( elif (
not camera is None camera is not None
and self.cameras[camera]["current_frame"] and self.cameras[camera]["current_frame"]
!= self.cameras[camera]["layout_frame"] != self.cameras[camera]["layout_frame"]
): ):
@ -423,8 +422,8 @@ class BirdsEyeFrameManager:
def output_frames(config: FrigateConfig, video_output_queue): def output_frames(config: FrigateConfig, video_output_queue):
threading.current_thread().name = f"output" threading.current_thread().name = "output"
setproctitle(f"frigate.output") setproctitle("frigate.output")
stop_event = mp.Event() stop_event = mp.Event()

View File

@ -3,7 +3,7 @@ import json
import logging import logging
import os import os
import re import re
from typing import Any, Dict, List from typing import Any, List
import requests import requests
from frigate.const import PLUS_ENV_VAR, PLUS_API_HOST from frigate.const import PLUS_ENV_VAR, PLUS_API_HOST
from requests.models import Response from requests.models import Response

View File

@ -145,7 +145,7 @@ class OnvifController:
onvif.get_service("ptz").ContinuousMove(move_request) onvif.get_service("ptz").ContinuousMove(move_request)
def _move_to_preset(self, camera_name: str, preset: str) -> None: def _move_to_preset(self, camera_name: str, preset: str) -> None:
if not preset in self.cams[camera_name]["presets"]: if preset not in self.cams[camera_name]["presets"]:
logger.error(f"{preset} is not a valid preset for {camera_name}") logger.error(f"{preset} is not a valid preset for {camera_name}")
return return

View File

@ -225,7 +225,7 @@ class RecordingCleanup(threading.Thread):
recordings_to_delete = [] recordings_to_delete = []
for recording in recordings.objects().iterator(): for recording in recordings.objects().iterator():
if not recording.path in files_on_disk: if recording.path not in files_on_disk:
recordings_to_delete.append(recording.id) recordings_to_delete.append(recording.id)
logger.debug( logger.debug(
@ -247,7 +247,7 @@ class RecordingCleanup(threading.Thread):
# Expire tmp clips every minute, recordings and clean directories every hour. # Expire tmp clips every minute, recordings and clean directories every hour.
for counter in itertools.cycle(range(self.config.record.expire_interval)): for counter in itertools.cycle(range(self.config.record.expire_interval)):
if self.stop_event.wait(60): if self.stop_event.wait(60):
logger.info(f"Exiting recording cleanup...") logger.info("Exiting recording cleanup...")
break break
self.clean_tmp_clips() self.clean_tmp_clips()

View File

@ -115,7 +115,7 @@ class RecordingMaintainer(threading.Thread):
Event.select() Event.select()
.where( .where(
Event.camera == camera, Event.camera == camera,
(Event.end_time == None) (Event.end_time is None)
| (Event.end_time >= recordings[0]["start_time"].timestamp()), | (Event.end_time >= recordings[0]["start_time"].timestamp()),
Event.has_clip, Event.has_clip,
) )
@ -127,7 +127,7 @@ class RecordingMaintainer(threading.Thread):
# Just delete files if recordings are turned off # Just delete files if recordings are turned off
if ( if (
not camera in self.config.cameras camera not in self.config.cameras
or not self.process_info[camera]["record_enabled"].value or not self.process_info[camera]["record_enabled"].value
): ):
Path(cache_path).unlink(missing_ok=True) Path(cache_path).unlink(missing_ok=True)
@ -394,4 +394,4 @@ class RecordingMaintainer(threading.Thread):
duration = datetime.datetime.now().timestamp() - run_start duration = datetime.datetime.now().timestamp() - run_start
wait_time = max(0, 5 - duration) wait_time = max(0, 5 - duration)
logger.info(f"Exiting recording maintenance...") logger.info("Exiting recording maintenance...")

View File

@ -308,4 +308,4 @@ class StatsEmitter(threading.Thread):
) )
self.dispatcher.publish("stats", json.dumps(stats), retain=False) self.dispatcher.publish("stats", json.dumps(stats), retain=False)
logger.debug("Finished stats collection") logger.debug("Finished stats collection")
logger.info(f"Exiting stats emitter...") logger.info("Exiting stats emitter...")

View File

@ -107,7 +107,7 @@ class StorageMaintainer(threading.Thread):
retained_events: Event = ( retained_events: Event = (
Event.select() Event.select()
.where( .where(
Event.retain_indefinitely == True, Event.retain_indefinitely is True,
Event.has_clip, Event.has_clip,
) )
.order_by(Event.start_time.asc()) .order_by(Event.start_time.asc())
@ -188,4 +188,4 @@ class StorageMaintainer(threading.Thread):
if self.check_storage_needs_cleanup(): if self.check_storage_needs_cleanup():
self.reduce_storage_consumption() self.reduce_storage_consumption()
logger.info(f"Exiting storage maintainer...") logger.info("Exiting storage maintainer...")

View File

@ -675,7 +675,7 @@ class TestConfig(unittest.TestCase):
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds
assert len(ffmpeg_cmds) == 1 assert len(ffmpeg_cmds) == 1
assert not "clips" in ffmpeg_cmds[0]["roles"] assert "clips" not in ffmpeg_cmds[0]["roles"]
def test_max_disappeared_default(self): def test_max_disappeared_default(self):
config = { config = {
@ -986,7 +986,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
runtime_config = frigate_config.runtime_config() frigate_config.runtime_config()
def test_global_detect(self): def test_global_detect(self):
config = { config = {
@ -1145,7 +1145,7 @@ class TestConfig(unittest.TestCase):
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.dict(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.bounding_box == False assert runtime_config.cameras["back"].snapshots.bounding_box is False
assert runtime_config.cameras["back"].snapshots.height == 150 assert runtime_config.cameras["back"].snapshots.height == 150
assert runtime_config.cameras["back"].snapshots.enabled assert runtime_config.cameras["back"].snapshots.enabled

View File

@ -1,7 +1,7 @@
import unittest import unittest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats, get_nvidia_gpu_stats from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats
class TestGpuStats(unittest.TestCase): class TestGpuStats(unittest.TestCase):

View File

@ -128,22 +128,22 @@ class TestHttp(unittest.TestCase):
with app.test_client() as client: with app.test_client() as client:
_insert_mock_event(id) _insert_mock_event(id)
events = client.get(f"/events").json events = client.get("/events").json
assert events assert events
assert len(events) == 1 assert len(events) == 1
assert events[0]["id"] == id assert events[0]["id"] == id
_insert_mock_event(id2) _insert_mock_event(id2)
events = client.get(f"/events").json events = client.get("/events").json
assert events assert events
assert len(events) == 2 assert len(events) == 2
events = client.get( events = client.get(
f"/events", "/events",
query_string={"limit": 1}, query_string={"limit": 1},
).json ).json
assert events assert events
assert len(events) == 1 assert len(events) == 1
events = client.get( events = client.get(
f"/events", "/events",
query_string={"has_clip": 0}, query_string={"has_clip": 0},
).json ).json
assert not events assert not events
@ -230,12 +230,12 @@ class TestHttp(unittest.TestCase):
event = client.get(f"/events/{id}").json event = client.get(f"/events/{id}").json
assert event assert event
assert event["id"] == id assert event["id"] == id
assert event["retain_indefinitely"] == True assert event["retain_indefinitely"] is True
client.delete(f"/events/{id}/retain") client.delete(f"/events/{id}/retain")
event = client.get(f"/events/{id}").json event = client.get(f"/events/{id}").json
assert event assert event
assert event["id"] == id assert event["id"] == id
assert event["retain_indefinitely"] == False assert event["retain_indefinitely"] is False
def test_set_delete_sub_label(self): def test_set_delete_sub_label(self):
app = create_app( app = create_app(

View File

@ -1,4 +1,3 @@
import numpy as np
from unittest import TestCase, main from unittest import TestCase, main
from frigate.video import box_overlaps, reduce_boxes from frigate.video import box_overlaps, reduce_boxes

View File

@ -1,18 +1,15 @@
import datetime import datetime
import json
import logging import logging
import os import os
import unittest import unittest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock
from peewee import DoesNotExist from peewee import DoesNotExist
from peewee_migrate import Router from peewee_migrate import Router
from playhouse.sqlite_ext import SqliteExtDatabase from playhouse.sqlite_ext import SqliteExtDatabase
from playhouse.sqliteq import SqliteQueueDatabase from playhouse.sqliteq import SqliteQueueDatabase
from playhouse.shortcuts import model_to_dict
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.http import create_app
from frigate.models import Event, Recordings from frigate.models import Event, Recordings
from frigate.storage import StorageMaintainer from frigate.storage import StorageMaintainer

View File

@ -33,7 +33,7 @@ class TestYuvRegion2RGB(TestCase):
# cv2.imwrite(f"bgr_frame.jpg", self.bgr_frame) # cv2.imwrite(f"bgr_frame.jpg", self.bgr_frame)
yuv_frame = cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2YUV_I420) yuv_frame = cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2YUV_I420)
cropped = yuv_region_2_rgb(yuv_frame, (0, 852, 648, 1500)) yuv_region_2_rgb(yuv_frame, (0, 852, 648, 1500))
# cv2.imwrite(f"cropped.jpg", cv2.cvtColor(cropped, cv2.COLOR_RGB2BGR)) # cv2.imwrite(f"cropped.jpg", cv2.cvtColor(cropped, cv2.COLOR_RGB2BGR))

View File

@ -20,7 +20,6 @@ import py3nvml.py3nvml as nvml
import cv2 import cv2
import numpy as np import numpy as np
import os
import psutil import psutil
import pytz import pytz
@ -457,7 +456,7 @@ def copy_yuv_to_position(
# clear v2 # clear v2
destination_frame[v2[1] : v2[3], v2[0] : v2[2]] = 128 destination_frame[v2[1] : v2[3], v2[0] : v2[2]] = 128
if not source_frame is None: if source_frame is not None:
# calculate the resized frame, maintaining the aspect ratio # calculate the resized frame, maintaining the aspect ratio
source_aspect_ratio = source_frame.shape[1] / (source_frame.shape[0] // 3 * 2) source_aspect_ratio = source_frame.shape[1] / (source_frame.shape[0] // 3 * 2)
dest_aspect_ratio = destination_shape[1] / destination_shape[0] dest_aspect_ratio = destination_shape[1] / destination_shape[0]

View File

@ -45,7 +45,7 @@ def filtered(obj, objects_to_track, object_filters):
object_area = obj[3] object_area = obj[3]
object_ratio = obj[4] object_ratio = obj[4]
if not object_name in objects_to_track: if object_name not in objects_to_track:
return True return True
if object_name in object_filters: if object_name in object_filters:
@ -73,7 +73,7 @@ def filtered(obj, objects_to_track, object_filters):
if obj_settings.max_ratio < object_ratio: if obj_settings.max_ratio < object_ratio:
return True return True
if not obj_settings.mask is None: if obj_settings.mask is not None:
# compute the coordinates of the object and make sure # compute the coordinates of the object and make sure
# the location isn't outside the bounds of the image (can happen from rounding) # the location isn't outside the bounds of the image (can happen from rounding)
object_xmin = object_box[0] object_xmin = object_box[0]
@ -169,20 +169,20 @@ def capture_frames(
skipped_eps.start() skipped_eps.start()
while True: while True:
fps.value = frame_rate.eps() fps.value = frame_rate.eps()
skipped_fps = skipped_eps.eps() skipped_eps.eps()
current_frame.value = datetime.datetime.now().timestamp() current_frame.value = datetime.datetime.now().timestamp()
frame_name = f"{camera_name}{current_frame.value}" frame_name = f"{camera_name}{current_frame.value}"
frame_buffer = frame_manager.create(frame_name, frame_size) frame_buffer = frame_manager.create(frame_name, frame_size)
try: try:
frame_buffer[:] = ffmpeg_process.stdout.read(frame_size) frame_buffer[:] = ffmpeg_process.stdout.read(frame_size)
except Exception as e: except Exception:
# shutdown has been initiated # shutdown has been initiated
if stop_event.is_set(): if stop_event.is_set():
break break
logger.error(f"{camera_name}: Unable to read frames from ffmpeg process.") logger.error(f"{camera_name}: Unable to read frames from ffmpeg process.")
if ffmpeg_process.poll() != None: if ffmpeg_process.poll() is not None:
logger.error( logger.error(
f"{camera_name}: ffmpeg process is not running. exiting capture thread..." f"{camera_name}: ffmpeg process is not running. exiting capture thread..."
) )
@ -604,7 +604,7 @@ def process_frames(
while not stop_event.is_set(): while not stop_event.is_set():
if exit_on_empty and frame_queue.empty(): if exit_on_empty and frame_queue.empty():
logger.info(f"Exiting track_objects...") logger.info("Exiting track_objects...")
break break
try: try:
@ -655,7 +655,7 @@ def process_frames(
tracked_object_boxes = [ tracked_object_boxes = [
obj["box"] obj["box"]
for obj in object_tracker.tracked_objects.values() for obj in object_tracker.tracked_objects.values()
if not obj["id"] in stationary_object_ids if obj["id"] not in stationary_object_ids
] ]
# combine motion boxes with known locations of existing objects # combine motion boxes with known locations of existing objects

View File

@ -2,8 +2,6 @@ import datetime
import logging import logging
import threading import threading
import time import time
import os
import signal
from frigate.object_detection import ObjectDetectProcess from frigate.object_detection import ObjectDetectProcess
from frigate.util import restart_frigate from frigate.util import restart_frigate
@ -39,4 +37,4 @@ class FrigateWatchdog(threading.Thread):
logger.info("Detection appears to have stopped. Exiting Frigate...") logger.info("Detection appears to have stopped. Exiting Frigate...")
restart_frigate() restart_frigate()
logger.info(f"Exiting watchdog...") logger.info("Exiting watchdog...")