From 5385d4d5fd61b80e96c3f313eafd00cfcb15eb00 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Mon, 2 Jan 2023 22:30:21 -0800 Subject: [PATCH] Move some Frigate specific interfaces under the Frigate engine. --- src/camera/frigate/engine-frigate.ts | 4 ++-- src/camera/frigate/requests.ts | 6 ++--- src/camera/frigate/{schema.ts => types.ts} | 25 +++++++++++++++++++ src/camera/frigate/util.ts | 7 ++---- src/camera/types.ts | 5 ++-- src/types.ts | 28 ++-------------------- src/utils/ha/browse-media.ts | 3 +-- src/view-media.ts | 3 +-- src/view.ts | 1 + 9 files changed, 39 insertions(+), 43 deletions(-) rename src/camera/frigate/{schema.ts => types.ts} (61%) diff --git a/src/camera/frigate/engine-frigate.ts b/src/camera/frigate/engine-frigate.ts index d7a955fb..327f9139 100644 --- a/src/camera/frigate/engine-frigate.ts +++ b/src/camera/frigate/engine-frigate.ts @@ -4,7 +4,7 @@ import endOfHour from 'date-fns/endOfHour'; import getUnixTime from 'date-fns/getUnixTime'; import startOfHour from 'date-fns/startOfHour'; import { CAMERA_BIRDSEYE } from '../../const'; -import { CameraConfig, FrigateRecording, RecordingSegment } from '../../types'; +import { CameraConfig, RecordingSegment } from '../../types'; import { MediaQueries, MediaQueriesResults } from '../../view'; import { ViewMedia, ViewMediaClassifier, ViewMediaFactory } from '../../view-media'; import { errorToConsole } from '../../utils/basic'; @@ -31,7 +31,7 @@ import { RecordingQuery, RecordingSegmentsQuery, } from '../types'; -import { RecordingSummary } from './schema'; +import { FrigateRecording, RecordingSummary } from './types'; import { getEvents, getRecordingSegments, getRecordingsSummary, NativeFrigateEventQuery, NativeFrigateRecordingSegmentsQuery, retainEvent } from './requests'; const EVENT_REQUEST_CACHE_MAX_AGE_SECONDS = 60; diff --git a/src/camera/frigate/requests.ts b/src/camera/frigate/requests.ts index 6f119f3a..0675e364 100644 --- a/src/camera/frigate/requests.ts +++ b/src/camera/frigate/requests.ts @@ -2,12 +2,10 @@ import { HomeAssistant } from 'custom-card-helpers'; import { localize } from '../../localize/localize'; import { FrigateCardError, - FrigateEvents, - frigateEventsSchema, RecordingSegment, } from '../../types'; import { homeAssistantWSRequest } from '../../utils/ha'; -import { recordingSegmentsSchema, RecordingSummary, recordingSummarySchema, RetainResult, retainResultSchema } from './schema'; +import { FrigateEvent, frigateEventsSchema, recordingSegmentsSchema, RecordingSummary, recordingSummarySchema, RetainResult, retainResultSchema } from './types'; /** * Get the recordings summary. May throw. @@ -115,7 +113,7 @@ export interface NativeFrigateEventQuery { export const getEvents = async ( hass: HomeAssistant, params?: NativeFrigateEventQuery, -): Promise => { +): Promise => { return await homeAssistantWSRequest( hass, frigateEventsSchema, diff --git a/src/camera/frigate/schema.ts b/src/camera/frigate/types.ts similarity index 61% rename from src/camera/frigate/schema.ts rename to src/camera/frigate/types.ts index 599de6b3..26608e77 100644 --- a/src/camera/frigate/schema.ts +++ b/src/camera/frigate/types.ts @@ -1,5 +1,22 @@ import { z } from 'zod'; +export const eventSchema = z.object({ + camera: z.string(), + end_time: z.number().nullable(), + false_positive: z.boolean().nullable(), + has_clip: z.boolean(), + has_snapshot: z.boolean(), + id: z.string(), + label: z.string(), + start_time: z.number(), + top_score: z.number(), + zones: z.string().array(), + retain_indefinitely: z.boolean().optional(), +}); +export const frigateEventsSchema = eventSchema.array(); + +export type FrigateEvent = z.infer; + const recordingSummaryHourSchema = z.object({ hour: z.preprocess((arg) => Number(arg), z.number().min(0).max(23)), duration: z.number().min(0), @@ -31,3 +48,11 @@ export const retainResultSchema = z.object({ message: z.string(), }); export type RetainResult = z.infer; + +export interface FrigateRecording { + // Frigate camera name (may not be unique) + camera: string; + start_time: number; + end_time: number; + events: number; +} \ No newline at end of file diff --git a/src/camera/frigate/util.ts b/src/camera/frigate/util.ts index 01728b4e..42a8becd 100644 --- a/src/camera/frigate/util.ts +++ b/src/camera/frigate/util.ts @@ -1,11 +1,8 @@ import utcToZonedTime from 'date-fns-tz/utcToZonedTime'; import fromUnixTime from 'date-fns/fromUnixTime'; -import { - ClipsOrSnapshots, - FrigateEvent, - FrigateRecording, -} from '../../types'; +import { ClipsOrSnapshots } from '../../types'; import { formatDateAndTime, prettifyTitle } from '../../utils/basic'; +import { FrigateEvent, FrigateRecording } from './types'; /** * Given an event generate a title. diff --git a/src/camera/types.ts b/src/camera/types.ts index 0cedc17b..159f02db 100644 --- a/src/camera/types.ts +++ b/src/camera/types.ts @@ -1,4 +1,5 @@ -import { FrigateEvents, FrigateRecording, RecordingSegment } from '../types'; +import { RecordingSegment } from '../types'; +import { FrigateEvent, FrigateRecording } from './frigate/types'; // ==== // Base @@ -119,7 +120,7 @@ export interface RecordingSegmentsQueryResults extends QueryResults { export interface FrigateEventQueryResults extends EventQueryResults { engine: Engine.Frigate; - events: FrigateEvents; + events: FrigateEvent[]; } export interface FrigateRecordingQueryResults extends RecordingQueryResults { diff --git a/src/types.ts b/src/types.ts index 67875087..44752342 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,6 +13,7 @@ import { } from 'custom-card-helpers'; import { StyleInfo } from 'lit/directives/style-map.js'; import { z } from 'zod'; +import { eventSchema, FrigateEvent, FrigateRecording } from './camera/frigate/types.js'; import { deepRemoveDefaults } from './utils/zod.js'; // The min allowed size of buttons. @@ -1415,14 +1416,6 @@ export interface BrowseMediaSource { children?: BrowseMediaSource[] | null; } -export interface FrigateRecording { - // Frigate camera name (may not be unique) - camera: string; - start_time: number; - end_time: number; - events: number; -} - export interface FrigateBrowseMediaSource extends BrowseMediaSource { children?: FrigateBrowseMediaSource[] | null; frigate?: { @@ -1432,23 +1425,6 @@ export interface FrigateBrowseMediaSource extends BrowseMediaSource { }; } -export const frigateEventSchema = z.object({ - camera: z.string(), - end_time: z.number().nullable(), - false_positive: z.boolean().nullable(), - has_clip: z.boolean(), - has_snapshot: z.boolean(), - id: z.string(), - label: z.string(), - start_time: z.number(), - top_score: z.number(), - zones: z.string().array(), - retain_indefinitely: z.boolean().optional(), -}); -export type FrigateEvent = z.infer; - -export const frigateEventsSchema = frigateEventSchema.array(); -export type FrigateEvents = z.infer; export const frigateBrowseMediaSourceSchema: z.ZodSchema = z.lazy( () => @@ -1464,7 +1440,7 @@ export const frigateBrowseMediaSourceSchema: z.ZodSchema = z. children: z.array(frigateBrowseMediaSourceSchema).nullable().optional(), frigate: z .object({ - event: frigateEventSchema, + event: eventSchema, }) .optional(), }), diff --git a/src/utils/ha/browse-media.ts b/src/utils/ha/browse-media.ts index 2bece47c..e824e353 100644 --- a/src/utils/ha/browse-media.ts +++ b/src/utils/ha/browse-media.ts @@ -1,5 +1,6 @@ import { HomeAssistant } from 'custom-card-helpers'; import { homeAssistantWSRequest } from '.'; +import { FrigateEvent, FrigateRecording } from '../../camera/frigate/types'; import { dispatchErrorMessageEvent } from '../../components/message.js'; import { localize } from '../../localize/localize.js'; import { @@ -9,8 +10,6 @@ import { ClipsOrSnapshots, FrigateBrowseMediaSource, frigateBrowseMediaSourceSchema, - FrigateEvent, - FrigateRecording, MEDIA_CLASS_PLAYLIST, MEDIA_CLASS_VIDEO, MEDIA_TYPE_PLAYLIST, diff --git a/src/view-media.ts b/src/view-media.ts index b63067bb..67952a7d 100644 --- a/src/view-media.ts +++ b/src/view-media.ts @@ -3,8 +3,6 @@ import isEqual from 'lodash-es/isEqual'; import { BrowseMediaSource, CameraConfig, - FrigateEvent, - FrigateRecording, MEDIA_TYPE_IMAGE, } from './types.js'; import { ModifyInterface } from './utils/basic.js'; @@ -15,6 +13,7 @@ import { getRecordingMediaContentID, getRecordingTitle, } from './camera/frigate/util.js'; +import { FrigateEvent, FrigateRecording } from './camera/frigate/types.js'; export type ViewMediaType = 'clip' | 'snapshot' | 'recording'; export type ViewMediaSourceType = FrigateEvent | FrigateRecording | BrowseMediaSource; diff --git a/src/view.ts b/src/view.ts index 13aac7f8..97779e4a 100644 --- a/src/view.ts +++ b/src/view.ts @@ -20,6 +20,7 @@ // Hard: // - TODO: Implement dragging the timeline seeking forward in both Frigate recordings & events. // - TODO: Implement gallery. +// - TODO: Remove FrigateBrowseMediaSource if not necessary (post-gallery). // - TODO: In generateMediaViewerContext there is an assumption that recordings start/end on the hour, which is true for Frigate but that assumption should be in the engine. // - TODO: What should the timeline do when an event is clicked on that is not in the queryResults (or if queryResults is empty)? // - TODO: Should the timeline data source clear events (as it currently does) when the query changes?