Add sub_label support.
This commit is contained in:
@@ -448,6 +448,7 @@ export class FrigateCameraManagerEngine
|
||||
cameras: Array.from(this._getFrigateCameraNamesForCameraIDs(cameras, cameraIDs)),
|
||||
...(query.what && { labels: Array.from(query.what) }),
|
||||
...(query.where && { zones: Array.from(query.where) }),
|
||||
...(query.tags && { sub_labels: Array.from(query.tags) }),
|
||||
...(query.end && { before: Math.floor(query.end.getTime() / 1000) }),
|
||||
...(query.start && { after: Math.floor(query.start.getTime() / 1000) }),
|
||||
...(query.limit && { limit: query.limit }),
|
||||
@@ -704,6 +705,7 @@ export class FrigateCameraManagerEngine
|
||||
cameraID,
|
||||
cameraConfig,
|
||||
event,
|
||||
event.sub_label ? this._splitSubLabels(event.sub_label) : undefined,
|
||||
);
|
||||
if (media) {
|
||||
output.push(media);
|
||||
@@ -795,6 +797,16 @@ export class FrigateCameraManagerEngine
|
||||
return cameraConfig;
|
||||
}
|
||||
|
||||
protected _splitSubLabels(input: string): string[] {
|
||||
// A note on Frigate sub_labels: As of Frigate v0.12 sub_labels is a string
|
||||
// (not an array) per event, but may contain comma-separated values (e.g.
|
||||
// double-take (https://github.com/jakowenko/double-take) identifying two
|
||||
// people in the same photo). When we search for multiple sub_labels, the
|
||||
// integration will comma-join them together, then the Frigate backend will
|
||||
// do the magic to match exactly or against a comma-separated part.
|
||||
return input.split(',').map((s) => s.trim());
|
||||
}
|
||||
|
||||
public async getMediaMetadata(
|
||||
hass: HomeAssistant,
|
||||
cameras: CameraConfigs,
|
||||
@@ -814,6 +826,7 @@ export class FrigateCameraManagerEngine
|
||||
const what: Set<string> = new Set();
|
||||
const where: Set<string> = new Set();
|
||||
const days: Set<string> = new Set();
|
||||
const tags: Set<string> = new Set();
|
||||
|
||||
const instances = this._buildInstanceToCameraIDMapFromQuery(
|
||||
cameras,
|
||||
@@ -840,6 +853,9 @@ export class FrigateCameraManagerEngine
|
||||
if (entry.day) {
|
||||
days.add(entry.day);
|
||||
}
|
||||
if (entry.sub_label) {
|
||||
this._splitSubLabels(entry.sub_label).forEach(tags.add, tags);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -880,6 +896,7 @@ export class FrigateCameraManagerEngine
|
||||
...(what.size && { what: what }),
|
||||
...(where.size && { where: where }),
|
||||
...(days.size && { days: days }),
|
||||
...(tags.size && { tags: tags }),
|
||||
},
|
||||
expiry: add(new Date(), { seconds: MEDIA_METADATA_REQUEST_CACHE_AGE_SECONDS }),
|
||||
cached: false,
|
||||
|
||||
@@ -21,6 +21,7 @@ export class FrigateEventViewMedia extends ViewMedia implements EventViewMedia {
|
||||
protected _event: FrigateEvent;
|
||||
protected _contentID: string;
|
||||
protected _thumbnail: string;
|
||||
protected _subLabels: string[] | null;
|
||||
|
||||
constructor(
|
||||
mediaType: ViewMediaType,
|
||||
@@ -28,11 +29,17 @@ export class FrigateEventViewMedia extends ViewMedia implements EventViewMedia {
|
||||
event: FrigateEvent,
|
||||
contentID: string,
|
||||
thumbnail: string,
|
||||
// See 'A note on Frigate sub_labels' in engine-frigate.ts for more
|
||||
// details about why sub-labels are treated specially. By taking in
|
||||
// subLabels as an array here, we can keep a single place that splits
|
||||
// sublabels (`_splitSubLabels` in engine-frigate.ts).
|
||||
subLabels?: string[],
|
||||
) {
|
||||
super(mediaType, cameraID);
|
||||
this._event = event;
|
||||
this._contentID = contentID;
|
||||
this._thumbnail = thumbnail;
|
||||
this._subLabels = subLabels ?? null;
|
||||
}
|
||||
|
||||
public hasClip(): boolean {
|
||||
@@ -72,6 +79,9 @@ export class FrigateEventViewMedia extends ViewMedia implements EventViewMedia {
|
||||
public getScore(): number | null {
|
||||
return this._event.top_score;
|
||||
}
|
||||
public getTags(): string[] | null {
|
||||
return this._subLabels;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public isGroupableWith(that: EventViewMedia): boolean {
|
||||
@@ -130,6 +140,7 @@ export class FrigateViewMediaFactory {
|
||||
cameraID: string,
|
||||
cameraConfig: CameraConfig,
|
||||
event: FrigateEvent,
|
||||
subLabels?: string[],
|
||||
): FrigateEventViewMedia | null {
|
||||
if (
|
||||
(mediaType === 'clip' && !event.has_clip) ||
|
||||
@@ -151,6 +162,7 @@ export class FrigateViewMediaFactory {
|
||||
mediaType === 'clip' ? 'clips' : 'snapshots',
|
||||
),
|
||||
getEventThumbnailURL(cameraConfig.frigate.client_id, event),
|
||||
subLabels,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ const eventSchema = z.object({
|
||||
has_snapshot: z.boolean(),
|
||||
id: z.string(),
|
||||
label: z.string(),
|
||||
sub_label: z.string().nullable(),
|
||||
start_time: z.number(),
|
||||
top_score: z.number(),
|
||||
zones: z.string().array(),
|
||||
@@ -68,6 +69,7 @@ export const eventSummarySchema = z
|
||||
camera: z.string(),
|
||||
day: z.string(),
|
||||
label: z.string(),
|
||||
sub_label: z.string().nullable(),
|
||||
zones: z.string().array(),
|
||||
})
|
||||
.array();
|
||||
|
||||
@@ -279,6 +279,7 @@ export class CameraManager {
|
||||
}
|
||||
|
||||
public async getMediaMetadata(hass: HomeAssistant): Promise<MediaMetadata | null> {
|
||||
const tags: Set<string> = new Set();
|
||||
const what: Set<string> = new Set();
|
||||
const where: Set<string> = new Set();
|
||||
const days: Set<string> = new Set();
|
||||
@@ -291,6 +292,9 @@ export class CameraManager {
|
||||
const results = await this._handleQuery(hass, query);
|
||||
|
||||
for (const result of results?.values() ?? []) {
|
||||
if (result.metadata.tags) {
|
||||
result.metadata.tags.forEach(tags.add, tags);
|
||||
}
|
||||
if (result.metadata.what) {
|
||||
result.metadata.what.forEach(what.add, what);
|
||||
}
|
||||
@@ -306,6 +310,7 @@ export class CameraManager {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...(tags.size && { tags: tags }),
|
||||
...(what.size && { what: what }),
|
||||
...(where.size && { where: where }),
|
||||
...(days.size && { days: days }),
|
||||
|
||||
@@ -84,9 +84,10 @@ export type RecordingSegmentsQueryResultsMap = ResultsMap<RecordingSegmentsQuery
|
||||
export type MediaMetadataQueryResultsMap = ResultsMap<MediaMetadataQuery>;
|
||||
|
||||
export interface MediaMetadata {
|
||||
days?: Set<string>;
|
||||
tags?: Set<string>;
|
||||
where?: Set<string>;
|
||||
what?: Set<string>;
|
||||
days?: Set<string>;
|
||||
}
|
||||
|
||||
interface BaseCapabilities {
|
||||
@@ -145,6 +146,9 @@ export interface EventQuery extends MediaQuery {
|
||||
// Frigate equivalent: label
|
||||
what?: Set<string>;
|
||||
|
||||
// Frigate equivalent: sub_label
|
||||
tags?: Set<string>;
|
||||
|
||||
// Frigate equivalent: zone
|
||||
where?: Set<string>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user