Send camera state to dispatcher

This commit is contained in:
Nicolas Mowen 2024-04-29 17:01:58 -06:00
parent 1c9626ecff
commit c2e33ef0e2
3 changed files with 47 additions and 1 deletions

View File

@ -12,6 +12,7 @@ from frigate.const import (
INSERT_MANY_RECORDINGS, INSERT_MANY_RECORDINGS,
INSERT_PREVIEW, INSERT_PREVIEW,
REQUEST_REGION_GRID, REQUEST_REGION_GRID,
UPDATE_CAMERA_ACTIVITY,
UPSERT_REVIEW_SEGMENT, UPSERT_REVIEW_SEGMENT,
) )
from frigate.models import Previews, Recordings, ReviewSegment from frigate.models import Previews, Recordings, ReviewSegment
@ -76,6 +77,8 @@ class Dispatcher:
for comm in self.comms: for comm in self.comms:
comm.subscribe(self._receive) comm.subscribe(self._receive)
self.camera_activity = {}
def _receive(self, topic: str, payload: str) -> Optional[Any]: def _receive(self, topic: str, payload: str) -> Optional[Any]:
"""Handle receiving of payload from communicators.""" """Handle receiving of payload from communicators."""
if topic.endswith("set"): if topic.endswith("set"):
@ -122,6 +125,8 @@ class Dispatcher:
ReviewSegment.update(end_time=datetime.datetime.now().timestamp()).where( ReviewSegment.update(end_time=datetime.datetime.now().timestamp()).where(
ReviewSegment.end_time == None ReviewSegment.end_time == None
).execute() ).execute()
elif topic == UPDATE_CAMERA_ACTIVITY:
logger.error(f"we got the incoming data {payload}")
else: else:
self.publish(topic, payload, retain=False) self.publish(topic, payload, retain=False)

View File

@ -80,6 +80,7 @@ INSERT_PREVIEW = "insert_preview"
REQUEST_REGION_GRID = "request_region_grid" REQUEST_REGION_GRID = "request_region_grid"
UPSERT_REVIEW_SEGMENT = "upsert_review_segment" UPSERT_REVIEW_SEGMENT = "upsert_review_segment"
CLEAR_ONGOING_REVIEW_SEGMENTS = "clear_ongoing_review_segments" CLEAR_ONGOING_REVIEW_SEGMENTS = "clear_ongoing_review_segments"
UPDATE_CAMERA_ACTIVITY = "update_camera_activity"
# Autotracking # Autotracking

View File

