feat: Add severity media filter (#2323)
This commit is contained in:
@@ -6,12 +6,12 @@ import { CameraConfig } from '../../config/schema/cameras';
|
||||
import { Entity, EntityRegistryManager } from '../../ha/registry/entity/types';
|
||||
import { HomeAssistant } from '../../ha/types';
|
||||
import { localize } from '../../localize/localize';
|
||||
import { SEVERITIES } from '../../severity';
|
||||
import {
|
||||
CapabilitiesRaw,
|
||||
Endpoint,
|
||||
PTZCapabilities,
|
||||
PTZMovementType,
|
||||
SEVERITIES,
|
||||
} from '../../types';
|
||||
import { errorToConsole } from '../../utils/basic';
|
||||
import { Camera, CameraInitializationOptions } from '../camera';
|
||||
|
||||
@@ -62,7 +62,6 @@ import { FrigateViewMediaClassifier } from './media-classifier';
|
||||
import {
|
||||
NativeFrigateEventQuery,
|
||||
NativeFrigateRecordingSegmentsQuery,
|
||||
NativeFrigateReviewQuery,
|
||||
getEventSummary,
|
||||
getEvents,
|
||||
getRecordingSegments,
|
||||
@@ -86,7 +85,7 @@ const RECORDING_SUMMARY_REQUEST_CACHE_MAX_AGE_SECONDS = 60;
|
||||
const MEDIA_METADATA_REQUEST_CACHE_AGE_SECONDS = 60;
|
||||
const REVIEW_REQUEST_CACHE_MAX_AGE_SECONDS = 60;
|
||||
|
||||
class FrigateQueryResultsClassifier {
|
||||
export class FrigateQueryResultsClassifier {
|
||||
public static isFrigateEventQueryResults(
|
||||
results: QueryResults,
|
||||
): results is FrigateEventQueryResults {
|
||||
@@ -484,7 +483,14 @@ export class FrigateCameraManagerEngine
|
||||
query: ReviewQuery,
|
||||
engineOptions?: EngineOptions,
|
||||
): Promise<ReviewQueryResultsMap | null> {
|
||||
if (hasUnsupportedFilters(query, { what: true, where: true, reviewed: true })) {
|
||||
if (
|
||||
hasUnsupportedFilters(query, {
|
||||
what: true,
|
||||
where: true,
|
||||
reviewed: true,
|
||||
severity: true,
|
||||
})
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -505,23 +511,36 @@ export class FrigateCameraManagerEngine
|
||||
return;
|
||||
}
|
||||
|
||||
const nativeQuery: NativeFrigateReviewQuery = {
|
||||
instance_id: instanceID,
|
||||
cameras: Array.from(this._getFrigateCameraNamesForCameraIDs(store, cameraIDs)),
|
||||
...(query.what && { labels: Array.from(query.what) }),
|
||||
...(query.where && { zones: Array.from(query.where) }),
|
||||
...(query.end && { before: Math.floor(query.end.getTime() / 1000) }),
|
||||
...(query.start && { after: Math.floor(query.start.getTime() / 1000) }),
|
||||
...(query.limit && { limit: query.limit }),
|
||||
...(query.severity && { severity: FRIGATE_SEVERITY_MAP[query.severity] }),
|
||||
...(query.reviewed !== undefined && { reviewed: query.reviewed }),
|
||||
};
|
||||
const severities = query.severity?.size ? Array.from(query.severity) : [undefined];
|
||||
|
||||
// Frigate only supports querying for a single severity, so we generate
|
||||
// multiple queries and combine the results.
|
||||
const reviewPromises = severities
|
||||
// Frigate does not support a 'low' severity.
|
||||
.filter((severity) => severity !== 'low')
|
||||
.map((severity) => (!!severity ? FRIGATE_SEVERITY_MAP[severity] : undefined))
|
||||
.map(
|
||||
async (frigateSeverity) =>
|
||||
await getReviews(hass, {
|
||||
instance_id: instanceID,
|
||||
cameras: Array.from(
|
||||
this._getFrigateCameraNamesForCameraIDs(store, cameraIDs),
|
||||
),
|
||||
...(query.what && { labels: Array.from(query.what) }),
|
||||
...(query.where && { zones: Array.from(query.where) }),
|
||||
...(query.end && { before: Math.floor(query.end.getTime() / 1000) }),
|
||||
...(query.start && { after: Math.floor(query.start.getTime() / 1000) }),
|
||||
...(query.limit && { limit: query.limit }),
|
||||
severity: frigateSeverity,
|
||||
...(query.reviewed !== undefined && { reviewed: query.reviewed }),
|
||||
}),
|
||||
);
|
||||
|
||||
const result: FrigateReviewQueryResults = {
|
||||
type: QueryResultsType.Review,
|
||||
engine: Engine.Frigate,
|
||||
instanceID: instanceID,
|
||||
reviews: await getReviews(hass, nativeQuery),
|
||||
reviews: (await Promise.all(reviewPromises)).flat(),
|
||||
expiry: add(new Date(), { seconds: REVIEW_REQUEST_CACHE_MAX_AGE_SECONDS }),
|
||||
cached: false,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { fromUnixTime } from 'date-fns';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { CameraConfig } from '../../config/schema/cameras';
|
||||
import { Severity } from '../../types';
|
||||
import { Severity } from '../../severity';
|
||||
import {
|
||||
EventViewMedia,
|
||||
RecordingViewMedia,
|
||||
|
||||
@@ -181,7 +181,7 @@ export const getPTZInfo = async (
|
||||
);
|
||||
};
|
||||
|
||||
export interface NativeFrigateReviewQuery {
|
||||
interface NativeFrigateReviewQuery {
|
||||
instance_id: string;
|
||||
cameras?: string[];
|
||||
labels?: string[];
|
||||
|
||||
@@ -146,7 +146,6 @@ export interface FrigateRecordingSegmentsQueryResults
|
||||
export const FRIGATE_SEVERITY_MAP = {
|
||||
high: 'alert',
|
||||
medium: 'detection',
|
||||
low: 'significant_motion',
|
||||
} as const;
|
||||
|
||||
export type FrigateReviewSeverity =
|
||||
@@ -170,7 +169,7 @@ const frigateReviewDataSchema = z.object({
|
||||
const frigateReviewSchema = z.object({
|
||||
id: z.string(),
|
||||
camera: z.string(),
|
||||
severity: z.enum(['alert', 'detection', 'significant_motion']),
|
||||
severity: z.enum(['alert', 'detection']),
|
||||
start_time: z.number(),
|
||||
end_time: z.number().nullable(),
|
||||
thumb_path: z.string().nullable(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { toZonedTime } from 'date-fns-tz';
|
||||
import { CameraConfig } from '../../config/schema/cameras';
|
||||
import { Severity } from '../../types';
|
||||
import { Severity } from '../../severity';
|
||||
import { formatDateAndTime, prettifyTitle } from '../../utils/basic';
|
||||
import {
|
||||
FrigateEvent,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ExpiringEqualityCache } from '../cache/expiring-cache';
|
||||
import { SSLCiphers } from '../config/schema/cameras';
|
||||
import { AdvancedCameraCardView } from '../config/schema/common/const';
|
||||
import { BaseQuery, QueryFilters, QuerySource } from '../query-source';
|
||||
import { CapabilityKey, Endpoint, Icon, Severity } from '../types';
|
||||
import { CapabilityKey, Endpoint, Icon } from '../types';
|
||||
import { ViewMedia } from '../view/item';
|
||||
|
||||
// ====
|
||||
@@ -252,8 +252,6 @@ export interface MediaMetadataQueryResults extends QueryResults {
|
||||
|
||||
export interface ReviewQuery extends MediaQuery {
|
||||
type: QueryType.Review;
|
||||
|
||||
severity?: Severity;
|
||||
}
|
||||
export type PartialReviewQuery = Partial<ReviewQuery>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user