forked from Github/frigate
Add support for filtering history page and add support for creating timeline entries for audio / custom events (#9034)
* Add filter popover * Add api filter hook and use UI with filtering * Get history filtering working for cameras and labels * Allow filtering on detail level * Save timeline entries for api events * reset * fix width
This commit is contained in:
committed by
Blake Blackshear
parent
feb3ee0703
commit
a1e5c658d5
@@ -52,7 +52,7 @@ class ExternalEventProcessor:
|
||||
(
|
||||
EventTypeEnum.api,
|
||||
"new",
|
||||
camera_config,
|
||||
camera,
|
||||
{
|
||||
"id": event_id,
|
||||
"label": label,
|
||||
|
||||
@@ -109,6 +109,16 @@ class EventProcessor(threading.Thread):
|
||||
|
||||
self.handle_object_detection(event_type, camera, event_data)
|
||||
elif source_type == EventTypeEnum.api:
|
||||
self.timeline_queue.put(
|
||||
(
|
||||
camera,
|
||||
source_type,
|
||||
event_type,
|
||||
{},
|
||||
event_data,
|
||||
)
|
||||
)
|
||||
|
||||
self.handle_external_detection(event_type, event_data)
|
||||
|
||||
# set an end_time on events without an end_time before exiting
|
||||
|
||||
@@ -614,20 +614,30 @@ def timeline():
|
||||
@bp.route("/timeline/hourly")
|
||||
def hourly_timeline():
|
||||
"""Get hourly summary for timeline."""
|
||||
camera = request.args.get("camera", "all")
|
||||
cameras = request.args.get("cameras", "all")
|
||||
labels = request.args.get("labels", "all")
|
||||
before = request.args.get("before", type=float)
|
||||
after = request.args.get("after", type=float)
|
||||
limit = request.args.get("limit", 200)
|
||||
tz_name = request.args.get("timezone", default="utc", type=str)
|
||||
_, minute_modifier, _ = get_tz_modifiers(tz_name)
|
||||
|
||||
clauses = []
|
||||
|
||||
if camera != "all":
|
||||
clauses.append((Timeline.camera == camera))
|
||||
if cameras != "all":
|
||||
camera_list = cameras.split(",")
|
||||
clauses.append((Timeline.camera << camera_list))
|
||||
|
||||
if labels != "all":
|
||||
label_list = labels.split(",")
|
||||
clauses.append((Timeline.data["label"] << label_list))
|
||||
|
||||
if before:
|
||||
clauses.append((Timeline.timestamp < before))
|
||||
|
||||
if after:
|
||||
clauses.append((Timeline.timestamp > after))
|
||||
|
||||
if len(clauses) == 0:
|
||||
clauses.append((True))
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ class TimelineProcessor(threading.Thread):
|
||||
self.handle_object_detection(
|
||||
camera, event_type, prev_event_data, event_data
|
||||
)
|
||||
elif input_type == EventTypeEnum.api:
|
||||
self.handle_api_entry(camera, event_type, event_data)
|
||||
|
||||
def insert_or_save(
|
||||
self,
|
||||
@@ -140,3 +142,40 @@ class TimelineProcessor(threading.Thread):
|
||||
|
||||
if save:
|
||||
self.insert_or_save(timeline_entry, prev_event_data, event_data)
|
||||
|
||||
def handle_api_entry(
|
||||
self,
|
||||
camera: str,
|
||||
event_type: str,
|
||||
event_data: dict[any, any],
|
||||
) -> bool:
|
||||
if event_type != "new":
|
||||
return False
|
||||
|
||||
if event_data.get("type", "api") == "audio":
|
||||
timeline_entry = {
|
||||
Timeline.class_type: "heard",
|
||||
Timeline.timestamp: event_data["start_time"],
|
||||
Timeline.camera: camera,
|
||||
Timeline.source: "audio",
|
||||
Timeline.source_id: event_data["id"],
|
||||
Timeline.data: {
|
||||
"label": event_data["label"],
|
||||
"sub_label": event_data.get("sub_label"),
|
||||
},
|
||||
}
|
||||
else:
|
||||
timeline_entry = {
|
||||
Timeline.class_type: "external",
|
||||
Timeline.timestamp: event_data["start_time"],
|
||||
Timeline.camera: camera,
|
||||
Timeline.source: "api",
|
||||
Timeline.source_id: event_data["id"],
|
||||
Timeline.data: {
|
||||
"label": event_data["label"],
|
||||
"sub_label": event_data.get("sub_label"),
|
||||
},
|
||||
}
|
||||
|
||||
Timeline.insert(timeline_entry).execute()
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user