Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish finished reviews to mqtt / ws and use that for source of update banner #10072

Merged
merged 4 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion frigate/review/maintainer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Maintain review segments in db."""

import json
import logging
import os
import random
Expand Down Expand Up @@ -138,7 +139,12 @@ def __init__(self, config: FrigateConfig, stop_event: MpEvent):

def end_segment(self, segment: PendingReviewSegment) -> None:
"""End segment."""
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, segment.end())
seg_data = segment.end()
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data)
self.requestor.send_data(
"reviews",
json.dumps({"type": "end", "review": {k.name: v for k, v in seg_data.items()}}),
)
self.active_review_segments[segment.camera] = None

def update_existing_segment(
Expand Down
11 changes: 9 additions & 2 deletions web/src/api/ws.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { produce, Draft } from "immer";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { FrigateConfig } from "@/types/frigateConfig";
import { FrigateEvent, ToggleableSetting } from "@/types/ws";
import { FrigateEvent, FrigateReview, ToggleableSetting } from "@/types/ws";
import { FrigateStats } from "@/types/stats";

type ReducerState = {
Expand Down Expand Up @@ -218,7 +218,14 @@ export function useRestart(): {
export function useFrigateEvents(): { payload: FrigateEvent } {
const {
value: { payload },
} = useWs(`events`, "");
} = useWs("events", "");
return { payload };
}

export function useFrigateReviews(): { payload: FrigateReview } {
const {
value: { payload },
} = useWs("reviews", "");
return { payload };
}

Expand Down
30 changes: 20 additions & 10 deletions web/src/pages/Events.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useFrigateEvents } from "@/api/ws";
import { useFrigateReviews } from "@/api/ws";
import useApiFilter from "@/hooks/use-api-filter";
import useOverlayState from "@/hooks/use-overlay-state";
import { ReviewFilter, ReviewSegment } from "@/types/review";
import { ReviewFilter, ReviewSegment, ReviewSeverity } from "@/types/review";
import DesktopEventView from "@/views/events/DesktopEventView";
import DesktopRecordingView from "@/views/events/DesktopRecordingView";
import MobileEventView from "@/views/events/MobileEventView";
Expand All @@ -15,6 +15,8 @@ const API_LIMIT = 250;

export default function Events() {
// recordings viewer

const [severity, setSeverity] = useState<ReviewSeverity>("alert");
const [selectedReviewId, setSelectedReviewId] = useOverlayState("review");

// review filter
Expand Down Expand Up @@ -97,6 +99,11 @@ export default function Events() {
setSize(size + 1);
}, [size]);

const reloadData = useCallback(() => {
setSize(1);
updateSegments();
}, [])

// preview videos

const previewTimes = useMemo(() => {
Expand Down Expand Up @@ -196,22 +203,21 @@ export default function Events() {

// review updates

const { payload: eventUpdate } = useFrigateEvents();
const { payload: reviewUpdate } = useFrigateReviews();
const [hasUpdate, setHasUpdate] = useState(false);
useEffect(() => {
if (!eventUpdate) {
if (!reviewUpdate || hasUpdate) {
return;
}

// if event is ended and was saved, update events list
if (
eventUpdate.type == "end" &&
(eventUpdate.after.has_clip || eventUpdate.after.has_snapshot)
reviewUpdate.type == "end" &&
reviewUpdate.review.severity == severity
) {
setHasUpdate(true);
return;
}
}, [eventUpdate]);
}, [reviewUpdate]);

if (selectedData) {
return (
Expand All @@ -229,11 +235,13 @@ export default function Events() {
relevantPreviews={allPreviews}
reachedEnd={isDone}
isValidating={isValidating}
severity={severity}
hasUpdate={hasUpdate}
setSeverity={setSeverity}
setHasUpdate={setHasUpdate}
loadNextPage={onLoadNextPage}
markItemAsReviewed={markItemAsReviewed}
pullLatestData={updateSegments}
pullLatestData={reloadData}
/>
);
}
Expand All @@ -246,12 +254,14 @@ export default function Events() {
reachedEnd={isDone}
isValidating={isValidating}
filter={reviewFilter}
severity={severity}
hasUpdate={hasUpdate}
setSeverity={setSeverity}
setHasUpdate={setHasUpdate}
loadNextPage={onLoadNextPage}
markItemAsReviewed={markItemAsReviewed}
onSelectReview={setSelectedReviewId}
pullLatestData={updateSegments}
pullLatestData={reloadData}
updateFilter={onUpdateFilter}
/>
);
Expand Down
7 changes: 7 additions & 0 deletions web/src/types/ws.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ReviewSegment } from "./review";

type FrigateObjectState = {
id: string;
camera: string;
Expand Down Expand Up @@ -27,6 +29,11 @@ type FrigateObjectState = {
};
};

export interface FrigateReview {
type: "new" | "update" | "end";
review: ReviewSegment;
}

export interface FrigateEvent {
type: "new" | "update" | "end";
before: FrigateObjectState;
Expand Down
5 changes: 4 additions & 1 deletion web/src/views/events/DesktopEventView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ type DesktopEventViewProps = {
reachedEnd: boolean;
isValidating: boolean;
filter?: ReviewFilter;
severity: ReviewSeverity;
hasUpdate: boolean;
setSeverity: (severity: ReviewSeverity) => void;
setHasUpdate: (hasUpdated: boolean) => void;
loadNextPage: () => void;
markItemAsReviewed: (reviewId: string) => void;
Expand All @@ -33,7 +35,9 @@ export default function DesktopEventView({
reachedEnd,
isValidating,
filter,
severity,
hasUpdate,
setSeverity,
setHasUpdate,
loadNextPage,
markItemAsReviewed,
Expand All @@ -42,7 +46,6 @@ export default function DesktopEventView({
updateFilter,
}: DesktopEventViewProps) {
const { data: config } = useSWR<FrigateConfig>("config");
const [severity, setSeverity] = useState<ReviewSeverity>("alert");
const contentRef = useRef<HTMLDivElement | null>(null);

// review paging
Expand Down
5 changes: 4 additions & 1 deletion web/src/views/events/MobileEventView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ type MobileEventViewProps = {
relevantPreviews?: Preview[];
reachedEnd: boolean;
isValidating: boolean;
severity: ReviewSeverity;
hasUpdate: boolean;
setSeverity: (severity: ReviewSeverity) => void;
setHasUpdate: (hasUpdated: boolean) => void;
loadNextPage: () => void;
markItemAsReviewed: (reviewId: string) => void;
Expand All @@ -25,14 +27,15 @@ export default function MobileEventView({
relevantPreviews,
reachedEnd,
isValidating,
severity,
hasUpdate,
setSeverity,
setHasUpdate,
loadNextPage,
markItemAsReviewed,
pullLatestData,
}: MobileEventViewProps) {
const { data: config } = useSWR<FrigateConfig>("config");
const [severity, setSeverity] = useState<ReviewSeverity>("alert");
const contentRef = useRef<HTMLDivElement | null>(null);

// review paging
Expand Down
Loading