From cff2a4836cf25672c183a9c28d1b8784d26d7013 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 26 Sep 2024 07:21:22 -0500 Subject: [PATCH] Add ability to time_range filter chroma searches --- frigate/api/defs/events_query_parameters.py | 1 + frigate/api/event.py | 52 +++++++++++++++++++++ web/src/views/search/SearchView.tsx | 23 +-------- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/frigate/api/defs/events_query_parameters.py b/frigate/api/defs/events_query_parameters.py index 884cbe9f6..02bbc31ea 100644 --- a/frigate/api/defs/events_query_parameters.py +++ b/frigate/api/defs/events_query_parameters.py @@ -43,6 +43,7 @@ class EventsSearchQueryParams(BaseModel): zones: Optional[str] = "all" after: Optional[float] = None before: Optional[float] = None + time_range: Optional[str] = DEFAULT_TIME_RANGE timezone: Optional[str] = "utc" diff --git a/frigate/api/event.py b/frigate/api/event.py index 556d19909..e924e7ae6 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -357,6 +357,7 @@ def events_search(request: Request, params: EventsSearchQueryParams = Depends()) zones = params.zones after = params.after before = params.before + time_range = params.time_range # for similarity search event_id = params.event_id @@ -428,6 +429,57 @@ def events_search(request: Request, params: EventsSearchQueryParams = Depends()) if before: embeddings_filters.append({"start_time": {"$lt": before}}) + if time_range != DEFAULT_TIME_RANGE: + # Get timezone arg to ensure browser times are used + tz_name = params.timezone + hour_modifier, minute_modifier, _ = get_tz_modifiers(tz_name) + + times = time_range.split(",") + time_after = times[0] + time_before = times[1] + hour_modifier_value = int(hour_modifier.split()[0]) + minute_modifier_value = int(minute_modifier.split()[0]) + + after_hour, after_minute = map(int, time_after.split(":")) + before_hour, before_minute = map(int, time_before.split(":")) + + now = datetime.datetime.now() + + tz_offset = datetime.timedelta( + hours=hour_modifier_value, minutes=minute_modifier_value + ) + + after_time = ( + now.replace(hour=after_hour, minute=after_minute, second=0, microsecond=0) + + tz_offset + ) + before_time = ( + now.replace(hour=before_hour, minute=before_minute, second=0, microsecond=0) + + tz_offset + ) + + # Take midnight into account + if after_time > before_time: + # Time range crosses midnight, so we need to split the filter + embeddings_filters.append( + { + "$or": [ + {"start_time": {"$gte": after_time.timestamp()}}, + {"start_time": {"$lt": before_time.timestamp()}}, + ] + } + ) + else: + # Normal case where after_time is before before_time + embeddings_filters.append( + { + "$and": [ + {"start_time": {"$gte": after_time.timestamp()}}, + {"start_time": {"$lt": before_time.timestamp()}}, + ] + } + ) + where = None if len(embeddings_filters) > 1: where = {"$and": embeddings_filters} diff --git a/web/src/views/search/SearchView.tsx b/web/src/views/search/SearchView.tsx index 48920e44d..3f6d59161 100644 --- a/web/src/views/search/SearchView.tsx +++ b/web/src/views/search/SearchView.tsx @@ -11,13 +11,7 @@ import { } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { FrigateConfig } from "@/types/frigateConfig"; -import { - DEFAULT_SEARCH_FILTERS, - SearchFilter, - SearchFilters, - SearchResult, - SearchSource, -} from "@/types/search"; +import { SearchFilter, SearchResult, SearchSource } from "@/types/search"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { isMobileOnly } from "react-device-detect"; import { LuImage, LuSearchX, LuText } from "react-icons/lu"; @@ -145,20 +139,6 @@ export default function SearchView({ const [searchDetail, setSearchDetail] = useState(); - const selectedFilters = useMemo(() => { - const filters = [...DEFAULT_SEARCH_FILTERS]; - - if ( - searchFilter && - (searchFilter?.query?.length || searchFilter?.event_id?.length) - ) { - const index = filters.indexOf("time"); - filters.splice(index, 1); - } - - return filters; - }, [searchFilter]); - // search interaction const [selectedIndex, setSelectedIndex] = useState(null); @@ -336,7 +316,6 @@ export default function SearchView({ "w-full justify-between md:justify-start lg:justify-end", )} filter={searchFilter} - filters={selectedFilters as SearchFilters[]} onUpdateFilter={onUpdateFilter} />