@ -16,6 +16,7 @@ import numpy as np
from frigate.comms.detections_updater import DetectionPublisher, DetectionTypeEnum from frigate.comms.detections_updater import DetectionPublisher, DetectionTypeEnum
from frigate.comms.dispatcher import Dispatcher from frigate.comms.dispatcher import Dispatcher
from frigate.comms.events_updater import EventEndSubscriber, EventUpdatePublisher from frigate.comms.events_updater import EventEndSubscriber, EventUpdatePublisher
from frigate.comms.inter_process import InterProcessRequestor
from frigate.config import ( from frigate.config import (
CameraConfig, CameraConfig,
FrigateConfig, FrigateConfig,
@ -24,7 +25,7 @@ from frigate.config import (
SnapshotsConfig, SnapshotsConfig,
ZoomingModeEnum, ZoomingModeEnum,
) )
from frigate.const import CLIPS_DIR from frigate.const import CLIPS_DIR, UPDATE_CAMERA_ACTIVITY
from frigate.events.types import EventStateEnum, EventTypeEnum from frigate.events.types import EventStateEnum, EventTypeEnum
from frigate.ptz.autotrack import PtzAutoTrackerThread from frigate.ptz.autotrack import PtzAutoTrackerThread
from frigate.util.image import ( from frigate.util.image import (
@ -724,8 +725,31 @@ class CameraState:
# TODO: can i switch to looking this up and only changing when an event ends? # TODO: can i switch to looking this up and only changing when an event ends?
# maintain best objects # maintain best objects
camera_activity = {
"motion": len(motion_boxes) > 0,
}
for obj in tracked_objects.values(): for obj in tracked_objects.values():
object_type = obj.obj_data["label"] object_type = obj.obj_data["label"]
active = (
obj.obj_data["motionless_count"]
> self.camera_config.detect.stationary.threshold
)
if (
obj.obj_data["position_changes"] > 0
and not obj.obj_data["false_positive"]
):
if object_type not in camera_activity:
camera_activity[object_type] = {
"active": 1 if active else 0,
"stationary": 1 if not active else 0,
}
else:
camera_activity[object_type][
"active" if active else "stationary"
] += 1
# if the object's thumbnail is not from the current frame # if the object's thumbnail is not from the current frame
if obj.false_positive or obj.thumbnail_data["frame_time"] != frame_time: if obj.false_positive or obj.thumbnail_data["frame_time"] != frame_time:
continue continue
@ -752,6 +776,9 @@ class CameraState:
for c in self.callbacks["snapshot"]: for c in self.callbacks["snapshot"]:
c(self.name, self.best_objects[object_type], frame_time) c(self.name, self.best_objects[object_type], frame_time)
for c in self.callbacks["camera_activity"]:
c(self.name, camera_activity)
# update overall camera state for each object type # update overall camera state for each object type
obj_counter = Counter( obj_counter = Counter(
obj.obj_data["label"] obj.obj_data["label"]
@ -841,10 +868,14 @@ class TrackedObjectProcessor(threading.Thread):
self.frame_manager = SharedMemoryFrameManager() self.frame_manager = SharedMemoryFrameManager()
self.last_motion_detected: dict[str, float] = {} self.last_motion_detected: dict[str, float] = {}
self.ptz_autotracker_thread = ptz_autotracker_thread self.ptz_autotracker_thread = ptz_autotracker_thread
self.requestor = InterProcessRequestor()
self.detection_publisher = DetectionPublisher(DetectionTypeEnum.video) self.detection_publisher = DetectionPublisher(DetectionTypeEnum.video)
self.event_sender = EventUpdatePublisher() self.event_sender = EventUpdatePublisher()
self.event_end_subscriber = EventEndSubscriber() self.event_end_subscriber = EventEndSubscriber()
self.camera_activity: dict[str, dict[str, any]] = {}
def start(camera, obj: TrackedObject, current_frame_time): def start(camera, obj: TrackedObject, current_frame_time):
self.event_sender.publish( self.event_sender.publish(
( (
@ -962,6 +993,13 @@ class TrackedObjectProcessor(threading.Thread):
def object_status(camera, object_name, status): def object_status(camera, object_name, status):
self.dispatcher.publish(f"{camera}/{object_name}", status, retain=False) self.dispatcher.publish(f"{camera}/{object_name}", status, retain=False)
def camera_activity(camera, activity):
last_activity = self.camera_activity.get(camera)
if not last_activity or activity != last_activity:
self.camera_activity[camera] = activity
self.requestor.send_data(UPDATE_CAMERA_ACTIVITY, self.camera_activity)
for camera in self.config.cameras.keys(): for camera in self.config.cameras.keys():
camera_state = CameraState( camera_state = CameraState(
camera, self.config, self.frame_manager, self.ptz_autotracker_thread camera, self.config, self.frame_manager, self.ptz_autotracker_thread
@ -972,6 +1010,7 @@ class TrackedObjectProcessor(threading.Thread):
camera_state.on("end", end) camera_state.on("end", end)
camera_state.on("snapshot", snapshot) camera_state.on("snapshot", snapshot)
camera_state.on("object_status", object_status) camera_state.on("object_status", object_status)
camera_state.on("camera_activity", camera_activity)
self.camera_states[camera] = camera_state self.camera_states[camera] = camera_state
# { # {
@ -1228,6 +1267,7 @@ class TrackedObjectProcessor(threading.Thread):
event_id, camera = update event_id, camera = update
self.camera_states[camera].finished(event_id) self.camera_states[camera].finished(event_id)
self.requestor.stop()
self.detection_publisher.stop() self.detection_publisher.stop()
self.event_sender.stop() self.event_sender.stop()
self.event_end_subscriber.stop() self.event_end_subscriber.stop()