From 5fb2a9d3ed10b5191e6c957f3b5ec1ee08e50c94 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 29 Jan 2023 11:26:48 -0800 Subject: [PATCH] Include metadata from recordings. --- src/camera/frigate/engine-frigate.ts | 41 ++++++++++++++++++++++------ src/components/media-filter.ts | 2 +- src/utils/basic.ts | 9 ++++++ src/view/view.ts | 1 + 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/camera/frigate/engine-frigate.ts b/src/camera/frigate/engine-frigate.ts index 4199c013..5916017a 100644 --- a/src/camera/frigate/engine-frigate.ts +++ b/src/camera/frigate/engine-frigate.ts @@ -48,7 +48,7 @@ import { } from './requests'; import orderBy from 'lodash-es/orderBy'; import throttle from 'lodash-es/throttle'; -import { allPromises, runWhenIdleIfSupported } from '../../utils/basic'; +import { allPromises, formatDate, runWhenIdleIfSupported } from '../../utils/basic'; import { fromUnixTime } from 'date-fns'; import { sum } from 'lodash-es'; import { FrigateViewMediaClassifier } from './media-classifier'; @@ -127,7 +127,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { public generateDefaultEventQuery( cameras: Map, cameraIDs: Set, - query: PartialEventQuery, + query?: PartialEventQuery, ): EventQuery[] | null { const relevantCameraConfigs = Array.from(cameraIDs).map((cameraID) => cameras.get(cameraID), @@ -172,8 +172,8 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { public generateDefaultRecordingQuery( _cameras: Map, cameraIDs: Set, - query: PartialRecordingQuery, - ): RecordingQuery[] | null { + query?: PartialRecordingQuery, + ): RecordingQuery[] { return [ { type: QueryType.Recording, @@ -631,7 +631,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { new Set(cameras.keys()), ); - const processQuery = async ( + const processEventSummary = async ( instanceID: string, cameraIDs: Set, ): Promise => { @@ -654,9 +654,34 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { } }; - await allPromises([...instances.entries()], ([instanceID, cameraIDs]) => - processQuery(instanceID, cameraIDs), - ); + const processRecordings = async ( + cameraIDs: Set): Promise => { + + const recordings = await this.getRecordings(hass, cameras, { + type: QueryType.Recording, + cameraIDs: cameraIDs, + }); + if (!recordings) { + return; + } + + for (const result of recordings.values()) { + if (!FrigateQueryResultsClassifier.isFrigateRecordingQueryResults(result)) { + continue; + } + + for (const recording of result.recordings) { + // Frigate recordings are always 1 hour long, i.e. never span a day. + days.add(formatDate(recording.startTime)); + } + } + } + + await allPromises([...instances.entries()], ([instanceID, cameraIDs]) => (async () => { + await Promise.all([ + processEventSummary(instanceID, cameraIDs), + processRecordings(cameraIDs)]); + })()); if (!what.size && !where.size && !days.size) { return null; diff --git a/src/components/media-filter.ts b/src/components/media-filter.ts index 3e98be31..a3a49c4e 100644 --- a/src/components/media-filter.ts +++ b/src/components/media-filter.ts @@ -257,7 +257,7 @@ export class MediaMetadataController implements ReactiveController { if (metadata.days) { const yearMonths: Set = new Set(); [...metadata.days].forEach((day) => { - // An efficient conversion: 2023-01-26 -> 2023-01 + // An efficient conversion: "2023-01-26" -> "2023-01" yearMonths.add(day.substring(0, 7)); }); const monthStarts: Date[] = []; diff --git a/src/utils/basic.ts b/src/utils/basic.ts index 19ce2cb6..200b3939 100644 --- a/src/utils/basic.ts +++ b/src/utils/basic.ts @@ -116,6 +116,15 @@ export const formatDateAndTime = (date: Date): string => { return format(date, 'yyyy-MM-dd HH:mm'); }; +/** + * Format a date object to RFC3339. + * @param date A Date object. + * @returns A date. + */ +export const formatDate = (date: Date): string => { + return format(date, 'yyyy-MM-dd'); +}; + /** * Run a function in idle periods. If idle callbacks are not supported (e.g. * Safari) the callback is run immediately. diff --git a/src/view/view.ts b/src/view/view.ts index a2fba263..1018831c 100644 --- a/src/view/view.ts +++ b/src/view/view.ts @@ -12,6 +12,7 @@ // - TODO: Make media filter slot choice configurable (gallery.ts). // - TODO: Filter panel expands from right can occasionally 'stick' open. // - TODO: Media type selection, i.e. events or recordings. +// - TODO: Cache every summary. // Hard: // - TODO: Implement gallery.