Include metadata from recordings.

This commit is contained in:
Dermot Duffy
2023-01-29 11:26:48 -08:00
parent 1ad600c231
commit 5fb2a9d3ed
4 changed files with 44 additions and 9 deletions
+33 -8
View File
@@ -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<string, CameraConfig>,
cameraIDs: Set<string>,
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<string, CameraConfig>,
cameraIDs: Set<string>,
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<string>,
): Promise<void> => {
@@ -654,9 +654,34 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
}
};
await allPromises([...instances.entries()], ([instanceID, cameraIDs]) =>
processQuery(instanceID, cameraIDs),
);
const processRecordings = async (
cameraIDs: Set<string>): Promise<void> => {
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;
+1 -1
View File
@@ -257,7 +257,7 @@ export class MediaMetadataController implements ReactiveController {
if (metadata.days) {
const yearMonths: Set<string> = 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[] = [];
+9
View File
@@ -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.
+1
View File
@@ -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.