Motion timeline data (#10245)

* Refactor activity api to send motion and audio data

* Prepare for using motion data timeline

* Get working

* reduce to 0

* fix

* Formatting

* fix typing

* add motion data to timelines and allow motion cameas to be selectable

* Fix tests

* cleanup

* Fix not loading preview when changing hours
This commit is contained in:
Nicolas Mowen
2024-03-05 12:55:44 -07:00
committed by GitHub
parent a174d82eb9
commit 9e8a42ca0e
11 changed files with 269 additions and 197 deletions

View File

@@ -240,22 +240,37 @@ export default function Events() {
// selected items
const selectedData = useMemo(() => {
const selectedReviewData = useMemo(() => {
if (!config) {
return undefined;
}
if (!selectedReviewId) {
return undefined;
}
if (!reviewPages) {
return undefined;
}
if (!selectedReviewId) {
return undefined;
}
const allCameras = reviewFilter?.cameras ?? Object.keys(config.cameras);
const allReviews = reviewPages.flat();
if (selectedReviewId.startsWith("motion")) {
const motionData = selectedReviewId.split(",");
// format is motion,camera,start_time
return {
camera: motionData[1],
severity: "significant_motion" as ReviewSeverity,
start_time: parseFloat(motionData[2]),
allCameras: allCameras,
cameraSegments: allReviews.filter((seg) =>
allCameras.includes(seg.camera),
),
};
}
const selectedReview = allReviews.find(
(item) => item.id == selectedReviewId,
);
@@ -265,7 +280,9 @@ export default function Events() {
}
return {
selected: selectedReview,
camera: selectedReview.camera,
severity: selectedReview.severity,
start_time: selectedReview.start_time,
allCameras: allCameras,
cameraSegments: allReviews.filter((seg) =>
allCameras.includes(seg.camera),
@@ -280,12 +297,14 @@ export default function Events() {
return <ActivityIndicator />;
}
if (selectedData) {
if (selectedReviewData) {
if (isMobile) {
return (
<MobileRecordingView
reviewItems={selectedData.cameraSegments}
selectedReview={selectedData.selected}
reviewItems={selectedReviewData.cameraSegments}
startCamera={selectedReviewData.camera}
startTime={selectedReviewData.start_time}
severity={selectedReviewData.severity}
relevantPreviews={allPreviews}
/>
);
@@ -293,11 +312,11 @@ export default function Events() {
return (
<DesktopRecordingView
startCamera={selectedData.selected.camera}
startTime={selectedData.selected.start_time}
allCameras={selectedData.allCameras}
severity={selectedData.selected.severity}
reviewItems={selectedData.cameraSegments}
startCamera={selectedReviewData.camera}
startTime={selectedReviewData.start_time}
allCameras={selectedReviewData.allCameras}
severity={selectedReviewData.severity}
reviewItems={selectedReviewData.cameraSegments}
allPreviews={allPreviews}
/>
);

View File

@@ -4,7 +4,12 @@ import useSWR from "swr";
import { FrigateConfig } from "@/types/frigateConfig";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import EventReviewTimeline from "@/components/timeline/EventReviewTimeline";
import { ReviewData, ReviewSegment, ReviewSeverity } from "@/types/review";
import {
MotionData,
ReviewData,
ReviewSegment,
ReviewSeverity,
} from "@/types/review";
import { Button } from "@/components/ui/button";
import CameraActivityIndicator from "@/components/indicators/CameraActivityIndicator";
import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline";
@@ -53,14 +58,7 @@ function ColorSwatch({ name, value }: { name: string; value: string }) {
);
}
export type MockMotionData = {
start_time: number;
end_time: number;
motionValue: number;
audioValue: number;
};
function generateRandomMotionAudioData(): MockMotionData[] {
function generateRandomMotionAudioData(): MotionData[] {
const now = new Date();
const endTime = now.getTime() / 1000;
const startTime = endTime - 24 * 60 * 60; // 24 hours ago
@@ -72,14 +70,12 @@ function generateRandomMotionAudioData(): MockMotionData[] {
startTimestamp < endTime;
startTimestamp += interval
) {
const endTimestamp = startTimestamp + interval;
const motionValue = Math.floor(Math.random() * 101); // Random number between 0 and 100
const audioValue = Math.random() * -100; // Random negative value between -100 and 0
const motion = Math.floor(Math.random() * 101); // Random number between 0 and 100
const audio = Math.random() * -100; // Random negative value between -100 and 0
data.push({
start_time: startTimestamp,
end_time: endTimestamp,
motionValue,
audioValue,
motion,
audio,
});
}
@@ -126,7 +122,7 @@ function UIPlayground() {
const { data: config } = useSWR<FrigateConfig>("config");
const contentRef = useRef<HTMLDivElement>(null);
const [mockEvents, setMockEvents] = useState<ReviewSegment[]>([]);
const [mockMotionData, setMockMotionData] = useState<MockMotionData[]>([]);
const [mockMotionData, setMockMotionData] = useState<MotionData[]>([]);
const [handlebarTime, setHandlebarTime] = useState(
Math.floor(Date.now() / 1000) - 15 * 60,
);