Store PlusApi in FrigateConfig

This commit is contained in:
George Tsiamasiotis 2024-09-23 10:48:31 +03:00
parent 6128d608d3
commit aa62a0be11
7 changed files with 33 additions and 40 deletions

View File

@ -9,7 +9,6 @@ from pydantic import ValidationError
from frigate.app import FrigateApp from frigate.app import FrigateApp
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.plus import PlusApi
def main() -> None: def main() -> None:
@ -33,11 +32,9 @@ def main() -> None:
parser.add_argument("--validate-config", action="store_true") parser.add_argument("--validate-config", action="store_true")
args = parser.parse_args() args = parser.parse_args()
plus_api = PlusApi()
# Load the configuration. # Load the configuration.
try: try:
config = FrigateConfig.load(plus_api=plus_api) config = FrigateConfig.load()
except ValidationError as e: except ValidationError as e:
print("*************************************************************") print("*************************************************************")
print("*************************************************************") print("*************************************************************")
@ -62,7 +59,7 @@ def main() -> None:
sys.exit(0) sys.exit(0)
# Run the main application. # Run the main application.
FrigateApp(config, plus_api).start() FrigateApp(config).start()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -28,7 +28,6 @@ from frigate.const import CONFIG_DIR
from frigate.embeddings import EmbeddingsContext from frigate.embeddings import EmbeddingsContext
from frigate.events.external import ExternalEventProcessor from frigate.events.external import ExternalEventProcessor
from frigate.models import Event, Timeline from frigate.models import Event, Timeline
from frigate.plus import PlusApi
from frigate.ptz.onvif import OnvifController from frigate.ptz.onvif import OnvifController
from frigate.stats.emitter import StatsEmitter from frigate.stats.emitter import StatsEmitter
from frigate.storage import StorageMaintainer from frigate.storage import StorageMaintainer
@ -61,7 +60,6 @@ def create_app(
storage_maintainer: StorageMaintainer, storage_maintainer: StorageMaintainer,
onvif: OnvifController, onvif: OnvifController,
external_processor: ExternalEventProcessor, external_processor: ExternalEventProcessor,
plus_api: PlusApi,
stats_emitter: StatsEmitter, stats_emitter: StatsEmitter,
): ):
app = Flask(__name__) app = Flask(__name__)
@ -89,7 +87,6 @@ def create_app(
app.storage_maintainer = storage_maintainer app.storage_maintainer = storage_maintainer
app.onvif = onvif app.onvif = onvif
app.external_processor = external_processor app.external_processor = external_processor
app.plus_api = plus_api
app.camera_error_image = None app.camera_error_image = None
app.stats_emitter = stats_emitter app.stats_emitter = stats_emitter
app.jwt_token = get_jwt_secret() if frigate_config.auth.enabled else None app.jwt_token = get_jwt_secret() if frigate_config.auth.enabled else None
@ -199,7 +196,7 @@ def config():
for zone_name, zone in config_obj.cameras[camera_name].zones.items(): for zone_name, zone in config_obj.cameras[camera_name].zones.items():
camera_dict["zones"][zone_name]["color"] = zone.color camera_dict["zones"][zone_name]["color"] = zone.color
config["plus"] = {"enabled": current_app.plus_api.is_active()} config["plus"] = {"enabled": current_app.frigate_config.plus_api.is_active()}
config["model"]["colormap"] = config_obj.model.colormap config["model"]["colormap"] = config_obj.model.colormap
for detector_config in config["detectors"].values(): for detector_config in config["detectors"].values():
@ -362,7 +359,7 @@ def config_set():
if json.get("requires_restart", 1) == 0: if json.get("requires_restart", 1) == 0:
current_app.frigate_config = FrigateConfig.parse_object( current_app.frigate_config = FrigateConfig.parse_object(
config_obj, plus_api=current_app.plus_api config_obj, plus_api=current_app.frigate_config.plus_api
) )
return make_response( return make_response(

View File

@ -612,7 +612,7 @@ def set_retain(id):
@EventBp.route("/events/<id>/plus", methods=("POST",)) @EventBp.route("/events/<id>/plus", methods=("POST",))
def send_to_plus(id): def send_to_plus(id):
if not current_app.plus_api.is_active(): if not current_app.frigate_config.plus_api.is_active():
message = "PLUS_API_KEY environment variable is not set" message = "PLUS_API_KEY environment variable is not set"
logger.error(message) logger.error(message)
return make_response( return make_response(
@ -680,7 +680,7 @@ def send_to_plus(id):
) )
try: try:
plus_id = current_app.plus_api.upload_image(image, event.camera) plus_id = current_app.frigate_config.plus_api.upload_image(image, event.camera)
except Exception as ex: except Exception as ex:
logger.exception(ex) logger.exception(ex)
return make_response( return make_response(
@ -696,7 +696,7 @@ def send_to_plus(id):
box = event.data["box"] box = event.data["box"]
try: try:
current_app.plus_api.add_annotation( current_app.frigate_config.plus_api.add_annotation(
event.plus_id, event.plus_id,
box, box,
event.label, event.label,
@ -720,7 +720,7 @@ def send_to_plus(id):
@EventBp.route("/events/<id>/false_positive", methods=("PUT",)) @EventBp.route("/events/<id>/false_positive", methods=("PUT",))
def false_positive(id): def false_positive(id):
if not current_app.plus_api.is_active(): if not current_app.frigate_config.plus_api.is_active():
message = "PLUS_API_KEY environment variable is not set" message = "PLUS_API_KEY environment variable is not set"
logger.error(message) logger.error(message)
return make_response( return make_response(
@ -769,7 +769,7 @@ def false_positive(id):
) )
try: try:
current_app.plus_api.add_false_positive( current_app.frigate_config.plus_api.add_false_positive(
event.plus_id, event.plus_id,
region, region,
box, box,

View File

@ -294,7 +294,7 @@ def submit_recording_snapshot_to_plus(camera_name: str, frame_time: str):
) )
nd = cv2.imdecode(np.frombuffer(image_data, dtype=np.int8), cv2.IMREAD_COLOR) nd = cv2.imdecode(np.frombuffer(image_data, dtype=np.int8), cv2.IMREAD_COLOR)
current_app.plus_api.upload_image(nd, camera_name) current_app.frigate_config.plus_api.upload_image(nd, camera_name)
return make_response( return make_response(
jsonify( jsonify(

View File

@ -9,7 +9,7 @@ import sys
from multiprocessing import Queue from multiprocessing import Queue
from multiprocessing.synchronize import Event as MpEvent from multiprocessing.synchronize import Event as MpEvent
from types import FrameType from types import FrameType
from typing import Optional from typing import Any, Optional
import psutil import psutil
from peewee_migrate import Router from peewee_migrate import Router
@ -75,14 +75,14 @@ logger = logging.getLogger(__name__)
class FrigateApp: class FrigateApp:
def __init__(self, config, plus_api) -> None: # TODO: Fix FrigateConfig usage, so we can properly annotate it here without mypy erroring out.
def __init__(self, config: Any) -> None:
self.stop_event: MpEvent = mp.Event() self.stop_event: MpEvent = mp.Event()
self.detection_queue: Queue = mp.Queue() self.detection_queue: Queue = mp.Queue()
self.detectors: dict[str, ObjectDetectProcess] = {} self.detectors: dict[str, ObjectDetectProcess] = {}
self.detection_out_events: dict[str, MpEvent] = {} self.detection_out_events: dict[str, MpEvent] = {}
self.detection_shms: list[mp.shared_memory.SharedMemory] = [] self.detection_shms: list[mp.shared_memory.SharedMemory] = []
self.log_queue: Queue = mp.Queue() self.log_queue: Queue = mp.Queue()
self.plus_api = plus_api
self.camera_metrics: dict[str, CameraMetricsTypes] = {} self.camera_metrics: dict[str, CameraMetricsTypes] = {}
self.ptz_metrics: dict[str, PTZMetricsTypes] = {} self.ptz_metrics: dict[str, PTZMetricsTypes] = {}
self.processes: dict[str, int] = {} self.processes: dict[str, int] = {}
@ -361,7 +361,6 @@ class FrigateApp:
self.storage_maintainer, self.storage_maintainer,
self.onvif_controller, self.onvif_controller,
self.external_event_processor, self.external_event_processor,
self.plus_api,
self.stats_emitter, self.stats_emitter,
) )

View File

@ -45,6 +45,7 @@ from frigate.ffmpeg_presets import (
parse_preset_input, parse_preset_input,
parse_preset_output_record, parse_preset_output_record,
) )
from frigate.plus import PlusApi
from frigate.util.builtin import ( from frigate.util.builtin import (
deep_merge, deep_merge,
escape_special_characters, escape_special_characters,
@ -1515,11 +1516,22 @@ class FrigateConfig(FrigateBaseModel):
) )
version: Optional[str] = Field(default=None, title="Current config version.") version: Optional[str] = Field(default=None, title="Current config version.")
_plus_api: PlusApi
@property
def plus_api(self) -> PlusApi:
return self._plus_api
@model_validator(mode="after") @model_validator(mode="after")
def post_validation(self, info: ValidationInfo) -> Self: def post_validation(self, info: ValidationInfo) -> Self:
plus_api = None # Load plus api from context, if possible.
self._plus_api = None
if isinstance(info.context, dict): if isinstance(info.context, dict):
plus_api = info.context.get("plus_api") self._plus_api = info.context.get("plus_api")
# Ensure self._plus_api is set, if no explicit value is provided.
if self._plus_api is None:
self._plus_api = PlusApi()
# set notifications state # set notifications state
self.notifications.enabled_in_config = self.notifications.enabled self.notifications.enabled_in_config = self.notifications.enabled
@ -1714,7 +1726,7 @@ class FrigateConfig(FrigateBaseModel):
enabled_labels.update(camera.objects.track) enabled_labels.update(camera.objects.track)
self.model.create_colormap(sorted(enabled_labels)) self.model.create_colormap(sorted(enabled_labels))
self.model.check_and_load_plus_model(plus_api) self.model.check_and_load_plus_model(self.plus_api)
for key, detector in self.detectors.items(): for key, detector in self.detectors.items():
adapter = TypeAdapter(DetectorConfig) adapter = TypeAdapter(DetectorConfig)
@ -1749,7 +1761,7 @@ class FrigateConfig(FrigateBaseModel):
detector_config.model = ModelConfig.model_validate(merged_model) detector_config.model = ModelConfig.model_validate(merged_model)
detector_config.model.check_and_load_plus_model( detector_config.model.check_and_load_plus_model(
plus_api, detector_config.type self.plus_api, detector_config.type
) )
detector_config.model.compute_model_hash() detector_config.model.compute_model_hash()
self.detectors[key] = detector_config self.detectors[key] = detector_config
@ -1828,10 +1840,10 @@ class FrigateConfig(FrigateBaseModel):
# Validate and return the config dict. # Validate and return the config dict.
return cls.parse_object(config, **context) return cls.parse_object(config, **context)
@classmethod
def parse_object(cls, obj: Any, **context):
return cls.model_validate(obj, context=context)
@classmethod @classmethod
def parse_yaml(cls, config_yaml, **context): def parse_yaml(cls, config_yaml, **context):
return cls.parse(config_yaml, is_json=False, **context) return cls.parse(config_yaml, is_json=False, **context)
@classmethod
def parse_object(cls, obj: Any, *, plus_api: Optional[PlusApi] = None):
return cls.model_validate(obj, context={"plus_api": plus_api})

View File

@ -13,7 +13,6 @@ from playhouse.sqliteq import SqliteQueueDatabase
from frigate.api.app import create_app from frigate.api.app import create_app
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.models import Event, Recordings from frigate.models import Event, Recordings
from frigate.plus import PlusApi
from frigate.stats.emitter import StatsEmitter from frigate.stats.emitter import StatsEmitter
from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS
@ -121,7 +120,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -158,7 +156,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -180,7 +177,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -201,7 +197,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -224,7 +219,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -251,7 +245,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
morning_id = "123456.random" morning_id = "123456.random"
@ -290,7 +283,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -326,7 +318,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -352,7 +343,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
@ -370,7 +360,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
None, None,
) )
id = "123456.random" id = "123456.random"
@ -392,7 +381,6 @@ class TestHttp(unittest.TestCase):
None, None,
None, None,
None, None,
PlusApi(),
stats, stats,
) )